G
Guest
Hi all
I have a CF 1.0 application that needs to keep its time coordinated with
that of a server. I am using a P/Invoke of SetSystemTime on the device to set
the device time to that received from the server. However I have noted a
peculiarity when the new time is in a different daylight savings period from
the current time on the device. While, in general, the time drift between the
handheld device and the server will not show this issue, it will occur about
half the time after a hard reset of the handheld device. In addition, the
server may not be in the same time zone as the handheld device, so I must
deal with UTC time. (In fact, in the real system I must convert from the
server-reported time to UTC before using it.)
After calling SetSystemTime (with a UTC time), the clock in the title bar
becomes set to a date/time that seems to use the old value of a daylight
savings flag to convert from UTC to local rather than a flag based on the
date/time being set. However, if I look at the return of a call to
System.DateTime.Now, the local time is correct.
So as an example, say the current date time is 25 May 2006 17:30 in "GMT-5
Eastern US" (which is currently UTC-4 hours due to daylight savings). If the
time is set to 25 Jan 2006 22:30, the clock in the title bar displays 6:30
(pm). This is incorrect, it should be 5:30pm because in January it is
eastern standard time (UTC-5 hours). Even more interesting is that the time
returned by a System.DateTime.Now is correct. It appears that the clock on
the title bar uses a different mechanism to decide whether to apply the
daylight savings adjustment than the System.DateTime.
I poked around the newsgroups and Kbases and did find out some interesting
info.
http://support.microsoft.com/kb/821231/en-us
Since this article mentions that "The GetTimeZoneInformation API uses a
great deal of system resources and time",
I decided to check the value reported by the P/Invoke of
GetTimeZoneInformation. Indeed, it appears that this flag is not updated for
some time after a call to SetSystemTime that would cause an adjustment in the
flag. I have observed this delay to be something less than 200ms in the best
case and longer than 2 seconds in other cases. I have run a test app on an
array of different machines running both WM2003 and WM2005 from the
manufacturers HP, Symbol, and Intermec.
The test subtracts 6 months from the current time, converts to UTC and calls
SetSystemTime. Then it checks the time using DateTime.Now. It then goes into
a 10 iteration loop with a check of the result of GetTimeZoneInformation
followed by a sleep of 200ms. The times recoreded and set are displayed on a
form as well as the results of the loop.
I thought that, perhaps, I could avoid this by using a P/Invoke to
SetLocalTime, so I added the ability to test that to the test application.
Unfortunately, while that seems to make the title bar clock show the correct
time, the System.DateTime.Now returns an incorrect time. It appears that I
cannot win.
In the real system, after the initial call to SetSystemTime, I spawn a
thread that will sleep for 5 seconds and call SetSystemTime again with the
retrieved time (after adjusting for the sleep). When this second call to
SetSystemTime is made, there is no change to the Daylight Savings flag, so
both the title bar clock and the System.DateTime.Now end up in agreement.
So, I have a workaround, but I'm curious if there is another solution to this
problem or perhaps another approach to take.
Thanks for any ideas.
Kevin
Following is the code for Form1.cs.
Create a new C# Smart Device Application, replace the generated Form1.cs
with this code, compile and give it a try.
----------
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
namespace TimeZoneOddity
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.TextBox textBox3;
private System.Windows.Forms.TextBox textBox4;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox textBox5;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox6;
private System.Windows.Forms.CheckBox cbUseSetLocal;
private System.Windows.Forms.Label label9;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox2 = new System.Windows.Forms.TextBox();
this.textBox3 = new System.Windows.Forms.TextBox();
this.textBox4 = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.textBox5 = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.textBox6 = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.cbUseSetLocal = new System.Windows.Forms.CheckBox();
//
// label1
//
this.label1.Size = new System.Drawing.Size(144, 16);
this.label1.Text = "DateTime value at start";
//
// label2
//
this.label2.Location = new System.Drawing.Point(0, 16);
this.label2.Size = new System.Drawing.Size(144, 16);
this.label2.Text = "(local)";
//
// label3
//
this.label3.Location = new System.Drawing.Point(0, 40);
this.label3.Size = new System.Drawing.Size(144, 16);
this.label3.Text = "(UTC)";
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(40, 16);
this.textBox1.ReadOnly = true;
this.textBox1.Size = new System.Drawing.Size(192, 22);
this.textBox1.Text = "";
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(40, 40);
this.textBox2.ReadOnly = true;
this.textBox2.Size = new System.Drawing.Size(192, 22);
this.textBox2.Text = "";
//
// textBox3
//
this.textBox3.Location = new System.Drawing.Point(40, 80);
this.textBox3.ReadOnly = true;
this.textBox3.Size = new System.Drawing.Size(192, 22);
this.textBox3.Text = "";
//
// textBox4
//
this.textBox4.Location = new System.Drawing.Point(40, 104);
this.textBox4.ReadOnly = true;
this.textBox4.Size = new System.Drawing.Size(192, 22);
this.textBox4.Text = "";
//
// label4
//
this.label4.Location = new System.Drawing.Point(0, 104);
this.label4.Size = new System.Drawing.Size(144, 16);
this.label4.Text = "(UTC)";
//
// label5
//
this.label5.Location = new System.Drawing.Point(0, 80);
this.label5.Size = new System.Drawing.Size(144, 16);
this.label5.Text = "(local)";
//
// label6
//
this.label6.Location = new System.Drawing.Point(0, 64);
this.label6.Size = new System.Drawing.Size(168, 16);
this.label6.Text = "DateTime value - 6 months";
//
// textBox5
//
this.textBox5.Location = new System.Drawing.Point(40, 144);
this.textBox5.ReadOnly = true;
this.textBox5.Size = new System.Drawing.Size(192, 22);
this.textBox5.Text = "";
//
// label7
//
this.label7.Location = new System.Drawing.Point(0, 144);
this.label7.Size = new System.Drawing.Size(144, 16);
this.label7.Text = "(local)";
//
// label8
//
this.label8.Location = new System.Drawing.Point(0, 128);
this.label8.Size = new System.Drawing.Size(216, 16);
this.label8.Text = "DateTime value read just after set";
//
// button1
//
this.button1.Location = new System.Drawing.Point(112, 248);
this.button1.Size = new System.Drawing.Size(120, 20);
this.button1.Text = "set back 6 months";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// textBox6
//
this.textBox6.Location = new System.Drawing.Point(8, 184);
this.textBox6.Multiline = true;
this.textBox6.ReadOnly = true;
this.textBox6.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.textBox6.Size = new System.Drawing.Size(224, 56);
this.textBox6.Text = "";
//
// label9
//
this.label9.Location = new System.Drawing.Point(0, 168);
this.label9.Size = new System.Drawing.Size(208, 16);
this.label9.Text = "Daylight/Standard after set";
//
// cbUseSetLocal
//
this.cbUseSetLocal.Location = new System.Drawing.Point(8, 248);
this.cbUseSetLocal.Size = new System.Drawing.Size(96, 20);
this.cbUseSetLocal.Text = "use SetLocal";
//
// Form1
//
this.Controls.Add(this.cbUseSetLocal);
this.Controls.Add(this.label9);
this.Controls.Add(this.textBox6);
this.Controls.Add(this.button1);
this.Controls.Add(this.textBox5);
this.Controls.Add(this.label7);
this.Controls.Add(this.label8);
this.Controls.Add(this.textBox3);
this.Controls.Add(this.textBox4);
this.Controls.Add(this.label4);
this.Controls.Add(this.label5);
this.Controls.Add(this.label6);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.MinimizeBox = false;
this.Text = "Form1";
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
Application.Run(new Form1());
}
[DllImport("coredll", SetLastError=true)]
internal static extern bool SetSystemTime( byte[] st );
[DllImport("coredll", SetLastError=true)]
internal static extern bool SetLocalTime( byte[] st );
[DllImport("coredll", EntryPoint="GetTimeZoneInformation",
SetLastError=true)]
internal static extern int GetTimeZoneInformation( byte[] timezoneinfo );
private void button1_Click(object sender, System.EventArgs e)
{
//Clear all
this.textBox1.Text="";
this.textBox2.Text="";
this.textBox3.Text="";
this.textBox4.Text="";
this.textBox5.Text="";
this.textBox6.Text="";
//initialize a string builder for our message
System.Text.StringBuilder sb = new System.Text.StringBuilder();
//save our current time so we can reset
DateTime savedDTLocal = DateTime.Now;
//move the date 6 months back to change daylight savings
// time should change clock on title bar is reset
DateTime newLocalDt = savedDTLocal.AddMonths( -6 );
bool bSetResult;
if (this.cbUseSetLocal.Checked)
{
byte[] bytes = ToSystemTimeStructure(newLocalDt);
bSetResult = SetLocalTime( bytes );
}
else
{
byte[] bytes = ToSystemTimeStructure(newLocalDt.ToUniversalTime( ));
bSetResult = SetSystemTime( bytes );
}
//set the system time
if (!bSetResult)
{
System.Windows.Forms.MessageBox.Show("Could not set system time: " +
Marshal.GetLastWin32Error().ToString());
}
else
{
byte[] timezoneinfo = new byte[ 172 ];
this.textBox1.Text = savedDTLocal.ToString("yyyy/MM/ddTHH:mm:sszzz");
this.textBox2.Text =
savedDTLocal.ToUniversalTime().ToString("yyyy/MM/ddTHH:mm:ssZ");
this.textBox3.Text = newLocalDt.ToString("yyyy/MM/ddTHH:mm:sszzz");
this.textBox4.Text =
newLocalDt.ToUniversalTime().ToString("yyyy/MM/ddTHH:mm:ssZ");
this.textBox5.Text = DateTime.Now.ToString("yyyy/MM/ddTHH:mm:sszzz");
// start a loop that will run for about 2 seconds, checking the state of
the DST flag at 200 ms intervals
for ( int i = 0; i < 10; i++ )
{
sb.Append("Trial: " + i.ToString());
sb.Append(" " + (i*200).ToString() + "ms");
switch ( GetTimeZoneInformation( timezoneinfo ) )
{
case 0:
sb.Append(" GetTimeZoneInfo failed.\r\n");
break;
case 1:
sb.Append(" Standard.\r\n");
break;
case 2:
sb.Append(" Daylight Savings.\r\n");
break;
}
System.Threading.Thread.Sleep(200);
}
//Show the results
this.textBox6.Text = sb.ToString();
}
}
private byte [] ToSystemTimeStructure(DateTime dt)
{
//create the SYSTEMTIME-like byte array that SetSystemTime expects
byte[] bytes = new byte[16];
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Year ), 0,
bytes, 0, 2 );
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Month ), 0,
bytes, 2, 2 );
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Day ), 0,
bytes, 6, 2 );
//not setting day of week, it is ignored
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Hour ), 0,
bytes, 8, 2 );
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Minute ), 0,
bytes, 10, 2 );
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Second ), 0,
bytes, 12, 2 );
//no real need to set milliseconds for our test
return bytes;
}
}
}
I have a CF 1.0 application that needs to keep its time coordinated with
that of a server. I am using a P/Invoke of SetSystemTime on the device to set
the device time to that received from the server. However I have noted a
peculiarity when the new time is in a different daylight savings period from
the current time on the device. While, in general, the time drift between the
handheld device and the server will not show this issue, it will occur about
half the time after a hard reset of the handheld device. In addition, the
server may not be in the same time zone as the handheld device, so I must
deal with UTC time. (In fact, in the real system I must convert from the
server-reported time to UTC before using it.)
After calling SetSystemTime (with a UTC time), the clock in the title bar
becomes set to a date/time that seems to use the old value of a daylight
savings flag to convert from UTC to local rather than a flag based on the
date/time being set. However, if I look at the return of a call to
System.DateTime.Now, the local time is correct.
So as an example, say the current date time is 25 May 2006 17:30 in "GMT-5
Eastern US" (which is currently UTC-4 hours due to daylight savings). If the
time is set to 25 Jan 2006 22:30, the clock in the title bar displays 6:30
(pm). This is incorrect, it should be 5:30pm because in January it is
eastern standard time (UTC-5 hours). Even more interesting is that the time
returned by a System.DateTime.Now is correct. It appears that the clock on
the title bar uses a different mechanism to decide whether to apply the
daylight savings adjustment than the System.DateTime.
I poked around the newsgroups and Kbases and did find out some interesting
info.
http://support.microsoft.com/kb/821231/en-us
Since this article mentions that "The GetTimeZoneInformation API uses a
great deal of system resources and time",
I decided to check the value reported by the P/Invoke of
GetTimeZoneInformation. Indeed, it appears that this flag is not updated for
some time after a call to SetSystemTime that would cause an adjustment in the
flag. I have observed this delay to be something less than 200ms in the best
case and longer than 2 seconds in other cases. I have run a test app on an
array of different machines running both WM2003 and WM2005 from the
manufacturers HP, Symbol, and Intermec.
The test subtracts 6 months from the current time, converts to UTC and calls
SetSystemTime. Then it checks the time using DateTime.Now. It then goes into
a 10 iteration loop with a check of the result of GetTimeZoneInformation
followed by a sleep of 200ms. The times recoreded and set are displayed on a
form as well as the results of the loop.
I thought that, perhaps, I could avoid this by using a P/Invoke to
SetLocalTime, so I added the ability to test that to the test application.
Unfortunately, while that seems to make the title bar clock show the correct
time, the System.DateTime.Now returns an incorrect time. It appears that I
cannot win.
In the real system, after the initial call to SetSystemTime, I spawn a
thread that will sleep for 5 seconds and call SetSystemTime again with the
retrieved time (after adjusting for the sleep). When this second call to
SetSystemTime is made, there is no change to the Daylight Savings flag, so
both the title bar clock and the System.DateTime.Now end up in agreement.
So, I have a workaround, but I'm curious if there is another solution to this
problem or perhaps another approach to take.
Thanks for any ideas.
Kevin
Following is the code for Form1.cs.
Create a new C# Smart Device Application, replace the generated Form1.cs
with this code, compile and give it a try.
----------
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
namespace TimeZoneOddity
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.TextBox textBox3;
private System.Windows.Forms.TextBox textBox4;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox textBox5;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox6;
private System.Windows.Forms.CheckBox cbUseSetLocal;
private System.Windows.Forms.Label label9;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox2 = new System.Windows.Forms.TextBox();
this.textBox3 = new System.Windows.Forms.TextBox();
this.textBox4 = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.textBox5 = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.textBox6 = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.cbUseSetLocal = new System.Windows.Forms.CheckBox();
//
// label1
//
this.label1.Size = new System.Drawing.Size(144, 16);
this.label1.Text = "DateTime value at start";
//
// label2
//
this.label2.Location = new System.Drawing.Point(0, 16);
this.label2.Size = new System.Drawing.Size(144, 16);
this.label2.Text = "(local)";
//
// label3
//
this.label3.Location = new System.Drawing.Point(0, 40);
this.label3.Size = new System.Drawing.Size(144, 16);
this.label3.Text = "(UTC)";
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(40, 16);
this.textBox1.ReadOnly = true;
this.textBox1.Size = new System.Drawing.Size(192, 22);
this.textBox1.Text = "";
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(40, 40);
this.textBox2.ReadOnly = true;
this.textBox2.Size = new System.Drawing.Size(192, 22);
this.textBox2.Text = "";
//
// textBox3
//
this.textBox3.Location = new System.Drawing.Point(40, 80);
this.textBox3.ReadOnly = true;
this.textBox3.Size = new System.Drawing.Size(192, 22);
this.textBox3.Text = "";
//
// textBox4
//
this.textBox4.Location = new System.Drawing.Point(40, 104);
this.textBox4.ReadOnly = true;
this.textBox4.Size = new System.Drawing.Size(192, 22);
this.textBox4.Text = "";
//
// label4
//
this.label4.Location = new System.Drawing.Point(0, 104);
this.label4.Size = new System.Drawing.Size(144, 16);
this.label4.Text = "(UTC)";
//
// label5
//
this.label5.Location = new System.Drawing.Point(0, 80);
this.label5.Size = new System.Drawing.Size(144, 16);
this.label5.Text = "(local)";
//
// label6
//
this.label6.Location = new System.Drawing.Point(0, 64);
this.label6.Size = new System.Drawing.Size(168, 16);
this.label6.Text = "DateTime value - 6 months";
//
// textBox5
//
this.textBox5.Location = new System.Drawing.Point(40, 144);
this.textBox5.ReadOnly = true;
this.textBox5.Size = new System.Drawing.Size(192, 22);
this.textBox5.Text = "";
//
// label7
//
this.label7.Location = new System.Drawing.Point(0, 144);
this.label7.Size = new System.Drawing.Size(144, 16);
this.label7.Text = "(local)";
//
// label8
//
this.label8.Location = new System.Drawing.Point(0, 128);
this.label8.Size = new System.Drawing.Size(216, 16);
this.label8.Text = "DateTime value read just after set";
//
// button1
//
this.button1.Location = new System.Drawing.Point(112, 248);
this.button1.Size = new System.Drawing.Size(120, 20);
this.button1.Text = "set back 6 months";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// textBox6
//
this.textBox6.Location = new System.Drawing.Point(8, 184);
this.textBox6.Multiline = true;
this.textBox6.ReadOnly = true;
this.textBox6.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.textBox6.Size = new System.Drawing.Size(224, 56);
this.textBox6.Text = "";
//
// label9
//
this.label9.Location = new System.Drawing.Point(0, 168);
this.label9.Size = new System.Drawing.Size(208, 16);
this.label9.Text = "Daylight/Standard after set";
//
// cbUseSetLocal
//
this.cbUseSetLocal.Location = new System.Drawing.Point(8, 248);
this.cbUseSetLocal.Size = new System.Drawing.Size(96, 20);
this.cbUseSetLocal.Text = "use SetLocal";
//
// Form1
//
this.Controls.Add(this.cbUseSetLocal);
this.Controls.Add(this.label9);
this.Controls.Add(this.textBox6);
this.Controls.Add(this.button1);
this.Controls.Add(this.textBox5);
this.Controls.Add(this.label7);
this.Controls.Add(this.label8);
this.Controls.Add(this.textBox3);
this.Controls.Add(this.textBox4);
this.Controls.Add(this.label4);
this.Controls.Add(this.label5);
this.Controls.Add(this.label6);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.MinimizeBox = false;
this.Text = "Form1";
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
Application.Run(new Form1());
}
[DllImport("coredll", SetLastError=true)]
internal static extern bool SetSystemTime( byte[] st );
[DllImport("coredll", SetLastError=true)]
internal static extern bool SetLocalTime( byte[] st );
[DllImport("coredll", EntryPoint="GetTimeZoneInformation",
SetLastError=true)]
internal static extern int GetTimeZoneInformation( byte[] timezoneinfo );
private void button1_Click(object sender, System.EventArgs e)
{
//Clear all
this.textBox1.Text="";
this.textBox2.Text="";
this.textBox3.Text="";
this.textBox4.Text="";
this.textBox5.Text="";
this.textBox6.Text="";
//initialize a string builder for our message
System.Text.StringBuilder sb = new System.Text.StringBuilder();
//save our current time so we can reset
DateTime savedDTLocal = DateTime.Now;
//move the date 6 months back to change daylight savings
// time should change clock on title bar is reset
DateTime newLocalDt = savedDTLocal.AddMonths( -6 );
bool bSetResult;
if (this.cbUseSetLocal.Checked)
{
byte[] bytes = ToSystemTimeStructure(newLocalDt);
bSetResult = SetLocalTime( bytes );
}
else
{
byte[] bytes = ToSystemTimeStructure(newLocalDt.ToUniversalTime( ));
bSetResult = SetSystemTime( bytes );
}
//set the system time
if (!bSetResult)
{
System.Windows.Forms.MessageBox.Show("Could not set system time: " +
Marshal.GetLastWin32Error().ToString());
}
else
{
byte[] timezoneinfo = new byte[ 172 ];
this.textBox1.Text = savedDTLocal.ToString("yyyy/MM/ddTHH:mm:sszzz");
this.textBox2.Text =
savedDTLocal.ToUniversalTime().ToString("yyyy/MM/ddTHH:mm:ssZ");
this.textBox3.Text = newLocalDt.ToString("yyyy/MM/ddTHH:mm:sszzz");
this.textBox4.Text =
newLocalDt.ToUniversalTime().ToString("yyyy/MM/ddTHH:mm:ssZ");
this.textBox5.Text = DateTime.Now.ToString("yyyy/MM/ddTHH:mm:sszzz");
// start a loop that will run for about 2 seconds, checking the state of
the DST flag at 200 ms intervals
for ( int i = 0; i < 10; i++ )
{
sb.Append("Trial: " + i.ToString());
sb.Append(" " + (i*200).ToString() + "ms");
switch ( GetTimeZoneInformation( timezoneinfo ) )
{
case 0:
sb.Append(" GetTimeZoneInfo failed.\r\n");
break;
case 1:
sb.Append(" Standard.\r\n");
break;
case 2:
sb.Append(" Daylight Savings.\r\n");
break;
}
System.Threading.Thread.Sleep(200);
}
//Show the results
this.textBox6.Text = sb.ToString();
}
}
private byte [] ToSystemTimeStructure(DateTime dt)
{
//create the SYSTEMTIME-like byte array that SetSystemTime expects
byte[] bytes = new byte[16];
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Year ), 0,
bytes, 0, 2 );
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Month ), 0,
bytes, 2, 2 );
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Day ), 0,
bytes, 6, 2 );
//not setting day of week, it is ignored
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Hour ), 0,
bytes, 8, 2 );
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Minute ), 0,
bytes, 10, 2 );
Buffer.BlockCopy(BitConverter.GetBytes( (short)dt.Second ), 0,
bytes, 12, 2 );
//no real need to set milliseconds for our test
return bytes;
}
}
}