Ensure we can roundtrip 'Local' (special case) timezone. Fix bug #326
[mono.git] / mcs / class / System.Core / Test / System / TimeZoneInfoTest.cs
1 /*
2  * TimeZoneInfo.Tests
3  *
4  * Author(s)
5  *      Stephane Delcroix <stephane@delcroix.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  * 
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26
27 using System;
28 using System.Collections;
29
30 using NUnit.Framework;
31 #if NET_2_0
32 namespace MonoTests.System
33 {
34         public class TimeZoneInfoTest
35         {
36                 [TestFixture]
37                 public class PropertiesTests
38                 {
39                         [Test]
40                         public void GetLocal ()
41                         {
42                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
43                                         return;
44                                 TimeZoneInfo local = TimeZoneInfo.Local;
45                                 Assert.IsNotNull (local);
46                                 Assert.IsTrue (true);
47                         }
48                 }
49
50                 [TestFixture]
51                 public class CreateCustomTimezoneTests
52                 {
53                         [Test]
54                         [ExpectedException (typeof (ArgumentNullException))]
55                         public void IdIsNullException ()
56                         {
57                                 TimeZoneInfo.CreateCustomTimeZone (null, new TimeSpan (0), null, null); 
58                         }
59                 
60                         [Test]
61                         [ExpectedException (typeof (ArgumentException))]
62                         public void IdIsEmptyString ()
63                         {
64                                 TimeZoneInfo.CreateCustomTimeZone ("", new TimeSpan (0), null, null);   
65                         }
66                 
67                         [Test]
68                         [ExpectedException (typeof (ArgumentException))]
69                         public void OffsetIsNotMinutes ()
70                         {
71                                 TimeZoneInfo.CreateCustomTimeZone ("mytimezone", new TimeSpan (0, 0, 55), null, null);  
72                         }
73                 
74                         [Test]
75                         [ExpectedException (typeof (ArgumentOutOfRangeException))]
76                         public void OffsetTooBig ()
77                         {
78                                 TimeZoneInfo.CreateCustomTimeZone ("mytimezone", new TimeSpan (14, 1, 0), null, null);
79                         }
80                 
81                         [Test]
82                         [ExpectedException (typeof (ArgumentOutOfRangeException))]
83                         public void OffsetTooSmall ()
84                         {
85                                 TimeZoneInfo.CreateCustomTimeZone ("mytimezone", - new TimeSpan (14, 1, 0), null, null);
86                         }
87                 
88                 #if STRICT
89                         [Test]
90                         [ExpectedException (typeof (ArgumentException))]
91                         public void IdLongerThan32 ()
92                         {
93                                 TimeZoneInfo.CreateCustomTimeZone ("12345678901234567890123456789012345", new TimeSpan (0), null, null);        
94                         }       
95                 #endif
96                 
97                         [Test]
98                         [ExpectedException (typeof (InvalidTimeZoneException))]
99                         public void AdjustmentRulesOverlap ()
100                         {
101                                 TimeZoneInfo.TransitionTime s1 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 3, 2, DayOfWeek.Sunday);
102                                 TimeZoneInfo.TransitionTime e1 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 10, 2, DayOfWeek.Sunday);
103                                 TimeZoneInfo.AdjustmentRule r1 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (new DateTime (2000,1,1), new DateTime (2005,1,1), new TimeSpan (1,0,0), s1, e1);
104                                 TimeZoneInfo.TransitionTime s2 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 2, 2, DayOfWeek.Sunday);
105                                 TimeZoneInfo.TransitionTime e2 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 11, 2, DayOfWeek.Sunday);
106                                 TimeZoneInfo.AdjustmentRule r2 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (new DateTime (2004,1,1), new DateTime (2007,1,1), new TimeSpan (1,0,0), s2, e2);
107                                 TimeZoneInfo.CreateCustomTimeZone ("mytimezone", new TimeSpan (6,0,0),null,null,null,new TimeZoneInfo.AdjustmentRule[] {r1, r2});
108                         }
109                 
110                         [Test]
111                         [ExpectedException (typeof (InvalidTimeZoneException))]
112                         public void RulesNotOrdered ()
113                         {
114                                 TimeZoneInfo.TransitionTime s1 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 3, 2, DayOfWeek.Sunday);
115                                 TimeZoneInfo.TransitionTime e1 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 10, 2, DayOfWeek.Sunday);
116                                 TimeZoneInfo.AdjustmentRule r1 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (new DateTime (2000,1,1), new DateTime (2005,1,1), new TimeSpan (1,0,0), s1, e1);
117                                 TimeZoneInfo.TransitionTime s2 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 2, 2, DayOfWeek.Sunday);
118                                 TimeZoneInfo.TransitionTime e2 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 11, 2, DayOfWeek.Sunday);
119                                 TimeZoneInfo.AdjustmentRule r2 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (new DateTime (2006,1,1), new DateTime (2007,1,1), new TimeSpan (1,0,0), s2, e2);
120                                 TimeZoneInfo.CreateCustomTimeZone ("mytimezone", new TimeSpan (6,0,0),null,null,null,new TimeZoneInfo.AdjustmentRule[] {r2, r1});
121                         }
122                 
123                         [Test]
124                         [ExpectedException (typeof (InvalidTimeZoneException))]
125                         public void OffsetOutOfRange ()
126                         {
127                                 TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 3, 2, DayOfWeek.Sunday);
128                                 TimeZoneInfo.TransitionTime endTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 10, 2, DayOfWeek.Sunday);
129                                 TimeZoneInfo.AdjustmentRule rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (new DateTime (2000,1,1), new DateTime (2005,1,1), new TimeSpan (3,0,0), startTransition, endTransition);
130                                 TimeZoneInfo.CreateCustomTimeZone ("mytimezone", new TimeSpan (12,0,0),null,null,null,new TimeZoneInfo.AdjustmentRule[] {rule});
131                         }
132                 
133                         [Test]
134                         [ExpectedException (typeof (InvalidTimeZoneException))]
135                         public void NullRule ()
136                         {
137                                 TimeZoneInfo.CreateCustomTimeZone ("mytimezone", new TimeSpan (12,0,0),null,null,null,new TimeZoneInfo.AdjustmentRule[] {null});
138                         }
139                 
140                         [Test]
141                         [ExpectedException (typeof (InvalidTimeZoneException))]
142                         public void MultiplesRulesForDate ()
143                         {
144                                 TimeZoneInfo.TransitionTime s1 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 3, 2, DayOfWeek.Sunday);
145                                 TimeZoneInfo.TransitionTime e1 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 10, 2, DayOfWeek.Sunday);
146                                 TimeZoneInfo.AdjustmentRule r1 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (new DateTime (2000,1,1), new DateTime (2005,1,1), new TimeSpan (1,0,0), s1, e1);
147                                 TimeZoneInfo.TransitionTime s2 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 2, 2, DayOfWeek.Sunday);
148                                 TimeZoneInfo.TransitionTime e2 = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,4,0,0), 11, 2, DayOfWeek.Sunday);
149                                 TimeZoneInfo.AdjustmentRule r2 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (new DateTime (2005,1,1), new DateTime (2007,1,1), new TimeSpan (1,0,0), s2, e2);
150                                 TimeZoneInfo.CreateCustomTimeZone ("mytimezone", new TimeSpan (6,0,0),null,null,null,new TimeZoneInfo.AdjustmentRule[] {r1, r2});
151                         }
152                 }
153                 
154                 [TestFixture]
155                 public class IsDaylightSavingTimeTests
156                 {
157                         TimeZoneInfo london;
158                 
159                         [SetUp]
160                         public void CreateTimeZones ()
161                         {
162                                 TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,1,0,0), 3, 5, DayOfWeek.Sunday);
163                                 TimeZoneInfo.TransitionTime end = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,2,0,0), 10, 5, DayOfWeek.Sunday);
164                                 TimeZoneInfo.AdjustmentRule rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (DateTime.MinValue.Date, DateTime.MaxValue.Date, new TimeSpan (1,0,0), start, end);
165                                 london = TimeZoneInfo.CreateCustomTimeZone ("Europe/London", new TimeSpan (0), "Europe/London", "British Standard Time", "British Summer Time", new TimeZoneInfo.AdjustmentRule [] {rule});
166                         }
167                 
168                         [Test]
169                         public void NoDSTInUTC ()
170                         {
171                                 DateTime june01 = new DateTime (2007, 06, 01);
172                                 Assert.IsFalse (TimeZoneInfo.Utc.IsDaylightSavingTime (june01));
173                         }
174                 
175                         [Test]
176                         public void DSTInLondon ()
177                         {
178                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
179                                         return;
180                                 DateTime june01 = new DateTime (2007, 06, 01);
181                                 DateTime xmas = new DateTime (2007, 12, 25);
182                                 Assert.IsTrue (london.IsDaylightSavingTime (june01), "June 01 is DST in London");
183                                 Assert.IsFalse (london.IsDaylightSavingTime (xmas), "Xmas is not DST in London");
184                         }
185                 
186                         [Test]
187                         public void DSTTransisions ()
188                         {
189                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
190                                         return;
191                                 DateTime beforeDST = new DateTime (2007, 03, 25, 0, 59, 59, DateTimeKind.Unspecified);
192                                 DateTime startDST = new DateTime (2007, 03, 25, 2, 0, 0, DateTimeKind.Unspecified);
193                                 DateTime endDST = new DateTime (2007, 10, 28, 1, 59, 59, DateTimeKind.Unspecified);
194                                 DateTime afterDST = new DateTime (2007, 10, 28, 2, 0, 0, DateTimeKind.Unspecified);
195                                 Assert.IsFalse (london.IsDaylightSavingTime (beforeDST), "Just before DST");
196                                 Assert.IsTrue (london.IsDaylightSavingTime (startDST), "the first seconds of DST");
197                                 Assert.IsTrue (london.IsDaylightSavingTime (endDST), "The last seconds of DST");
198                                 Assert.IsFalse (london.IsDaylightSavingTime (afterDST), "Just after DST");
199                         }
200                 
201                         [Test]
202                         public void DSTTransisionsUTC ()
203                         {
204                                 DateTime beforeDST = new DateTime (2007, 03, 25, 0, 59, 59, DateTimeKind.Utc);
205                                 DateTime startDST = new DateTime (2007, 03, 25, 1, 0, 0, DateTimeKind.Utc);
206                                 DateTime endDST = new DateTime (2007, 10, 28, 0, 59, 59, DateTimeKind.Utc);
207                                 DateTime afterDST = new DateTime (2007, 10, 28, 1, 0, 0, DateTimeKind.Utc);
208                                 Assert.IsFalse (london.IsDaylightSavingTime (beforeDST), "Just before DST");
209                                 Assert.IsTrue (london.IsDaylightSavingTime (startDST), "the first seconds of DST");
210                                 Assert.IsTrue (london.IsDaylightSavingTime (endDST), "The last seconds of DST");
211                                 Assert.IsFalse (london.IsDaylightSavingTime (afterDST), "Just after DST");
212                         }
213                 
214                 #if SLOW_TESTS
215                         [Test]
216                         public void MatchTimeZoneBehavior ()
217                         {
218                                 TimeZone tzone = TimeZone.CurrentTimeZone;
219                                 TimeZoneInfo local = TimeZoneInfo.Local;
220                                 for (DateTime date = new DateTime (2007, 01, 01, 0, 0, 0, DateTimeKind.Local); date < new DateTime (2007, 12, 31, 23, 59, 59); date += new TimeSpan (0,1,0)) {
221                                         date = DateTime.SpecifyKind (date, DateTimeKind.Local);
222                                         if (local.IsInvalidTime (date))
223                                                 continue;
224                                         Assert.IsTrue (tzone.IsDaylightSavingTime (date) == local.IsDaylightSavingTime (date));
225                                 }
226                         }
227                 #endif
228                 }
229                 
230                 [TestFixture]
231                 public class ConvertTimeTests
232                 {
233                         TimeZoneInfo london;
234                 
235                         [SetUp]
236                         public void CreateTimeZones ()
237                         {
238                                 TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,1,0,0), 3, 5, DayOfWeek.Sunday);
239                                 TimeZoneInfo.TransitionTime end = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,2,0,0), 10, 5, DayOfWeek.Sunday);
240                                 TimeZoneInfo.AdjustmentRule rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (DateTime.MinValue.Date, DateTime.MaxValue.Date, new TimeSpan (1,0,0), start, end);
241                                 london = TimeZoneInfo.CreateCustomTimeZone ("Europe/London", new TimeSpan (0), "Europe/London", "British Standard Time", "British Summer Time", new TimeZoneInfo.AdjustmentRule [] {rule});
242                         }
243                 
244                         [Test]
245                         [ExpectedException (typeof (ArgumentException))]
246                         public void ConvertFromUtc_KindIsLocalException ()
247                         {
248                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
249                                         throw new ArgumentException ();
250                                 TimeZoneInfo.ConvertTimeFromUtc (new DateTime (2007, 5, 3, 11, 8, 0, DateTimeKind.Local), TimeZoneInfo.Local);  
251                         }
252                 
253                         [Test]
254                         [ExpectedException (typeof (ArgumentNullException))]
255                         public void ConvertFromUtc_DestinationTimeZoneIsNullException ()
256                         {
257                                 TimeZoneInfo.ConvertTimeFromUtc (new DateTime (2007, 5, 3, 11, 8, 0), null);            
258                         }
259                 
260                         [Test]
261                         public void ConvertFromUtc_DestinationIsUTC ()
262                         {
263                                 DateTime now = DateTime.UtcNow;
264                                 DateTime converted = TimeZoneInfo.ConvertTimeFromUtc (now, TimeZoneInfo.Utc);
265                                 Assert.AreEqual (now, converted);
266                         }
267                         
268                         [Test]
269                         public void ConvertFromUTC_ConvertInWinter ()
270                         {
271                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
272                                         return;
273                                 DateTime utc = new DateTime (2007, 12, 25, 12, 0, 0);
274                                 DateTime converted = TimeZoneInfo.ConvertTimeFromUtc (utc, london);
275                                 Assert.AreEqual (utc, converted);
276                         }
277                 
278                         [Test]
279                         public void ConvertFromUtc_ConvertInSummer ()
280                         {
281                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
282                                         return;
283                                 DateTime utc = new DateTime (2007, 06, 01, 12, 0, 0);
284                                 DateTime converted = TimeZoneInfo.ConvertTimeFromUtc (utc, london);
285                                 Assert.AreEqual (utc + new TimeSpan (1,0,0), converted);
286                         }
287                 
288                         [Test]
289                         public void ConvertToUTC_KindIsUtc ()
290                         {
291                                 DateTime now = DateTime.UtcNow;
292                                 Assert.AreEqual (now.Kind, DateTimeKind.Utc);
293                                 DateTime converted = TimeZoneInfo.ConvertTimeToUtc (now);
294                                 Assert.AreEqual (now, converted);
295                         }
296                 
297                         [Test]
298                         [ExpectedException (typeof (ArgumentException))]
299                         public void ConvertToUTC_KindIsUTCButSourceIsNot ()
300                         {
301                                 TimeZoneInfo.ConvertTimeToUtc (new DateTime (2007, 5, 3, 12, 8, 0, DateTimeKind.Utc), london);
302                         }
303                 
304                         [Test]
305                         [ExpectedException (typeof (ArgumentException))]
306                         public void ConvertToUTC_KindIsLocalButSourceIsNot ()
307                         {
308                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
309                                         throw new ArgumentException ();
310                                 TimeZoneInfo.ConvertTimeToUtc (new DateTime (2007, 5, 3, 12, 8, 0, DateTimeKind.Local), london);        
311                         }
312                 
313                         [Test]
314                         [ExpectedException (typeof (ArgumentException))]
315                         public void ConvertToUTC_InvalidDate ()
316                         {
317                                 TimeZoneInfo.ConvertTimeToUtc (new DateTime (2007, 3, 25, 1, 30, 0), london);
318                         }
319                 
320                         [Test]
321                         [ExpectedException (typeof (ArgumentNullException))]
322                         public void ConvertToUTC_SourceIsNull ()
323                         {
324                                 TimeZoneInfo.ConvertTimeToUtc (new DateTime (2007, 5, 3, 12, 16, 0), null);
325                         }
326                 
327                 #if SLOW_TESTS
328                         [Test]
329                         public void ConvertToUtc_MatchDateTimeBehavior ()
330                         {
331                                 for (DateTime date = new DateTime (2007, 01, 01, 0, 0, 0); date < new DateTime (2007, 12, 31, 23, 59, 59); date += new TimeSpan (0,1,0)) {
332                                         Assert.AreEqual (TimeZoneInfo.ConvertTimeToUtc (date), date.ToUniversalTime ());
333                                 }
334                         }
335                 #endif
336                 
337                         [Test]
338                         public void ConvertFromToUtc ()
339                         {
340                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
341                                         return;
342                                 DateTime utc = DateTime.UtcNow;
343                                 Assert.AreEqual (utc.Kind, DateTimeKind.Utc);
344                                 DateTime converted = TimeZoneInfo.ConvertTimeFromUtc (utc, london);
345                                 Assert.AreEqual (converted.Kind, DateTimeKind.Unspecified);
346                                 DateTime back = TimeZoneInfo.ConvertTimeToUtc (converted, london);
347                                 Assert.AreEqual (back.Kind, DateTimeKind.Utc);
348                                 Assert.AreEqual (utc, back);
349                 
350                         }
351                 }
352                 
353                 [TestFixture]
354                 public class IsInvalidTimeTests
355                 {
356                         TimeZoneInfo london;
357                 
358                         [SetUp]
359                         public void CreateTimeZones ()
360                         {
361                                 TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,1,0,0), 3, 5, DayOfWeek.Sunday);
362                                 TimeZoneInfo.TransitionTime end = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,2,0,0), 10, 5, DayOfWeek.Sunday);
363                                 TimeZoneInfo.AdjustmentRule rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (DateTime.MinValue.Date, DateTime.MaxValue.Date, new TimeSpan (1,0,0), start, end);
364                                 london = TimeZoneInfo.CreateCustomTimeZone ("Europe/London", new TimeSpan (0), "Europe/London", "British Standard Time", "British Summer Time", new TimeZoneInfo.AdjustmentRule [] {rule});
365                         }
366                 
367                 #if SLOW_TESTS
368                         [Test]
369                         public void UTCDate ()
370                         {
371                                 for (DateTime date = new DateTime (2007, 01, 01, 0, 0, 0); date < new DateTime (2007, 12, 31, 23, 59, 59); date += new TimeSpan (0,1,0)) {
372                                         date = DateTime.SpecifyKind (date, DateTimeKind.Utc);
373                                         Assert.IsFalse (london.IsInvalidTime (date));
374                                 }
375                         }
376                 #endif
377                         [Test]
378                         public void InvalidDates ()
379                         {
380                                 Assert.IsFalse (london.IsInvalidTime (new DateTime (2007, 03, 25, 0, 59, 59)));
381                                 Assert.IsTrue (london.IsInvalidTime (new DateTime (2007, 03, 25, 1, 0, 0)));
382                                 Assert.IsTrue (london.IsInvalidTime (new DateTime (2007, 03, 25, 1, 59, 59)));
383                                 Assert.IsFalse (london.IsInvalidTime (new DateTime (2007, 03, 25, 2, 0, 0)));
384                         }
385                 }
386                 
387                 [TestFixture]
388                 public class IsAmbiguousTimeTests
389                 {
390                         TimeZoneInfo london;
391                 
392                         [SetUp]
393                         public void CreateTimeZones ()
394                         {
395                                 TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,1,0,0), 3, 5, DayOfWeek.Sunday);
396                                 TimeZoneInfo.TransitionTime end = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,2,0,0), 10, 5, DayOfWeek.Sunday);
397                                 TimeZoneInfo.AdjustmentRule rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (DateTime.MinValue.Date, DateTime.MaxValue.Date, new TimeSpan (1,0,0), start, end);
398                                 london = TimeZoneInfo.CreateCustomTimeZone ("Europe/London", new TimeSpan (0), "Europe/London", "British Standard Time", "British Summer Time", new TimeZoneInfo.AdjustmentRule [] {rule});
399                         }
400                 
401                         [Test]
402                         public void AmbiguousDates ()
403                         {
404                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
405                                         return;
406                                 Assert.IsFalse (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 1, 0, 0)));
407                                 Assert.IsTrue (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 1, 0, 1)));
408                                 Assert.IsTrue (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 2, 0, 0)));
409                                 Assert.IsFalse (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 2, 0, 1)));
410                         }
411                 
412                         [Test]
413                         public void AmbiguousUTCDates ()
414                         {
415                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
416                                         return;
417                                 Assert.IsFalse (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 0, 0, 0, DateTimeKind.Utc)));
418                                 Assert.IsTrue (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 0, 0, 1, DateTimeKind.Utc)));
419                                 Assert.IsTrue (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 0, 59, 59, DateTimeKind.Utc)));
420                                 Assert.IsFalse (london.IsAmbiguousTime (new DateTime (2007, 10, 28, 1, 0, 0, DateTimeKind.Utc)));
421                         }
422                 
423                 #if SLOW_TESTS
424                         [Test]
425                         public void AmbiguousInUTC ()
426                         {
427                                 for (DateTime date = new DateTime (2007, 01, 01, 0, 0, 0); date < new DateTime (2007, 12, 31, 23, 59, 59); date += new TimeSpan (0,1,0)) {
428                                         Assert.IsFalse (TimeZoneInfo.Utc.IsAmbiguousTime (date));
429                                 }
430                         }
431                 #endif
432                 }
433                 
434                 [TestFixture]
435                 public class GetSystemTimeZonesTests
436                 {
437                         [Test]
438                         public void NotEmpty ()
439                         {
440                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
441                                         return;
442                                 global::System.Collections.ObjectModel.ReadOnlyCollection<TimeZoneInfo> systemTZ = TimeZoneInfo.GetSystemTimeZones ();
443                                 Assert.IsNotNull(systemTZ, "SystemTZ is null");
444                                 Assert.IsFalse (systemTZ.Count == 0, "SystemTZ is empty");
445                         }
446                 
447                         [Test]
448                         public void ContainsBrussels ()
449                         {
450                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
451                                         return;
452                                 global::System.Collections.ObjectModel.ReadOnlyCollection<TimeZoneInfo> systemTZ = TimeZoneInfo.GetSystemTimeZones ();
453                                 foreach (TimeZoneInfo tz in systemTZ) {
454                                         if (tz.Id == "Europe/Brussels")
455                                                 return;
456                                 }
457                                 Assert.Fail ("Europe/Brussels not found in SystemTZ");
458                         }
459                 }
460                 
461                 [TestFixture]
462                 public class FindSystemTimeZoneByIdTests
463                 {
464                         [Test]
465                         [ExpectedException (typeof (ArgumentNullException))]
466                         public void NullId ()
467                         {
468                                 TimeZoneInfo.FindSystemTimeZoneById (null);
469                         }
470                 
471                         [Test]
472                         [ExpectedException (typeof (TimeZoneNotFoundException))]
473                         public void NonSystemTimezone ()
474                         {
475                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
476                                         throw new TimeZoneNotFoundException ();
477                                 TimeZoneInfo.FindSystemTimeZoneById ("Neverland/The_Lagoon");
478                         }
479                 
480                         [Test]
481                         public void FindBrusselsTZ ()
482                         {
483                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
484                                         return;
485                                 TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
486                                 Assert.IsNotNull (brussels);
487                         }
488                 
489                         [Test]
490                         public void OffsetIsCorrectInKinshasa ()
491                         {
492                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
493                                         return;
494                                 TimeZoneInfo kin = TimeZoneInfo.FindSystemTimeZoneById ("Africa/Kinshasa");
495                                 Assert.AreEqual (new TimeSpan (1,0,0), kin.BaseUtcOffset, "BaseUtcOffset in Kinshasa is not +1h");
496                         }
497                 
498                         [Test]
499                         public void OffsetIsCorrectInBrussels ()
500                         {
501                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
502                                         return;
503                                 TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
504                                 Assert.AreEqual (new TimeSpan (1,0,0), brussels.BaseUtcOffset, "BaseUtcOffset for Brussels is not +1h");
505                         }
506                 
507                         [Test]
508                         public void NoDSTInKinshasa ()
509                         {
510                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
511                                         return;
512                                 TimeZoneInfo kin = TimeZoneInfo.FindSystemTimeZoneById ("Africa/Kinshasa");
513                                 Assert.IsFalse (kin.SupportsDaylightSavingTime);
514                         }
515                 
516                         [Test]
517                         public void BrusselsSupportsDST ()
518                         {
519                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
520                                         return;
521                                 TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
522                                 Assert.IsTrue (brussels.SupportsDaylightSavingTime);
523                         }
524                 
525                         [Test]
526                         public void MelbourneSupportsDST ()
527                         {
528                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
529                                         return;
530                                 TimeZoneInfo melbourne = TimeZoneInfo.FindSystemTimeZoneById ("Australia/Melbourne");
531                                 Assert.IsTrue (melbourne.SupportsDaylightSavingTime);
532                         }
533                 
534                         [Test]
535                         public void RomeAndVaticanSharesTime ()
536                         {
537                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
538                                         return;
539                                 TimeZoneInfo rome = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Rome");
540                                 TimeZoneInfo vatican = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Vatican");
541                                 Assert.IsTrue (rome.HasSameRules (vatican));
542                         }
543
544                         [Test]
545                         public void FindSystemTimeZoneById_Local_Roundtrip ()
546                         {
547                                 Assert.AreEqual (TimeZoneInfo.Local.Id, TimeZoneInfo.FindSystemTimeZoneById (TimeZoneInfo.Local.Id).Id);
548                         }
549
550                         [Test]
551                         public void Test326 ()
552                         {
553                                 DateTime utc = DateTime.UtcNow;
554                                 DateTime local = TimeZoneInfo.ConvertTime (utc, TimeZoneInfo.Utc, TimeZoneInfo.FindSystemTimeZoneById (TimeZoneInfo.Local.Id));
555                                 Assert.AreEqual (local, utc + TimeZoneInfo.Local.GetUtcOffset (utc), "ConvertTime/Local");
556                         }
557                 
558                 #if SLOW_TESTS
559                         [Test]
560                         public void BrusselsAdjustments ()
561                         {
562                                 TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,2,0,0), 3, 5, DayOfWeek.Sunday);
563                                 TimeZoneInfo.TransitionTime end = TimeZoneInfo.TransitionTime.CreateFloatingDateRule (new DateTime (1,1,1,3,0,0), 10, 5, DayOfWeek.Sunday);
564                                 TimeZoneInfo.AdjustmentRule rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (DateTime.MinValue.Date, DateTime.MaxValue.Date, new TimeSpan (1,0,0), start, end);
565                                 TimeZoneInfo brussels = TimeZoneInfo.CreateCustomTimeZone ("Europe/Brussels", new TimeSpan (1, 0, 0), "Europe/Brussels", "", "", new TimeZoneInfo.AdjustmentRule [] {rule});
566                 
567                                 TimeZoneInfo brussels_sys = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
568                 
569                                 for (DateTime date = new DateTime (2006, 01, 01, 0, 0, 0, DateTimeKind.Local); date < new DateTime (2007, 12, 31, 23, 59, 59); date += new TimeSpan (0,30,0)) {
570                                         Assert.AreEqual (brussels.GetUtcOffset (date), brussels_sys.GetUtcOffset (date));
571                                         Assert.AreEqual (brussels.IsDaylightSavingTime (date), brussels_sys.IsDaylightSavingTime (date));
572                                 }               
573                         }
574                 #endif
575                 }
576                 
577                 [TestFixture]
578                 public class GetAmbiguousTimeOffsetsTests
579                 {
580                         [Test]
581                         [ExpectedException (typeof(ArgumentException))]
582                         public void DateIsNotAmbiguous ()
583                         {
584                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
585                                         throw new ArgumentException ();
586                                 TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
587                                 DateTime date = new DateTime (2007, 05, 11, 11, 40, 00);
588                                 brussels.GetAmbiguousTimeOffsets (date);
589                         }
590                 
591                         [Test]
592                         public void AmbiguousOffsets ()
593                         {
594                                 if (Environment.OSVersion.Platform != PlatformID.Unix)
595                                         return;
596                                 TimeZoneInfo brussels = TimeZoneInfo.FindSystemTimeZoneById ("Europe/Brussels");
597                                 DateTime date = new DateTime (2007, 10, 28, 2, 30, 00);
598                                 Assert.IsTrue (brussels.IsAmbiguousTime (date));
599                                 Assert.AreEqual (2, brussels.GetAmbiguousTimeOffsets (date).Length);
600                                 Assert.AreEqual (new TimeSpan[] {new TimeSpan (1, 0, 0), new TimeSpan (2, 0, 0)}, brussels.GetAmbiguousTimeOffsets (date));
601                         }
602                 }
603
604                 [TestFixture]
605                 public class HasSameRulesTests
606                 {
607                         [Test]
608                         public void NullAdjustments () //bnc #391011
609                         {
610                                 TimeZoneInfo utc = TimeZoneInfo.Utc;
611                                 TimeZoneInfo custom = TimeZoneInfo.CreateCustomTimeZone ("Custom", new TimeSpan (0), "Custom", "Custom");
612                                 Assert.IsTrue (utc.HasSameRules (custom));
613                         }
614                 }
615         }
616 }
617 #endif