DateDiff() result differs on 1st run and succeeding runs?
For example I key in tomorrow's date in the dtpBirthdate control, I'm expecting to immediately get 1 as a result in the following code:
Code:
DateDiff(DateInterval.Day, Date.Now.Date, dtpBirthdate.Value.Date)
However, I'm getting 0 on the first run, and then the correct answer on the next instance of execution ie: pressing Validate button once will return 0, and pressing it again will get 1 (without changing the values on the DateTimePicker).
This is the only one that's bugged in the code (as of now) and it's also affecting the validation process (ie: when user gives the correct value, they'd have to validate another time to pass the validation) and the error provider. Anyone have any ideas?
Code:
Private Sub InvalidDate()
Dim dateErrNIS As String = ""
Dim dateErrCOL As String = ""
If DateDiff(DateInterval.Day, Date.Now.Date, dtpBirthdate.Value.Date) > 0 Then
HighlightError(dtpBirthdate, emDateNow)
Else
If DateDiff(DateInterval.Day, dtpBirthdate.Value.Date, dtpAdmission.Value.Date) < 0 Then
HighlightError(dtpAdmission, emDatePx)
Else
If DateDiff(DateInterval.Day, dtpAdmission.Value.Date, dtpHAIAcquired.Value.Date) < 1 Then
dateErrNIS = dateErrNIS & emDateAdm
End If
If DateDiff(DateInterval.Day, dtpAdmission.Value.Date, dtpCollection.Value.Date) < 1 Then
dateErrCOL = dateErrCOL & emDateAdm
End If
If DateDiff(DateInterval.Day, dtpBirthdate.Value.Date, dtpHAIAcquired.Value.Date) < 0 Then
dateErrNIS = dateErrNIS & emDatePx
End If
If DateDiff(DateInterval.Day, dtpBirthdate.Value.Date, dtpCollection.Value.Date) < 0 Then
dateErrCOL = dateErrCOL & emDatePx
End If
End If
End If
If Not dateErrNIS = "" Then HighlightError(dtpHAIAcquired, dateErrNIS)
If Not dateErrCOL = "" Then HighlightError(dtpCollection, dateErrCOL)
End Sub
Re: DateDiff() result differs on 1st run and succeeding runs?
Put a breakpoint on the line and see what is in each value. My guess would be that dtpBirthdate.Value.Date doesn't contain what you think.
Re: DateDiff() result differs on 1st run and succeeding runs?
That would be my guess, as well. It's also the most straightforward way to approach this problem. Until you see what is in the arguments, you are kind of guessing at what the problem is. Once you see what is in the arguments you will probably know why the comparison is failing, even if not being quite sure how to solve it.
It seems like a somewhat archaic approach, though. I may be wrong about this, but isn't DateDiff a legacy function from VB6? What I would do would be to subtract the dates to get a TimeSpan and look at the TotalDays member:
Math.Abs((Date.Now.Date - dtp.Value.Date).TotalDays) > 0
I don't know what the performance difference might be, but this won't solve the problem if those variables don't hold what you think they should hold.
Re: DateDiff() result differs on 1st run and succeeding runs?
What does HighlightError do?
Re: DateDiff() result differs on 1st run and succeeding runs?
I'm adding a third hunch the DateTimePickers aren't unchanged like you think. Here's some other thoughts.
You say you expect a 1 or a 0, but when I read over your code I don't see how you decide you're getting a 1 or a 0. The only side effect of this code I see is you call HighlightError() with the results of concatenating some strings. That, in and of itself, seems really weird.
I can only guess that, for certain inputs, you're not getting the result you expect. But your If statements confuse me. Some of this is because DateDiff() is unfamiliar, it's not part of the average .NET developer's toolbox. I think you could probably restructure your code to accomplish the same thing with clearer techniques.
For example:
Code:
If DateDiff(DateInterval.Day, Date.Now.Date, dtpBirthdate.Value.Date) > 0 Then
I think this says, "If there are a positive number of days between Date.Now and the given birthday..." The sense of this is, "I want to know if the birthdate is earlier than today." You can more clearly state this like so:
Code:
If Date.Now < dtpBirthdate.Value.Date Then
That's closer to the intent. "If today is less than the birthday..." is a lot better than "If calling DateDiff() given these parameters gives a value greater than one..."
Consider dropping DateDiff() from your toolbox and adopting this technique of comparing dates. "If date1 < date2 Then" is easier to type and maintain than "If DateDiff(DateInterval.Day, date1, date2) < 0". Maybe that'll make this bug go away. But part of me doubts it, I think there's probably some odd interaction with the pickers you haven't anticipated. For example, if HighlightError() changes one of the values, even slightly, it could impact the behavior.
1 Attachment(s)
Re: DateDiff() result differs on 1st run and succeeding runs?
Hi guys! Thanks so much for the input.
Quote:
Originally Posted by
dbasnett
Put a breakpoint on the line and see what is in each value. My guess would be that dtpBirthdate.Value.Date doesn't contain what you think.
I checked the values of the DateTimePickers and tried changing one of them and upon checking, the supposedly changed value didn't change until I ran the code another time. If that's the case, then I wouldn't be able to save the correct data from the DateTimePickers. Does anyone know how to fix this?
This is basically what's happening:
Attachment 139249
When I change the value from the DateTimePicker's current value and run the code, it doesn't get the correct value right away. Only if I keep that DateTimePicker's value unchanged and run the code again does it get the correct value.
Quote:
Originally Posted by Sitten Spyne
I think this says, "If there are a positive number of days between Date.Now and the given birthday..." The sense of this is, "I want to know if the birthdate is earlier than today." You can more clearly state this like so:
Code:
If Date.Now < dtpBirthdate.Value.Date Then
That's closer to the intent. "If today is less than the birthday..." is a lot better than "If calling DateDiff() given these parameters gives a value greater than one..."
This works fine, however if I'm not able to get the correct values at first go, I wouldn't be able to truly check if the values are correct or not.
HighlightError() posts to the error provider:
Code:
Private Sub HighlightError(_Control As Control, ErrorString As String, Optional _Label As Control = Nothing)
If Not _Label Is Nothing Then
errNIS.SetError(_Label, ErrorString)
errNIS.SetIconPadding(_Label, 2)
Else
errNIS.SetError(_Control, ErrorString)
errNIS.SetIconPadding(_Control, 2)
End If
End Sub
Private Sub ClearError()
_list.Clear()
GetChildren(Me)
For Each ctrl As Control In Me.Controls
errNIS.SetError(ctrl, String.Empty)
Next
errNIS.Clear()
End Sub
Is there any other way for me to fetch the data from the DateTimePickers correctly aside from getting the DateTimePicker.value though?
Re: DateDiff() result differs on 1st run and succeeding runs?
I'm trying out other things at the moment, and correct me if I'm wrong, the value of the DateTimePicker doesn't get updated unless you remove focus from the DateTimePicker control? Could that be the reason why the other dates are not being updated? I was under the impression that the date would be updated every time I make a change in the control itself, like in a TextBox.
Tried the DTP_ValueChanged with a Msgbox and the Msgbox was triggered only after I removed focus from the DTP. Was expecting the Msgbox to be triggered each time I keyed in something on the DTP.
I usually invoke the btnSave_Click with a keyboard shortcut (eg: ALT+S), if say, I'm still on the DateTimePicker and press ALT+S, that would mean the data from the DateTimePicker will not be updated unless I click somewhere else or just click the save button itself.
Re: DateDiff() result differs on 1st run and succeeding runs?
The example given here might help prove your theory of when the value is actually updated.
Re: DateDiff() result differs on 1st run and succeeding runs?
It's expected that the value won't change until focus is lost (or maybe Enter is pressed). This is (probably) because more so than the TextBox, it's easy to type invalid values, and people like to add validation to change handlers, but you have to be able to type certain invalid dates to reach a valid date.
I don't like calling a click event handler directly, but that's a waste of time to discuss right now as I'm pretty sure that's not the problem.
What surprises me is using the keyboard shortcut doesn't cause the value update process to happen. So I made a quick test app to try it out. You're right. I didn't work very hard at trying to figure out the exact rules, but if you're typing dates in there's only a few things that cause the DateTimePicker to accept a new value. I'd hoped to find a method to tell it to accept the new value, but there's not, so something a little jankier will have to do.
The best I can come up with, after creating some more confusing situations, is that the value DOES change in response to the button being clicked, but due to the way event handlers happen in .NET it changes after the button is clicked. Let's talk about some weird-as-heck behavior.
Basically, the value doesn't change until some part of the "raise the ValueChanged event" process completes. Because of how events work in Windows, that normally can't happen until AFTER the button click. The intuitive sequence would be like:
Code:
* The button is clicked, a click event goes in the queue.
* The button gains focus, its gain focus event and the DTP's lose focus event goes in the queue.
* The button click handler executes.
* The DTP's lose focus event handler executes, the value is updated.
* The button's gain focus event handler executes.
But my debugging seemed to suggest the order was "Value changed, click", but that the click handler was seeing the wrong value. Stranger, if I used the debugger, I could see the right value at certain times. Stranger still, my message boxes were displaying in a different order than I saw them called. What was happening? Well, here's the code I was looking at:
Code:
Public Class Form1
Private Sub DateTimePicker1_ValueChanged(sender As Object, e As EventArgs) Handles DateTimePicker1.ValueChanged
Debug.WriteLine("<valueChanged>")
MessageBox.Show($"Value changed: {DateTimePicker1.Value}")
Debug.WriteLine("</valueChanged>")
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Debug.WriteLine("<click>")
Dim theDate As DateTime = DateTimePicker1.Value
MessageBox.Show("Button Click: " & theDate.ToString())
Debug.WriteLine("</click>")
End Sub
End Class
It turns out MessageBox.Show() does something like Application.DoEvents() as part of its execution. So what really ends up happening is:
Code:
* The button is 'clicked' via the shortcut. Its Click handler goes in the queue.
* The button gains focus, the DTP loses focus.
* The button's Click handler executes.
* The MessageBox.Show() call fetches the DTP value, which hasn't changed yet.
* MessageBox.Show() causes the event queue to run:
* The DTP 'lose focus' event handler runs, and updates the DTP value.
* The ValueChanged event is raised, and shows its MessageBox().
* The Click message box is displayed, with the old value it fetched before the DTP value updated.
The answer seemed obvious: add an Application.DoEvents() so the DTP can focus, right? Well, that didn't work. And I'm not sure why. I also tried some goofy things like scheduling a worker thread to eventually call the MessageBox.Show after some delay. Everything seemed to point to "The focus has to actually change, and the Alt+S shortcut doesn't do that."
This is what I tried that worked. It's janky, but whatever:
Code:
Public Class Form1
Private Sub DateTimePicker1_ValueChanged(sender As Object, e As EventArgs) Handles DateTimePicker1.ValueChanged
MessageBox.Show($"Value changed: {DateTimePicker1.Value}")
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.Focus()
DateTimePicker1.Focus()
MessageBox.Show($"Click: {DateTimePicker1.Value}")
End Sub
End Class
I feel like this is almost a bug in the DateTimePicker.
Re: DateDiff() result differs on 1st run and succeeding runs?
That's pretty interesting. I've never seen this happen before, and now that I think about it, I'm not at all surprised. I don't believe that I have EVER validated a date right after it was entered. Whenever I have a DTP, the validation, if there even was any, wasn't done until considerably later.
Re: DateDiff() result differs on 1st run and succeeding runs?
Quote:
Originally Posted by
Shaggy Hiker
That's pretty interesting. I've never seen this happen before, and now that I think about it, I'm not at all surprised. I don't believe that I have EVER validated a date right after it was entered. Whenever I have a DTP, the validation, if there even was any, wasn't done until considerably later.
When in doubt there is always Me.ValidateChildren() I guess.