4

We have a VB.NET application installed on a customer's PC running XP, on which it appears that DateTime.ToLocalTime() has stopped working.

The problem first manifested itself in August 2013.

The customer is based in Texas, and their timezone is correct.

The documentation for DateTime.ToLocalTime() has the following interesting note:

On Windows XP systems, the ToLocalTime method recognizes only the current adjustment rule when converting from UTC to local time. As a result, conversions for periods before the current adjustment rule came into effect may not accurately reflect the difference between UTC and local time.

Therfore it appears likely that a timezone rule change was introduced in the August Windows Update, which has caused this.

I've found the following: http://support.microsoft.com/kb/2863058 which indicates that a cumulative timezone update was applied in August 2013, but no USA rules seem to be implicated in this change.

Has anyone else had experience of this problem, and (of course) a solution?

Edit

To clarify a bit. The times in question are stored in UTC in a SQL database, and we're converting to LocalTime for display. It's the display which is causing the problem.

Events which were recorded at 1500 localtime are now showing as recorded at 2100.

James Lavery
  • 920
  • 4
  • 25

2 Answers2

2

Will you be able to recode the product for the client?

You can use the Format function or the DateTime.Now, which gives you the date and time details of the local computer

Here give it a try:

        Textbox1.text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt") 
        Textbox1.Text = Format(now, "yyyy-MM-dd hh:mm:ss")

you can change the date time details inside the string, just remember y=year, M=month, d=day, h=hour, m=minute, s=seconds.

If you have a back end database though, I'd recommend getting the time from it. (which would depend on the database)

Malcolm Salvador
  • 1,476
  • 2
  • 21
  • 40
  • 1
    That should be `DateTime.Now` – Matt Wilko Nov 20 '13 at 09:10
  • Thanks - we can't recode (not right now), as it's an FDA approved system (ulp!) which needs complete validation on every release. I'm just about to code a test application to check what the behaviour/settings are - along the lines of your suggestion. We're storing all times as UTC in the database, and converting to localtime for display. – James Lavery Nov 20 '13 at 09:14
  • @Matt I edited my answer to also include your suggestion sir. – Malcolm Salvador Nov 20 '13 at 09:15
0

This is just a guess, since you didn't show any code. (Please show code in your questions, it makes it much easier to help!)

Texas is currently in Central Standard Time, which is UTC-6. Since there are 6 hours difference between the times you reported (1500, 2100), my guess is that you are converting twice somehow.

This shouldn't happen under normal conditions, thanks to the .Kind property attached to the DateTime. For example:

DateTime dt1 = new DateTime(2013, 11, 22, 3, 0, 0, DateTimeKind.Utc);
Debug.WriteLine("{0:HH:mm} ({1})", dt1, dt1.Kind);  // 3:00 (Utc)

DateTime dt2 = dt1.ToLocalTime();
Debug.WriteLine("{0:HH:mm} ({1})", dt2, dt2.Kind);  // 21:00 (Local)

DateTime dt3 = dt2.ToLocalTime();
Debug.WriteLine("{0:HH:mm} ({1})", dt3, dt3.Kind);  // 21:00 (Local)

But if somehow you loose track of the kind and it is set back to "unspecified", then the double conversion can happen:

DateTime dt1 = new DateTime(2013, 11, 22, 3, 0, 0, DateTimeKind.Utc);
Debug.WriteLine("{0:HH:mm} ({1})", dt1, dt1.Kind);  // 3:00 (Utc)

DateTime dt2 = dt1.ToLocalTime();
Debug.WriteLine("{0:HH:mm} ({1})", dt2, dt2.Kind);  // 21:00 (Local)

// somehow, the kind is getting set back to unspecified in your code
dt2 = DateTime.SpecifyKind(dt2, DateTimeKind.Unspecified);

DateTime dt3 = dt2.ToLocalTime();
Debug.WriteLine("{0:HH:mm} ({1})", dt3, dt3.Kind);  // 15:00 (Local)

Now, it's unlikely that you are actually calling DateTime.SpecifyKind. Instead, I'd be looking in your code for some place where you store the local time back to the DB instead of the UTC time.

Or it could be that you convert the local DateTime to a string and read it back to another DateTime by parsing that string. That can happen in UI code. Perhaps you need to specify Local kind when gathering from a user on a form?

You should debug your code and step through so you can see how it is being transformed. I think then you will find the answer.

No, nothing happened in the Aug 2013 Windows Time Zone update that would affect the United States. The last DST change in the US was in 2007. Even then, you would be off by 1 hour, not 6.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Sorry, I just realized you tagged your post as VB.net, but this should still apply if you are using `System.DateTime` from the .net framework. (VB.net's `Date` type is just an alias to there.) – Matt Johnson-Pint Nov 22 '13 at 05:02