KB928388 Breaking Tests with Windows DST TimeZone Patch and Past Dates
UPDATE: It appears that what we suspected is true, Windows understands one set of DST rules. Whatever the current DST rules are are applied to all dates. This doesn't make sense to me as that would make the 2005 test below fail also, and it doesn't. More as it comes in.
UPDATE#2: Seems that a new "Dynamic DST" section is added for future OS's, like Vista, for handling future DST time changes. This change will affect all Windows OS's equally - that is, you don't need to custom code for one OS versus another. If congress, in their infinite wisdom, decides to change the laws of Time and Space again, Vista and other OS's will require only a registry change, and past time rules will still apply. Thanks to Tim Heuer for helping puzzle through it all.
One of our Architects at Corillian, Paul Gomes, led the team that designed our .NET-based OFX Banking Server. That product happens to have ridiculously good Code Coverage and a metric-crapload of Unit Tests. Recently a build server had the Daylight Savings Time (DST) Windows KB928288 patch applied. Immediately an internal Date-related test failed.
Paul dug into it and boiled it down to this simplified test that takes a date in March of 2006 and converts it to GMT.
1: [TestFixture]
2: public class DSTTest
3: {
4: private const string DATEFORMAT =
@"yyyyMMddHHmmss.fff[0\:G\MT]";
5:
6: public DSTTest(){}
7:
8: [Test]
9: public void TestDateInThePast()
10: {
11: DateTime myDate = DateTime.ParseExact(
"2006/03/17 11:42:33",
"yyyy/MM/dd HH:mm:ss",
CultureInfo.InvariantCulture);
12: string myDateAsString = myDate.ToUniversalTime().ToString(
DATEFORMAT, CultureInfo.InvariantCulture);
13: Assert.AreEqual("20060317194233.000[0:GMT]",
myDateAsString);
14: }
15: }
The output is interesting. Note that we're comparing strings in this case for clarity.
Output from unit test:
TestCase 'DSTTest.DSTTest.TestDateInThePast'
failed:
String lengths are both 25.
Strings differ at index 9.
expected: <"20060317194233.000[0:GMT]">
but was: <"20060317184233.000[0:GMT]">
---------------------^
c:\dsttest\dsttest.cs(19,0): at DSTTest.DSTTest.TestDateInThePast()
I first thought that this was no problem and I said to Paul:
Makes sense…that date in your test is inside the DST boundary, so we switch from -8 to -7. 11:00 becomes 18:00, rather than 19:00. We “sprung forward.”
However, Paul reminded me that we were testing a date within 2006! We're testing the 17th of March, 2006, outside of DST. Note the table below. I'd expect that day to be DST for 2007, but not 2006.
Here's where it gets really weird. Let's try the 12th of March, and try dates in 2005, 2006, and 2007. Note that when the time is 02:59:59am on March 12th, 2006, the test succeeds, but it fails at 3am, one minute later. Again, note that this is using a date in 2006, where DST started in April.
1: [Test]
2: public void TestDateIn2007Succeeds()
3: {
4: DateTime myDate = DateTime.ParseExact(
"2007/03/12 03:00:00",
"yyyy/MM/dd HH:mm:ss",
CultureInfo.InvariantCulture);
5: string myDateAsString = myDate.ToUniversalTime().ToString(
DATEFORMAT, CultureInfo.InvariantCulture);
6: Assert.AreEqual("20070312100000.000[0:GMT]",myDateAsString);
7: }
8:
9: [Test]
10: public void TestDateIn2006Succeeds()
11: {
12: DateTime myDate = DateTime.ParseExact(
"2006/03/12 02:59:59",
"yyyy/MM/dd HH:mm:ss",
CultureInfo.InvariantCulture);
13: string myDateAsString = myDate.ToUniversalTime().ToString(
DATEFORMAT, CultureInfo.InvariantCulture);
14: Assert.AreEqual("20060312105959.000[0:GMT]",myDateAsString);
15: }
16:
17: [Test]
18: public void TestDateIn2006Fails()
19: {
20: DateTime myDate = DateTime.ParseExact(
"2006/03/12 03:00:00",
"yyyy/MM/dd HH:mm:ss",
CultureInfo.InvariantCulture);
21: string myDateAsString = myDate.ToUniversalTime().ToString(
DATEFORMAT, CultureInfo.InvariantCulture);
22: Assert.AreEqual("20060312110000.000[0:GMT]",myDateAsString);
23: }
24:
25: [Test]
26: public void TestDateIn2005Succeeds()
27: {
28: DateTime myDate = DateTime.ParseExact(
"2005/03/12 03:00:00",
"yyyy/MM/dd HH:mm:ss",
CultureInfo.InvariantCulture);
29: string myDateAsString = myDate.ToUniversalTime().ToString(
DATEFORMAT, CultureInfo.InvariantCulture);
30: Assert.AreEqual("20050312110000.000[0:GMT]",myDateAsString);
31: }
32: }
33: }
What are we missing, dear reader? Is there a problem (bug?) with the registry-based Windows DST Patch?
I'm leaning towards assuming it's us, but I wanted to ask you. It seems that the data points towards this patch not working with dates in 2006. Not a huge deal, but non-trivial,IMHO.
As an aside, but very slightly related note, Steve Harman had an interesting bug where his Unit Tests were expecting to see "Tijuana" at the end of his TimeZone's Display Name. Since Mexico isn't following our lead (if it could be called a "lead") and changing their DST, so Tijuana isn't in PST proper anymore.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.



About Newsletter