Implement mono_gc_alloc_fixed on Boehm to be uncollectable. This matches SGen behavio...
[mono.git] / mcs / class / corlib / Test / System / TimeZoneTest.cs
1 //
2 // TimeZoneTest.cs - NUnit Test Cases for the System.TimeZone struct
3 //
4 // Authors:
5 //      Martin Baulig (martin@gnome.org)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 //   (C) 2002 Martin Baulig
9 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
10 //
11
12 using NUnit.Framework;
13 using System;
14 using System.IO;
15 using System.Threading;
16 using System.Globalization;
17 using System.Runtime.Serialization.Formatters.Binary;
18
19 namespace MonoTests.System {
20
21 [TestFixture]
22 public class TimeZoneTest {
23
24         private void CET (TimeZone t1) 
25         {
26                 Assert.IsTrue("CET" == t1.StandardName || "W. Europe Standard Time" == t1.StandardName, "A01");
27                 Assert.IsTrue("CEST" == t1.DaylightName || "W. Europe Daylight Time" == t1.DaylightName, "A02");
28         
29                 DaylightTime d1 = t1.GetDaylightChanges (2002);
30                 Assert.AreEqual("03/31/2002 02:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "A03");
31                 Assert.AreEqual("10/27/2002 03:00:00", d1.End.ToString ("G", CultureInfo.InvariantCulture), "A04");
32                 Assert.AreEqual(36000000000L, d1.Delta.Ticks, "A05");
33         
34                 DaylightTime d2 = t1.GetDaylightChanges (1996);
35                 Assert.AreEqual("03/31/1996 02:00:00", d2.Start.ToString ("G", CultureInfo.InvariantCulture), "A06");
36                 Assert.AreEqual("10/27/1996 03:00:00", d2.End.ToString ("G", CultureInfo.InvariantCulture), "A07");
37                 Assert.AreEqual(36000000000L, d2.Delta.Ticks, "A08");
38         
39                 DateTime d3 = new DateTime (2002,2,25);
40                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d3), "A09");
41                 DateTime d4 = new DateTime (2002,4,2);
42                 Assert.AreEqual(true, t1.IsDaylightSavingTime (d4), "A10");
43                 DateTime d5 = new DateTime (2002,11,4);
44                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d5), "A11");
45         
46                 Assert.AreEqual(36000000000L, t1.GetUtcOffset (d3).Ticks, "A12");
47                 Assert.AreEqual(72000000000L, t1.GetUtcOffset (d4).Ticks, "A13");
48                 Assert.AreEqual(36000000000L, t1.GetUtcOffset (d5).Ticks, "A14");
49
50                 // Test TimeZone methods with UTC DateTime in DST.
51                 DateTime d6 = d4.ToUniversalTime ();
52                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d6), "A15");
53                 Assert.AreEqual(0, t1.GetUtcOffset (d6).Ticks, "A16");
54         }
55
56         private void EST (TimeZone t1) 
57         {
58                 Assert.IsTrue("EST" == t1.StandardName || "Eastern Standard Time" == t1.StandardName, "B01");
59                 Assert.IsTrue("EDT" == t1.DaylightName || "Eastern Daylight Time" == t1.DaylightName, "B02");
60
61                 DaylightTime d1 = t1.GetDaylightChanges (2002);
62                 Assert.AreEqual("04/07/2002 02:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "B03");
63                 Assert.AreEqual("10/27/2002 02:00:00", d1.End.ToString ("G", CultureInfo.InvariantCulture), "B04");
64                 Assert.AreEqual(36000000000L, d1.Delta.Ticks, "B05");
65
66                 DaylightTime d2 = t1.GetDaylightChanges (1996);
67                 Assert.AreEqual("04/07/1996 02:00:00", d2.Start.ToString ("G", CultureInfo.InvariantCulture), "B06");
68                 Assert.AreEqual("10/27/1996 02:00:00", d2.End.ToString ("G", CultureInfo.InvariantCulture), "B07");
69                 Assert.AreEqual(36000000000L, d2.Delta.Ticks, "B08");
70
71                 DateTime d3 = new DateTime (2002,2,25);
72                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d3), "B09");
73                 DateTime d4 = new DateTime (2002,4,8);
74                 Assert.AreEqual(true, t1.IsDaylightSavingTime (d4), "B10");
75                 
76                 DateTime d5 = new DateTime (2002,11,4);
77                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d5), "B11");
78
79                 Assert.AreEqual(-180000000000L, t1.GetUtcOffset (d3).Ticks, "B12");
80                 Assert.AreEqual(-144000000000L, t1.GetUtcOffset (d4).Ticks, "B13");
81                 Assert.AreEqual(-180000000000L, t1.GetUtcOffset (d5).Ticks, "B14");
82
83                 // Test TimeZone methods with UTC DateTime in DST.
84                 DateTime d6 = d4.ToUniversalTime ();
85                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d6), "B15");
86                 Assert.AreEqual(0, t1.GetUtcOffset (d6).Ticks, "B16");
87         }
88
89         private void TST (TimeZone t1) 
90         {
91                 Assert.AreEqual("Tokyo Standard Time", t1.StandardName, "C01");
92                 Assert.AreEqual("Tokyo Standard Time", t1.DaylightName, "C02");
93
94                 DateTime d3 = new DateTime (2002,2,25);
95                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d3), "C09");
96                 DateTime d4 = new DateTime (2002,4,8);
97                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d4), "C10");
98                 DateTime d5 = new DateTime (2002,11,4);
99                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d5), "C11");
100
101                 Assert.AreEqual(324000000000L, t1.GetUtcOffset (d3).Ticks, "C12");
102                 Assert.AreEqual(324000000000L, t1.GetUtcOffset (d4).Ticks, "C13");
103                 Assert.AreEqual(324000000000L, t1.GetUtcOffset (d5).Ticks, "C14");
104         }
105
106         private void GMT (TimeZone t1) {
107                 // Probably wont work on MS.NET, but is better than nothing. Where do
108                 // we change our implementation to match theirs?
109                 
110                 Assert.AreEqual("GMT", t1.StandardName, "D01");
111                 Assert.IsTrue("BST" == t1.DaylightName || "IST" == t1.DaylightName, "D02");
112         
113                 DaylightTime d1 = t1.GetDaylightChanges (2002);
114                 Assert.AreEqual("03/31/2002 01:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "D03");
115                 Assert.AreEqual("10/27/2002 02:00:00", d1.End.ToString ("G", CultureInfo.InvariantCulture), "D04");
116                 Assert.AreEqual(36000000000L, d1.Delta.Ticks, "D05");
117         
118                 DaylightTime d2 = t1.GetDaylightChanges (1996);
119                 Assert.AreEqual("03/31/1996 01:00:00", d2.Start.ToString ("G", CultureInfo.InvariantCulture), "D06");
120                 Assert.AreEqual("10/27/1996 02:00:00", d2.End.ToString ("G", CultureInfo.InvariantCulture), "D07");
121                 Assert.AreEqual(36000000000L, d2.Delta.Ticks, "D08");
122         
123                 DateTime d3 = new DateTime (2002,2,25);
124                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d3), "D09");
125                 DateTime d4 = new DateTime (2002,4,2);
126                 Assert.AreEqual(true, t1.IsDaylightSavingTime (d4), "D10");
127                 DateTime d5 = new DateTime (2002,11,4);
128                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d5), "D11");
129         
130                 Assert.AreEqual(0L, t1.GetUtcOffset (d3).Ticks, "D12");
131                 Assert.AreEqual(36000000000L, t1.GetUtcOffset (d4).Ticks, "D13");
132                 Assert.AreEqual(0L, t1.GetUtcOffset (d5).Ticks, "D14");
133
134                 // Test TimeZone methods with UTC DateTime in DST.
135                 DateTime d6 = d4.ToUniversalTime ();
136                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d6), "D15");
137                 Assert.AreEqual(0, t1.GetUtcOffset (d6).Ticks, "D16");
138         }
139
140         private void NZST(TimeZone t1) {
141                 Assert.AreEqual("NZST", t1.StandardName, "E01");
142                 Assert.AreEqual("NZDT", t1.DaylightName, "E02");
143
144                 DaylightTime d1 = t1.GetDaylightChanges (2013);
145                 Assert.AreEqual("09/29/2013 02:00:00", d1.Start.ToString ("G", CultureInfo.InvariantCulture), "E03");
146                 Assert.AreEqual("04/07/2013 03:00:00", d1.End.ToString ("G", CultureInfo.InvariantCulture), "E04");
147                 Assert.AreEqual(36000000000L, d1.Delta.Ticks, "E05");
148
149                 DaylightTime d2 = t1.GetDaylightChanges (2001);
150                 Assert.AreEqual("10/07/2001 02:00:00", d2.Start.ToString ("G", CultureInfo.InvariantCulture), "E06");
151                 Assert.AreEqual("03/18/2001 03:00:00", d2.End.ToString ("G", CultureInfo.InvariantCulture), "E07");
152                 Assert.AreEqual(36000000000L, d2.Delta.Ticks, "E08");
153
154                 DateTime d3 = new DateTime(2013,02,15);
155                 Assert.AreEqual(true, t1.IsDaylightSavingTime (d3), "E09");
156                 DateTime d4 = new DateTime(2013,04,30);
157                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d4), "E10");
158                 DateTime d5 = new DateTime(2013,11,03);
159                 Assert.AreEqual(true, t1.IsDaylightSavingTime (d5), "E11");
160
161                 Assert.AreEqual(36000000000L /*hour*/ * 13L, t1.GetUtcOffset (d3).Ticks, "E12");
162                 Assert.AreEqual(36000000000L /*hour*/ * 12L, t1.GetUtcOffset (d4).Ticks, "E13");
163                 Assert.AreEqual(36000000000L /*hour*/ * 13L, t1.GetUtcOffset (d5).Ticks, "E14");
164
165                 // Test TimeZone methods with UTC DateTime in DST.
166                 DateTime d6 = d5.ToUniversalTime ();
167                 Assert.AreEqual(false, t1.IsDaylightSavingTime (d6), "E15");
168                 Assert.AreEqual(0, t1.GetUtcOffset (d6).Ticks, "E16");
169         }
170
171         [Test]
172         public void TestCtors ()
173         {
174                 TimeZone t1 = TimeZone.CurrentTimeZone;
175                 switch (t1.StandardName) {
176                         case "W. Europe Standard Time":
177                         case "CET":
178                                 CET (t1);
179                                 break;
180                         case "Eastern Standard Time":
181                         case "EST":
182                                 EST (t1);
183                                 break;
184                         case "Tokyo Standard Time":
185                                 TST (t1);
186                                 break;
187                         case "GMT":
188                                 GMT (t1);
189                                 break;
190                         case "NZST":
191                                 NZST (t1);
192                                 break;
193                         default:
194                                 NUnit.Framework.Assert.Ignore ("Your time zone (" + t1.StandardName + ") isn't defined in the test case");
195                                 break;
196                 }
197         }
198
199         [Test]
200         public void CurrentTimeZone_SerializationRoundtrip ()
201         {
202                 TimeZone tz = TimeZone.CurrentTimeZone;
203                 BinaryFormatter bf = new BinaryFormatter ();
204                 MemoryStream ms = new MemoryStream ();
205                 bf.Serialize (ms, tz);
206
207                 ms.Position = 0;
208                 TimeZone clone = (TimeZone) bf.Deserialize (ms);
209
210                 Assert.AreEqual (tz.DaylightName, clone.DaylightName, "DaylightName");
211                 Assert.AreEqual (tz.StandardName, clone.StandardName, "StandardName");
212         }
213
214         static private byte[] serialized_timezone = {
215                 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 
216                 0x1C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x54, 
217                 0x69, 0x6D, 0x65, 0x5A, 0x6F, 0x6E, 0x65, 0x04, 0x00, 0x00, 0x00, 0x17, 0x6D, 0x5F, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x44, 0x61, 
218                 0x79, 0x6C, 0x69, 0x67, 0x68, 0x74, 0x43, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x73, 0x0D, 0x6D, 0x5F, 0x74, 0x69, 0x63, 0x6B, 0x73, 0x4F, 
219                 0x66, 0x66, 0x73, 0x65, 0x74, 0x0E, 0x6D, 0x5F, 0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x4E, 0x61, 0x6D, 0x65, 0x0E, 0x6D, 
220                 0x5F, 0x64, 0x61, 0x79, 0x6C, 0x69, 0x67, 0x68, 0x74, 0x4E, 0x61, 0x6D, 0x65, 0x03, 0x00, 0x01, 0x01, 0x1C, 0x53, 0x79, 0x73, 0x74, 
221                 0x65, 0x6D, 0x2E, 0x43, 0x6F, 0x6C, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2E, 0x48, 0x61, 0x73, 0x68, 0x74, 0x61, 0x62, 
222                 0x6C, 0x65, 0x09, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x29, 0x17, 0xD6, 0xFF, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x15, 
223                 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6E, 0x20, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x0A, 
224                 0x04, 0x02, 0x00, 0x00, 0x00, 0x1C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x43, 0x6F, 0x6C, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 
225                 0x6E, 0x73, 0x2E, 0x48, 0x61, 0x73, 0x68, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x07, 0x00, 0x00, 0x00, 0x0A, 0x4C, 0x6F, 0x61, 0x64, 0x46, 
226                 0x61, 0x63, 0x74, 0x6F, 0x72, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x08, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x72, 0x65, 0x72, 
227                 0x10, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6F, 0x64, 0x65, 0x50, 0x72, 0x6F, 0x76, 0x69, 0x64, 0x65, 0x72, 0x08, 0x48, 0x61, 0x73, 0x68, 
228                 0x53, 0x69, 0x7A, 0x65, 0x04, 0x4B, 0x65, 0x79, 0x73, 0x06, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x73, 0x00, 0x00, 0x03, 0x03, 0x00, 0x05, 
229                 0x05, 0x0B, 0x08, 0x1C, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x43, 0x6F, 0x6C, 0x6C, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 
230                 0x2E, 0x49, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x72, 0x65, 0x72, 0x24, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0x43, 0x6F, 0x6C, 0x6C, 
231                 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x2E, 0x49, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6F, 0x64, 0x65, 0x50, 0x72, 0x6F, 0x76, 0x69, 
232                 0x64, 0x65, 0x72, 0x08, 0xEC, 0x51, 0x38, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 
233                 0x00, 0x09, 0x05, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x08, 0xCC, 0x07, 0x00, 0x00, 0x08, 
234                 0x08, 0xD5, 0x07, 0x00, 0x00, 0x08, 0x08, 0xD2, 0x07, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x06, 
235                 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x21, 0x53, 0x79, 0x73, 
236                 0x74, 0x65, 0x6D, 0x2E, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x69, 0x7A, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x44, 0x61, 0x79, 0x6C, 
237                 0x69, 0x67, 0x68, 0x74, 0x54, 0x69, 0x6D, 0x65, 0x03, 0x00, 0x00, 0x00, 0x07, 0x6D, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x05, 0x6D, 
238                 0x5F, 0x65, 0x6E, 0x64, 0x07, 0x6D, 0x5F, 0x64, 0x65, 0x6C, 0x74, 0x61, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0C, 0x00, 0x10, 0xFA, 0x0F, 
239                 0x3D, 0xF2, 0xBC, 0x88, 0x00, 0x50, 0xD5, 0xB1, 0xC1, 0x91, 0xBD, 0x88, 0x00, 0x68, 0xC4, 0x61, 0x08, 0x00, 0x00, 0x00, 0x01, 0x07, 
240                 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x50, 0x23, 0xFA, 0x07, 0x06, 0xC7, 0x88, 0x00, 0xD0, 0xE2, 0xC4, 0x0C, 0xAB, 0xC7, 
241                 0x88, 0x00, 0x68, 0xC4, 0x61, 0x08, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x50, 0x0C, 0x0F, 
242                 0xEF, 0xAB, 0xC3, 0x88, 0x00, 0x90, 0xE7, 0xB0, 0x73, 0x4B, 0xC4, 0x88, 0x00, 0x68, 0xC4, 0x61, 0x08, 0x00, 0x00, 0x00, 0x0B
243         };
244
245         [Test]
246         [Category ("NotWorking")] 
247         // 1.x - deserialize but strings are null
248         // 2.x - eexception when creating a datetime with a negative value
249         public void DeserializeKnownValue ()
250         {
251                 MemoryStream ms = new MemoryStream (serialized_timezone);
252                 BinaryFormatter bf = new BinaryFormatter ();
253                 TimeZone tz = (TimeZone) bf.Deserialize (ms);
254                 Assert.AreEqual ("Eastern Daylight Time", tz.DaylightName, "DaylightName");
255                 Assert.AreEqual ("Eastern Standard Time", tz.StandardName, "StandardName");
256         }
257
258         [Test]
259         public void ToLocalTimeAtDSTBoundaries ()
260         {
261                 TimeZone tz = TimeZone.CurrentTimeZone;
262                 DateTime dst_start_utc = tz.GetDaylightChanges(2007).Start.ToUniversalTime ();
263
264                 if (dst_start_utc == DateTime.MinValue)
265                         Assert.Ignore ("Couldn't get beginning of daylight saving time in 2007.");
266                 Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Subtract (new TimeSpan (0, 1, 0))) < tz.ToLocalTime (dst_start_utc), "0:1:59 < 0:3:00");
267                 Assert.IsTrue (tz.ToLocalTime (dst_start_utc) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (0, 1, 0))), "0:3:00 < 0:3:01");
268                 Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (0, 1, 0))) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (0, 59, 0))), "0:3:01 < 0:3:59");
269                 Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (0, 59, 0))) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (1, 0, 0))), "0:3:59 < 0:4:00");
270                 Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (1, 0, 0))) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (1, 1, 0))), "0:4:00 < 0:4:01");
271         }
272
273                 [Test]
274                 public void GetUtcOffsetAtDSTBoundary ()
275                 {
276                         /*
277                          * Getting a definitive list of timezones which do or don't observe Daylight
278                          * Savings is difficult (can't say America's or USA definitively) and lengthy see 
279                          *
280                          * http://en.wikipedia.org/wiki/Daylight_saving_time_by_country
281                          *
282                          * as a good starting point for a list.
283                          *
284                          * The following are SOME of the timezones/regions which do support daylight savings.
285                          *
286                          * Pacific/Auckland
287                          * Pacific/Sydney
288                          * USA (EST, CST, MST, PST, AKST) note this does not cover all states or regions
289                          * Europe/London (GMT)
290                          * CET (member states of the European Union)
291                          *
292                          * This test should work in all the above timezones
293                          */
294
295
296                         TimeZone tz = TimeZone.CurrentTimeZone;
297                         int year = DateTime.Now.Year;
298                         DaylightTime daylightChanges = tz.GetDaylightChanges(year);
299                         DateTime dst_end = daylightChanges.End;
300
301                         if (dst_end == DateTime.MinValue)
302                                 Assert.Ignore (tz.StandardName + " did not observe daylight saving time during " + year + ".");
303
304                         var standardOffset = tz.GetUtcOffset(daylightChanges.Start.AddMinutes(-1));
305
306                         Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end));
307                         Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end.Add (daylightChanges.Delta.Negate ().Add (TimeSpan.FromSeconds(1)))));
308                         Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end.Add(daylightChanges.Delta.Negate ())));
309                         Assert.AreNotEqual(standardOffset, tz.GetUtcOffset (dst_end.Add(daylightChanges.Delta.Negate ().Add (TimeSpan.FromSeconds(-1)))));
310                 }
311
312
313                 [Test]
314                 public void StaticProperties ()
315                 {
316                         Assert.IsNotNull (TimeZoneInfo.Local, "Local");
317                         Assert.IsNotNull (TimeZoneInfo.Utc, "Utc");
318                 }
319                 
320                 [Test]
321                 public void FindSystemTimeZoneById ()
322                 {
323                         TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (TimeZoneInfoTest.MapTimeZoneId ("Canada/Eastern"));
324                         Assert.IsTrue ("EDT" == tzi.DaylightName || "Eastern Daylight Time" == tzi.DaylightName, "DaylightName");
325                         Assert.IsTrue ("EST" == tzi.StandardName || "Eastern Standard Time" == tzi.StandardName, "StandardName");
326                         Assert.IsTrue (tzi.SupportsDaylightSavingTime, "SupportsDaylightSavingTime");
327                 }
328
329                 [Test]
330                 public void OldEraToLocalTime ()
331                 {
332                         TimeSpan offset = TimeSpan.Zero;
333                         var dto = new DateTimeOffset (new DateTime (1900, 1, 1).Ticks, offset);
334
335                         // Should never throw
336                         dto.ToLocalTime ();
337                 }
338
339 #if MOBILE
340                 // On device we cannot read the OS file system to look for /etc/localtime
341                 // and /usr/share/zoneinfo - so we must initialize the BCL TimeZoneInfo
342                 // from NSTimeZoneInfo. The tests here check the code paths between the
343                 // two types - if they break then TimeZoneInfo work work at all
344                 // ref: http://bugzilla.xamarin.com/show_bug.cgi?id=1790
345                 
346                 bool incomplete_data_on_simulator_only_bug;
347
348                 [Test]
349                 public void GetSystemTimeZones ()
350                 {
351                         // if test is executed a second time then it report less than 400 (about 127) items available
352                         if (incomplete_data_on_simulator_only_bug)
353                                 Assert.Ignore ("known to fail on some iOS simulator versions - see source comments");
354                         
355                         try {
356                                 Assert.That (TimeZoneInfo.GetSystemTimeZones ().Count, Is.GreaterThan (400), "GetSystemTimeZones");
357                         } catch (NullReferenceException) {
358                                 // that's a weird one. It failed on iOS 5.1 *beta* simulator (on Lion) but it worked on *final*
359                                 // now it fails on Snow Leopard the same way (incomplete data) with iOS5 simulator (OS update ?)
360                                 // but it *never*ever* failed on devices
361                                 incomplete_data_on_simulator_only_bug = true;
362 #if XAMCORE_2_0 || MONOTOUCH
363
364 #if XAMCORE_2_0
365                                 if (ObjCRuntime.Runtime.Arch == ObjCRuntime.Arch.SIMULATOR)
366 #elif MONOTOUCH
367                                 if (MonoTouch.ObjCRuntime.Runtime.Arch == MonoTouch.ObjCRuntime.Arch.SIMULATOR)
368 #endif
369                                         Assert.Ignore ("known to fail on some iOS simulator versions - see source comments");
370 #endif // XAMCORE_2_0 || MONOTOUCH
371                         }
372                 }
373 #endif
374         }
375 }