DateTime Class shows wrong time when Time Zone is changed

D

Dave Hall

If the time zone is changed on my CE 4.1 device, or in the VS 2003 emulator
while my application is running, the DateTime class in the .NET CF does not
correctly report the current local time Here's how to reproduce the
problem: Compile & run the code shown below then change the time zone
through the standard date/time control panel applet while the application is
running. Notice that the clock in the system tray is quickly adjusted to
correspond to the new time zone, and the value returned by P/Invoking
GetLocalTime() in my application also reflects the change, but
System.DateTime.Now does not reflect the new time zone unless I stop and
restart the application. I haven't tried to see if a new thread that's
started after the timezone change would show the correct time or not,
although I'm curious about that too. If I change the external dll reference
per the comment, and run the same code on my W2K workstation with the full
..NET framework, I don't have any problem with the DateTime failing to adjust
to a timezone change, so it seems to be a CF bug. Since I am using
Console.WriteLine, the app below won't display on a PPC, so I don't know if
it has the same problem. I haven't bothered to rewrite it for the PPC since
my target is a specific CE device. My CE application needs to be able to
handle changing time zones while running, and I don't want to change every
reference to DateTime.Now to P/Invoke GetLocalTime() if I can help it, so I
have four questions:

1) Can someone try this code on a CE .NET 4.2 CF device and let me know if
it's fixed in 4.2?
2) Does anyone know if this is a known and documented bug in the CF?
2) Does anyone know if any service packs for Version 4.1 of the CF that
specifically mention and resolve this problem?
3) Does anyone know of any simple programatic work arounds other than
replacing DateTime.Now with GetLocalTime()?

Thanks,
Dave

Here's the offending code. It's pretty short.
==============================================================
using System;
using System.Runtime.InteropServices;

namespace RTCTest
{
public class ClockTest
{
static void Main()
{
SYSTEMTIME systemTime = new SYSTEMTIME();
for(int i=0; i<300; i++)
{
SYSTEMTIME.GetLocalTime(ref systemTime);
Console.WriteLine("DateTime = {0} \t GetLocalTime = {1}",
System.DateTime.Now.ToString("G"),
systemTime.ToString());
System.Threading.Thread.Sleep(1000);
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public UInt16 Year;
public UInt16 Month;
public UInt16 DayOfWeek;
public UInt16 Day;
public UInt16 Hour;
public UInt16 Minute;
public UInt16 Second;
public UInt16 Millisecond;

public override string ToString()
{
return String.Format(@"{0}/{1}/{2,4:D4} {3}:{4,2:D2}:{5,2:D2} {6}",
this.Month,
this.Day,
this.Year,
(((this.Hour + 11) % 12) + 1),
this.Minute,
this.Second,
(this.Hour < 12) ? "AM" : "PM");
}
// use Kernel32.dll for full .NET or coredll.dll for .NET CF
// [DllImport("Kernel32.dll", EntryPoint="GetLocalTime",
SetLastError=true)]
[DllImport("coredll.dll", EntryPoint="GetLocalTime", SetLastError=true)]
public extern static void GetLocalTime(ref SYSTEMTIME systemTime);
}
}
 
A

Alex Feinman [MVP]

We have discussed it about a year ago here. Take a look at:
http://groups.google.com/groups?hl=...man+datetime&hl=en&lr=&ie=UTF-8&start=20&sa=N


--
Alex Feinman
---
Visit http://www.opennetcf.org
Dave Hall said:
If the time zone is changed on my CE 4.1 device, or in the VS 2003 emulator
while my application is running, the DateTime class in the .NET CF does not
correctly report the current local time Here's how to reproduce the
problem: Compile & run the code shown below then change the time zone
through the standard date/time control panel applet while the application is
running. Notice that the clock in the system tray is quickly adjusted to
correspond to the new time zone, and the value returned by P/Invoking
GetLocalTime() in my application also reflects the change, but
System.DateTime.Now does not reflect the new time zone unless I stop and
restart the application. I haven't tried to see if a new thread that's
started after the timezone change would show the correct time or not,
although I'm curious about that too. If I change the external dll reference
per the comment, and run the same code on my W2K workstation with the full
.NET framework, I don't have any problem with the DateTime failing to adjust
to a timezone change, so it seems to be a CF bug. Since I am using
Console.WriteLine, the app below won't display on a PPC, so I don't know if
it has the same problem. I haven't bothered to rewrite it for the PPC since
my target is a specific CE device. My CE application needs to be able to
handle changing time zones while running, and I don't want to change every
reference to DateTime.Now to P/Invoke GetLocalTime() if I can help it, so I
have four questions:

1) Can someone try this code on a CE .NET 4.2 CF device and let me know if
it's fixed in 4.2?
2) Does anyone know if this is a known and documented bug in the CF?
2) Does anyone know if any service packs for Version 4.1 of the CF that
specifically mention and resolve this problem?
3) Does anyone know of any simple programatic work arounds other than
replacing DateTime.Now with GetLocalTime()?

Thanks,
Dave

Here's the offending code. It's pretty short.
==============================================================
using System;
using System.Runtime.InteropServices;

namespace RTCTest
{
public class ClockTest
{
static void Main()
{
SYSTEMTIME systemTime = new SYSTEMTIME();
for(int i=0; i<300; i++)
{
SYSTEMTIME.GetLocalTime(ref systemTime);
Console.WriteLine("DateTime = {0} \t GetLocalTime = {1}",
System.DateTime.Now.ToString("G"),
systemTime.ToString());
System.Threading.Thread.Sleep(1000);
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public UInt16 Year;
public UInt16 Month;
public UInt16 DayOfWeek;
public UInt16 Day;
public UInt16 Hour;
public UInt16 Minute;
public UInt16 Second;
public UInt16 Millisecond;

public override string ToString()
{
return String.Format(@"{0}/{1}/{2,4:D4} {3}:{4,2:D2}:{5,2:D2} {6}",
this.Month,
this.Day,
this.Year,
(((this.Hour + 11) % 12) + 1),
this.Minute,
this.Second,
(this.Hour < 12) ? "AM" : "PM");
}
// use Kernel32.dll for full .NET or coredll.dll for .NET CF
// [DllImport("Kernel32.dll", EntryPoint="GetLocalTime",
SetLastError=true)]
[DllImport("coredll.dll", EntryPoint="GetLocalTime", SetLastError=true)]
public extern static void GetLocalTime(ref SYSTEMTIME systemTime);
}
}
 
D

Dave Hall

Thanks Alex. I didn't expect a response so quickly, and so perfectly on
target.

Based on the work around in the article you referenced, I was able to add
the following line inside my for() loop:
typeof(TimeZone).GetField("currentTimeZone",
BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance).SetValue(n
ull, null);

That did the trick in my test app. In my production app, I already use
CeRunAppAtEvent(NE_TZ_CHANGE, myEvent) to hook the system timezone change
event. I should be able to add that same line in the event handler for the
notification, and it should fix the problem without changing every other
call to DateTime.Now, or calling the code above unnecessarily from anywhere
else.

That answers questions 2 and 4. Does anyone know if this problem has been
resolved in any of the newer releases of CE.NET or and service packs? It's
apparently only a problem in the Compact Framework, not the full .NET
Framework.

Thanks,
Dave



Alex Feinman said:
We have discussed it about a year ago here. Take a look at:
http://groups.google.com/groups?hl=...man+datetime&hl=en&lr=&ie=UTF-8&start=20&sa=N


--
Alex Feinman
---
Visit http://www.opennetcf.org
Dave Hall said:
If the time zone is changed on my CE 4.1 device, or in the VS 2003 emulator
while my application is running, the DateTime class in the .NET CF does not
correctly report the current local time Here's how to reproduce the
problem: Compile & run the code shown below then change the time zone
through the standard date/time control panel applet while the
application
is
running. Notice that the clock in the system tray is quickly adjusted to
correspond to the new time zone, and the value returned by P/Invoking
GetLocalTime() in my application also reflects the change, but
System.DateTime.Now does not reflect the new time zone unless I stop and
restart the application. I haven't tried to see if a new thread that's
started after the timezone change would show the correct time or not,
although I'm curious about that too. If I change the external dll reference
per the comment, and run the same code on my W2K workstation with the full
.NET framework, I don't have any problem with the DateTime failing to adjust
to a timezone change, so it seems to be a CF bug. Since I am using
Console.WriteLine, the app below won't display on a PPC, so I don't know if
it has the same problem. I haven't bothered to rewrite it for the PPC since
my target is a specific CE device. My CE application needs to be able to
handle changing time zones while running, and I don't want to change every
reference to DateTime.Now to P/Invoke GetLocalTime() if I can help it,
so
I
have four questions:

1) Can someone try this code on a CE .NET 4.2 CF device and let me know if
it's fixed in 4.2?
2) Does anyone know if this is a known and documented bug in the CF?
3) Does anyone know if any service packs for Version 4.1 of the CF that
specifically mention and resolve this problem?
4) Does anyone know of any simple programatic work arounds other than
replacing DateTime.Now with GetLocalTime()?

Thanks,
Dave

Here's the offending code. It's pretty short.
==============================================================
using System;
using System.Runtime.InteropServices;

namespace RTCTest
{
public class ClockTest
{
static void Main()
{
SYSTEMTIME systemTime = new SYSTEMTIME();
for(int i=0; i<300; i++)
{
SYSTEMTIME.GetLocalTime(ref systemTime);
Console.WriteLine("DateTime = {0} \t GetLocalTime = {1}",
System.DateTime.Now.ToString("G"),
systemTime.ToString());
System.Threading.Thread.Sleep(1000);
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public UInt16 Year;
public UInt16 Month;
public UInt16 DayOfWeek;
public UInt16 Day;
public UInt16 Hour;
public UInt16 Minute;
public UInt16 Second;
public UInt16 Millisecond;

public override string ToString()
{
return String.Format(@"{0}/{1}/{2,4:D4} {3}:{4,2:D2}:{5,2:D2} {6}",
this.Month,
this.Day,
this.Year,
(((this.Hour + 11) % 12) + 1),
this.Minute,
this.Second,
(this.Hour < 12) ? "AM" : "PM");
}
// use Kernel32.dll for full .NET or coredll.dll for .NET CF
// [DllImport("Kernel32.dll", EntryPoint="GetLocalTime",
SetLastError=true)]
[DllImport("coredll.dll", EntryPoint="GetLocalTime", SetLastError=true)]
public extern static void GetLocalTime(ref SYSTEMTIME systemTime);
}
}
 
A

Alex Feinman [MVP]

As for 1) and 3) - yes, the problem is known and no, as far as I know this
is not addressed by a service pack. Not 100% sure about SP3 but probably not
as well

--
Alex Feinman
---
Visit http://www.opennetcf.org
Dave Hall said:
Thanks Alex. I didn't expect a response so quickly, and so perfectly on
target.

Based on the work around in the article you referenced, I was able to add
the following line inside my for() loop:
typeof(TimeZone).GetField("currentTimeZone",
BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance).SetValue(n
ull, null);

That did the trick in my test app. In my production app, I already use
CeRunAppAtEvent(NE_TZ_CHANGE, myEvent) to hook the system timezone change
event. I should be able to add that same line in the event handler for the
notification, and it should fix the problem without changing every other
call to DateTime.Now, or calling the code above unnecessarily from anywhere
else.

That answers questions 2 and 4. Does anyone know if this problem has been
resolved in any of the newer releases of CE.NET or and service packs? It's
apparently only a problem in the Compact Framework, not the full .NET
Framework.

Thanks,
Dave



Alex Feinman said:
We have discussed it about a year ago here. Take a look at:
http://groups.google.com/groups?hl=...man+datetime&hl=en&lr=&ie=UTF-8&start=20&sa=N
--
Alex Feinman
---
Visit http://www.opennetcf.org
does
not application know
if so
know
if
it's fixed in 4.2?
2) Does anyone know if this is a known and documented bug in the CF?
3) Does anyone know if any service packs for Version 4.1 of the CF that
specifically mention and resolve this problem?
4) Does anyone know of any simple programatic work arounds other than
replacing DateTime.Now with GetLocalTime()?

Thanks,
Dave

Here's the offending code. It's pretty short.
==============================================================
using System;
using System.Runtime.InteropServices;

namespace RTCTest
{
public class ClockTest
{
static void Main()
{
SYSTEMTIME systemTime = new SYSTEMTIME();
for(int i=0; i<300; i++)
{
SYSTEMTIME.GetLocalTime(ref systemTime);
Console.WriteLine("DateTime = {0} \t GetLocalTime = {1}",
System.DateTime.Now.ToString("G"),
systemTime.ToString());
System.Threading.Thread.Sleep(1000);
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public UInt16 Year;
public UInt16 Month;
public UInt16 DayOfWeek;
public UInt16 Day;
public UInt16 Hour;
public UInt16 Minute;
public UInt16 Second;
public UInt16 Millisecond;

public override string ToString()
{
return String.Format(@"{0}/{1}/{2,4:D4} {3}:{4,2:D2}:{5,2:D2} {6}",
this.Month,
this.Day,
this.Year,
(((this.Hour + 11) % 12) + 1),
this.Minute,
this.Second,
(this.Hour < 12) ? "AM" : "PM");
}
// use Kernel32.dll for full .NET or coredll.dll for .NET CF
// [DllImport("Kernel32.dll", EntryPoint="GetLocalTime",
SetLastError=true)]
[DllImport("coredll.dll", EntryPoint="GetLocalTime", SetLastError=true)]
public extern static void GetLocalTime(ref SYSTEMTIME systemTime);
}
}
 
D

Dave Hall

Another interesting quirk I discovered... When I run the code shown below in
the CE emulator, then start the date/time control panel applet and just let
the applet sit there undisturbed for several minutes, I notice that almost
exactly every other minute rollover is skipped. That is to say, the minute
doesn't increment when the seconds roll over from 59 to 00. The thing that's
especially wierd is that the emulator's system clock itself, not just the
display on the applet looses one minute for every two that the applet is
open. Even if I never click the "Apply" or "OK" buttons, the system clock is
set to the incorrectly incremented time shown in the applet. This doesn't
appear to ever happen on my actual device. This only occurs in the emulator,
and only when my app is running. It's not anything for which I'm trying to
find a resolution. It's just an odd quirk that I'm curious about. Does
anyone else see this behavior in the VS 2003 CE emulator? Any comments?
Here's an example of the time progresssion that I see displayed.

7/14/2000 11:02:58 AM
7/14/2000 11:02:59 AM
7/14/2000 11:02:00 AM *** Note no minute rollover occurs
7/14/2000 11:02:01 AM
etc...
7/14/2000 11:02:58 AM
7/14/2000 11:02:59 AM
7/14/2000 11:03:00 AM *** Normal minute rollover occurs
7/14/2000 11:03:01 AM
etc...
7/14/2000 11:03:58 AM
7/14/2000 11:03:59 AM
7/14/2000 11:03:00 AM *** Note no minute rollover occurs
7/14/2000 11:03:01 AM
etc...
7/14/2000 11:03:58 AM
7/14/2000 11:03:59 AM
7/14/2000 11:04:00 AM *** Normal minute rollover occurs
7/14/2000 11:04:01 AM
etc...
7/14/2000 11:04:58 AM
7/14/2000 11:04:59 AM
7/14/2000 11:04:00 AM *** Note no minute rollover occurs
7/14/2000 11:04:01 AM
etc...

Dave

Dave Hall said:
If the time zone is changed on my CE 4.1 device, or in the VS 2003 emulator
while my application is running, the DateTime class in the .NET CF does not
correctly report the current local time Here's how to reproduce the
problem: Compile & run the code shown below then change the time zone
through the standard date/time control panel applet while the application is
running. Notice that the clock in the system tray is quickly adjusted to
correspond to the new time zone, and the value returned by P/Invoking
GetLocalTime() in my application also reflects the change, but
System.DateTime.Now does not reflect the new time zone unless I stop and
restart the application. I haven't tried to see if a new thread that's
started after the timezone change would show the correct time or not,
although I'm curious about that too. If I change the external dll reference
per the comment, and run the same code on my W2K workstation with the full
.NET framework, I don't have any problem with the DateTime failing to adjust
to a timezone change, so it seems to be a CF bug. Since I am using
Console.WriteLine, the app below won't display on a PPC, so I don't know if
it has the same problem. I haven't bothered to rewrite it for the PPC since
my target is a specific CE device. My CE application needs to be able to
handle changing time zones while running, and I don't want to change every
reference to DateTime.Now to P/Invoke GetLocalTime() if I can help it, so I
have four questions:

1) Can someone try this code on a CE .NET 4.2 CF device and let me know if
it's fixed in 4.2?
2) Does anyone know if this is a known and documented bug in the CF?
2) Does anyone know if any service packs for Version 4.1 of the CF that
specifically mention and resolve this problem?
3) Does anyone know of any simple programatic work arounds other than
replacing DateTime.Now with GetLocalTime()?

Thanks,
Dave

Here's the offending code. It's pretty short.
==============================================================
using System;
using System.Runtime.InteropServices;

namespace RTCTest
{
public class ClockTest
{
static void Main()
{
SYSTEMTIME systemTime = new SYSTEMTIME();
for(int i=0; i<300; i++)
{
SYSTEMTIME.GetLocalTime(ref systemTime);
Console.WriteLine("DateTime = {0} \t GetLocalTime = {1}",
System.DateTime.Now.ToString("G"),
systemTime.ToString());
System.Threading.Thread.Sleep(1000);
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public UInt16 Year;
public UInt16 Month;
public UInt16 DayOfWeek;
public UInt16 Day;
public UInt16 Hour;
public UInt16 Minute;
public UInt16 Second;
public UInt16 Millisecond;

public override string ToString()
{
return String.Format(@"{0}/{1}/{2,4:D4} {3}:{4,2:D2}:{5,2:D2} {6}",
this.Month,
this.Day,
this.Year,
(((this.Hour + 11) % 12) + 1),
this.Minute,
this.Second,
(this.Hour < 12) ? "AM" : "PM");
}
// use Kernel32.dll for full .NET or coredll.dll for .NET CF
// [DllImport("Kernel32.dll", EntryPoint="GetLocalTime",
SetLastError=true)]
[DllImport("coredll.dll", EntryPoint="GetLocalTime", SetLastError=true)]
public extern static void GetLocalTime(ref SYSTEMTIME systemTime);
}
}
 
C

Chris Tacke, eMVP

That's a known emulator issue. The clock (among other things) sucks.

--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
---
Principal Partner
OpenNETCF Consulting
www.OpenNETCF.com



Dave Hall said:
Another interesting quirk I discovered... When I run the code shown below in
the CE emulator, then start the date/time control panel applet and just let
the applet sit there undisturbed for several minutes, I notice that almost
exactly every other minute rollover is skipped. That is to say, the minute
doesn't increment when the seconds roll over from 59 to 00. The thing that's
especially wierd is that the emulator's system clock itself, not just the
display on the applet looses one minute for every two that the applet is
open. Even if I never click the "Apply" or "OK" buttons, the system clock is
set to the incorrectly incremented time shown in the applet. This doesn't
appear to ever happen on my actual device. This only occurs in the emulator,
and only when my app is running. It's not anything for which I'm trying to
find a resolution. It's just an odd quirk that I'm curious about. Does
anyone else see this behavior in the VS 2003 CE emulator? Any comments?
Here's an example of the time progresssion that I see displayed.

7/14/2000 11:02:58 AM
7/14/2000 11:02:59 AM
7/14/2000 11:02:00 AM *** Note no minute rollover occurs
7/14/2000 11:02:01 AM
etc...
7/14/2000 11:02:58 AM
7/14/2000 11:02:59 AM
7/14/2000 11:03:00 AM *** Normal minute rollover occurs
7/14/2000 11:03:01 AM
etc...
7/14/2000 11:03:58 AM
7/14/2000 11:03:59 AM
7/14/2000 11:03:00 AM *** Note no minute rollover occurs
7/14/2000 11:03:01 AM
etc...
7/14/2000 11:03:58 AM
7/14/2000 11:03:59 AM
7/14/2000 11:04:00 AM *** Normal minute rollover occurs
7/14/2000 11:04:01 AM
etc...
7/14/2000 11:04:58 AM
7/14/2000 11:04:59 AM
7/14/2000 11:04:00 AM *** Note no minute rollover occurs
7/14/2000 11:04:01 AM
etc...

Dave

Dave Hall said:
If the time zone is changed on my CE 4.1 device, or in the VS 2003 emulator
while my application is running, the DateTime class in the .NET CF does not
correctly report the current local time Here's how to reproduce the
problem: Compile & run the code shown below then change the time zone
through the standard date/time control panel applet while the
application
is
running. Notice that the clock in the system tray is quickly adjusted to
correspond to the new time zone, and the value returned by P/Invoking
GetLocalTime() in my application also reflects the change, but
System.DateTime.Now does not reflect the new time zone unless I stop and
restart the application. I haven't tried to see if a new thread that's
started after the timezone change would show the correct time or not,
although I'm curious about that too. If I change the external dll reference
per the comment, and run the same code on my W2K workstation with the full
.NET framework, I don't have any problem with the DateTime failing to adjust
to a timezone change, so it seems to be a CF bug. Since I am using
Console.WriteLine, the app below won't display on a PPC, so I don't know if
it has the same problem. I haven't bothered to rewrite it for the PPC since
my target is a specific CE device. My CE application needs to be able to
handle changing time zones while running, and I don't want to change every
reference to DateTime.Now to P/Invoke GetLocalTime() if I can help it,
so
I
have four questions:

1) Can someone try this code on a CE .NET 4.2 CF device and let me know if
it's fixed in 4.2?
2) Does anyone know if this is a known and documented bug in the CF?
2) Does anyone know if any service packs for Version 4.1 of the CF that
specifically mention and resolve this problem?
3) Does anyone know of any simple programatic work arounds other than
replacing DateTime.Now with GetLocalTime()?

Thanks,
Dave

Here's the offending code. It's pretty short.
==============================================================
using System;
using System.Runtime.InteropServices;

namespace RTCTest
{
public class ClockTest
{
static void Main()
{
SYSTEMTIME systemTime = new SYSTEMTIME();
for(int i=0; i<300; i++)
{
SYSTEMTIME.GetLocalTime(ref systemTime);
Console.WriteLine("DateTime = {0} \t GetLocalTime = {1}",
System.DateTime.Now.ToString("G"),
systemTime.ToString());
System.Threading.Thread.Sleep(1000);
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public UInt16 Year;
public UInt16 Month;
public UInt16 DayOfWeek;
public UInt16 Day;
public UInt16 Hour;
public UInt16 Minute;
public UInt16 Second;
public UInt16 Millisecond;

public override string ToString()
{
return String.Format(@"{0}/{1}/{2,4:D4} {3}:{4,2:D2}:{5,2:D2} {6}",
this.Month,
this.Day,
this.Year,
(((this.Hour + 11) % 12) + 1),
this.Minute,
this.Second,
(this.Hour < 12) ? "AM" : "PM");
}
// use Kernel32.dll for full .NET or coredll.dll for .NET CF
// [DllImport("Kernel32.dll", EntryPoint="GetLocalTime",
SetLastError=true)]
[DllImport("coredll.dll", EntryPoint="GetLocalTime", SetLastError=true)]
public extern static void GetLocalTime(ref SYSTEMTIME systemTime);
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top