Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / corlib / Test / System / TimeSpanTest.cs
1 //
2 // TimeSpanTest.cs - NUnit Test Cases for the System.TimeSpan struct
3 //
4 // Authors:
5 //      Duco Fijma (duco@lorentz.xs4all.nl)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // (C) 2001 Duco Fijma
9 // Copyright (C) 2004 Novell (http://www.novell.com)
10 //
11
12 using NUnit.Framework;
13 using System;
14 using System.Globalization;
15 using System.Threading;
16
17 namespace MonoTests.System
18 {
19
20 [TestFixture]
21 public class TimeSpanTest {
22
23         private void Debug (TimeSpan ts) 
24         {
25                 Console.Out.WriteLine ("Days {0}", ts.Days);
26                 Console.Out.WriteLine ("Hours {0}", ts.Hours);
27                 Console.Out.WriteLine ("Minutes {0}", ts.Minutes);
28                 Console.Out.WriteLine ("Seconds {0}", ts.Seconds);
29                 Console.Out.WriteLine ("Milliseconds {0}", ts.Milliseconds);
30                 Console.Out.WriteLine ("Ticks {0}", ts.Ticks);
31         }
32
33         public void TestCtors ()
34         {
35                 TimeSpan t1 = new TimeSpan (1234567890);
36
37                 Assert.AreEqual ("00:02:03.4567890", t1.ToString (), "A1");
38                 t1 = new TimeSpan (1,2,3);
39                 Assert.AreEqual ("01:02:03", t1.ToString (), "A2");
40                 t1 = new TimeSpan (1,2,3,4);
41                 Assert.AreEqual ("1.02:03:04", t1.ToString (), "A3");
42                 t1 = new TimeSpan (1,2,3,4,5);
43                 Assert.AreEqual ("1.02:03:04.0050000", t1.ToString (), "A4");
44                 t1 = new TimeSpan (-1,2,-3,4,-5);
45                 Assert.AreEqual ("-22:02:56.0050000", t1.ToString (), "A5");
46                 t1 = new TimeSpan (0,25,0,0,0);
47                 Assert.AreEqual ("1.01:00:00", t1.ToString (), "A6");
48         }
49
50         [Test]
51         [ExpectedException (typeof (ArgumentOutOfRangeException))]
52         public void DaysOverflow () 
53         {
54                 int days = (int) (Int64.MaxValue / TimeSpan.TicksPerDay) + 1;
55                 TimeSpan ts = new TimeSpan (days, 0, 0, 0, 0);
56         }
57
58         [Test]
59 #if NET_2_0
60         [ExpectedException (typeof (ArgumentOutOfRangeException))]
61         [Category ("NotWorking")]
62 #endif
63         public void TemporaryOverflow () 
64         {
65                 // calculating part of this results in overflow (days)
66                 // but the negative hours, minutes, seconds & ms correct this
67                 int days = (int) (Int64.MaxValue / TimeSpan.TicksPerDay) + 1;
68                 TimeSpan ts = new TimeSpan (days, Int32.MinValue, Int32.MinValue, Int32.MinValue, Int32.MinValue);
69                 Assert.AreEqual (10650320, ts.Days, "Days");
70                 Assert.AreEqual (0, ts.Hours, "Hours");
71                 Assert.AreEqual (14, ts.Minutes, "Minutes");
72                 Assert.AreEqual (28, ts.Seconds, "Seconds");
73                 Assert.AreEqual (352, ts.Milliseconds, "Milliseconds");
74                 Assert.AreEqual (9201876488683520000, ts.Ticks, "Ticks");
75         }
76
77         [Test]
78 #if NET_2_0
79         [ExpectedException (typeof (ArgumentOutOfRangeException))]
80         [Category ("NotWorking")]
81 #endif
82         public void NoOverflowInHoursMinsSecondsMS () 
83         {
84                 TimeSpan ts = new TimeSpan (0, Int32.MaxValue, Int32.MaxValue, Int32.MaxValue, Int32.MaxValue);
85                 Assert.AreEqual (24879, ts.Days, "Days");
86                 Assert.AreEqual (22, ts.Hours, "Hours");
87                 Assert.AreEqual (44, ts.Minutes, "Minutes");
88                 Assert.AreEqual (30, ts.Seconds, "Seconds");
89                 Assert.AreEqual (647, ts.Milliseconds, "Milliseconds");
90                 Assert.AreEqual (21496274706470000, ts.Ticks, "Ticks");
91         }
92
93         [Test]
94         [ExpectedException (typeof (ArgumentOutOfRangeException))]
95         public void MaxDays () 
96         {
97                 new TimeSpan (Int32.MaxValue, 0, 0, 0, 0);
98         }
99
100         [Test]
101         [ExpectedException (typeof (ArgumentOutOfRangeException))]
102         public void MinDays () 
103         {
104                 new TimeSpan (Int32.MinValue, 0, 0, 0, 0);
105         }
106
107         [Test]
108         [Ignore ("too long")]
109         public void MaxHours_TooLong () 
110         {
111                 // LAMESPEC: the highest hours are "special"
112                 for (int i=0; i < 596523; i++) {
113                         TimeSpan ts = new TimeSpan (0, Int32.MaxValue - i, 0, 0, 0);
114                         int h = i + 1;
115                         string prefix = i.ToString () + '-';
116                         Assert.AreEqual (-(h / 24), ts.Days, prefix + "Days");
117                         Assert.AreEqual (-(h % 24), ts.Hours, prefix + "Hours");
118                         Assert.AreEqual (0, ts.Minutes, prefix + "Minutes");
119                         Assert.AreEqual (0, ts.Seconds, prefix + "Seconds");
120                         Assert.AreEqual (0, ts.Milliseconds, prefix + "Milliseconds");
121                         Assert.AreEqual (-36000000000 * h, ts.Ticks, prefix + "Ticks");
122                 }
123         }
124
125         [Test]
126 #if NET_2_0
127         [ExpectedException (typeof (ArgumentOutOfRangeException))]
128         [Category ("NotWorking")]
129 #endif
130         public void MaxHours () 
131         {
132                 // LAMESPEC: the highest hours are "special"
133                 TimeSpan ts = new TimeSpan (0, Int32.MaxValue, 0, 0, 0);
134                 Assert.AreEqual (0, ts.Days, "Max-Days");
135                 Assert.AreEqual (-1, ts.Hours, "Max-Hours");
136                 Assert.AreEqual (0, ts.Minutes, "Max-Minutes");
137                 Assert.AreEqual (0, ts.Seconds, "Max-Seconds");
138                 Assert.AreEqual (0, ts.Milliseconds, "Max-Milliseconds");
139                 Assert.AreEqual (-36000000000, ts.Ticks, "Max-Ticks");
140
141                 ts = new TimeSpan (0, Int32.MaxValue - 596522, 0, 0, 0);
142                 Assert.AreEqual (-24855, ts.Days, "Days");
143                 Assert.AreEqual (-3, ts.Hours, "Hours");
144                 Assert.AreEqual (0, ts.Minutes, "Minutes");
145                 Assert.AreEqual (0, ts.Seconds, "Seconds");
146                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
147                 Assert.AreEqual (-21474828000000000, ts.Ticks, "Ticks");
148         }
149
150         [Test]
151 #if NET_2_0
152         [ExpectedException (typeof (ArgumentOutOfRangeException))]
153         [Category ("NotWorking")]
154 #endif
155         public void MaxHours_BreakPoint () 
156         {
157                 TimeSpan ts = new TimeSpan (0, Int32.MaxValue - 596523, 0, 0, 0);
158                 Assert.AreEqual (24855, ts.Days, "Days");
159                 Assert.AreEqual (2, ts.Hours, "Hours");
160                 Assert.AreEqual (28, ts.Minutes, "Minutes");
161                 Assert.AreEqual (16, ts.Seconds, "Seconds");
162                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
163                 Assert.AreEqual (21474808960000000, ts.Ticks, "Ticks");
164         }
165
166         [Test]
167         [Ignore ("too long")]
168         public void MinHours_TooLong () 
169         {
170                 // LAMESPEC: the lowest hours are "special"
171                 for (int i=Int32.MinValue; i < -2146887124; i++) {
172                         TimeSpan ts = new TimeSpan (0, i, 0, 0, 0);
173                         int h = i + Int32.MaxValue + 1;
174                         string prefix = i.ToString () + '-';
175                         Assert.AreEqual ((h / 24), ts.Days, prefix + "Days");
176                         Assert.AreEqual ((h % 24), ts.Hours, prefix + "Hours");
177                         Assert.AreEqual (0, ts.Minutes, prefix + "Minutes");
178                         Assert.AreEqual (0, ts.Seconds, prefix + "Seconds");
179                         Assert.AreEqual (0, ts.Milliseconds, prefix + "Milliseconds");
180                         Assert.AreEqual (36000000000 * h, ts.Ticks, prefix + "Ticks");
181                 }
182         }
183
184         [Test]
185 #if NET_2_0
186         [Category ("NotWorking")]
187 #endif
188         public void MinHours () 
189         {
190 #if NET_2_0
191                 TimeSpan ts = new TimeSpan (0, -256204778, 0, 0, 0);
192                 Assert.AreEqual (-10675199, ts.Days, "Days");
193                 Assert.AreEqual (-2, ts.Hours, "Hours");
194                 Assert.AreEqual (0, ts.Minutes, "Minutes");
195                 Assert.AreEqual (0, ts.Seconds, "Seconds");
196                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
197                 Assert.AreEqual (-9223372008000000000, ts.Ticks, "Ticks");
198 #else
199                 // LAMESPEC: the lowest hours are "special"
200                 TimeSpan ts = new TimeSpan (0, Int32.MinValue, 0, 0, 0);
201                 Assert.AreEqual (0, ts.Days, "Min-Days");
202                 Assert.AreEqual (0, ts.Hours, "Min-Hours");
203                 Assert.AreEqual (0, ts.Minutes, "Min-Minutes");
204                 Assert.AreEqual (0, ts.Seconds, "Min-Seconds");
205                 Assert.AreEqual (0, ts.Milliseconds, "Min-Milliseconds");
206                 Assert.AreEqual (0, ts.Ticks, "Min-Ticks");
207
208                 ts = new TimeSpan (0, -2146887125, 0, 0, 0);
209                 Assert.AreEqual (24855, ts.Days, "Days");
210                 Assert.AreEqual (3, ts.Hours, "Hours");
211                 Assert.AreEqual (0, ts.Minutes, "Minutes");
212                 Assert.AreEqual (0, ts.Seconds, "Seconds");
213                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
214                 Assert.AreEqual (21474828000000000, ts.Ticks, "Ticks");
215 #endif
216         }
217
218         [Test]
219 #if NET_2_0
220         [ExpectedException (typeof (ArgumentOutOfRangeException))]
221         [Category ("NotWorking")]
222 #endif
223         public void MinHours_BreakPoint () 
224         {
225                 TimeSpan ts = new TimeSpan (0, -2146887124, 0, 0, 0);
226                 Assert.AreEqual (-24855, ts.Days, "Days");
227                 Assert.AreEqual (-2, ts.Hours, "Hours");
228                 Assert.AreEqual (-28, ts.Minutes, "Minutes");
229                 Assert.AreEqual (-16, ts.Seconds, "Seconds");
230                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
231                 Assert.AreEqual (-21474808960000000, ts.Ticks, "Ticks");
232         }
233
234         [Test]
235         [Ignore ("too long")]
236         public void MaxMinutes_TooLong () 
237         {
238                 // LAMESPEC: the highest minutes are "special"
239                 for (int i=0; i < 35791394; i++) {
240                         TimeSpan ts = new TimeSpan (0, 0, Int32.MaxValue - i, 0, 0);
241                         long h = -(i + 1);
242                         string prefix = i.ToString () + '-';
243                         Assert.AreEqual ((h / 1440), ts.Days, prefix + "Days");
244                         Assert.AreEqual (((h / 60) % 24), ts.Hours, prefix + "Hours");
245                         Assert.AreEqual ((h % 60), ts.Minutes, prefix + "Minutes");
246                         Assert.AreEqual (0, ts.Seconds, prefix + "Seconds");
247                         Assert.AreEqual (0, ts.Milliseconds, prefix + "Milliseconds");
248                         Assert.AreEqual ((600000000L * h), ts.Ticks, prefix + "Ticks");
249                 }
250         }
251
252         [Test]
253 #if NET_2_0
254         [Category ("NotWorking")]
255 #endif
256         public void MaxMinutes () 
257         {
258                 TimeSpan ts;
259 #if NET_2_0
260                 ts = new TimeSpan (0, 0, 256204778, 0, 0);
261                 Assert.AreEqual (177919, ts.Days, "Max-Days");
262                 Assert.AreEqual (23, ts.Hours, "Max-Hours");
263                 Assert.AreEqual (38, ts.Minutes, "Max-Minutes");
264                 Assert.AreEqual (0, ts.Seconds, "Max-Seconds");
265                 Assert.AreEqual (0, ts.Milliseconds, "Max-Milliseconds");
266                 Assert.AreEqual (153722866800000000, ts.Ticks, "Max-Ticks");
267 #else
268                 // LAMESPEC: the highest minutes are "special"
269                 ts = new TimeSpan (0, 0, Int32.MaxValue, 0, 0);
270                 Assert.AreEqual (0, ts.Days, "Max-Days");
271                 Assert.AreEqual (0, ts.Hours, "Max-Hours");
272                 Assert.AreEqual (-1, ts.Minutes, "Max-Minutes");
273                 Assert.AreEqual (0, ts.Seconds, "Max-Seconds");
274                 Assert.AreEqual (0, ts.Milliseconds, "Max-Milliseconds");
275                 Assert.AreEqual (-600000000, ts.Ticks, "Max-Ticks");
276
277                 ts = new TimeSpan (0, 0, Int32.MaxValue - 35791393, 0, 0);
278                 Assert.AreEqual (-24855, ts.Days, "Days");
279                 Assert.AreEqual (-3, ts.Hours, "Hours");
280                 Assert.AreEqual (-14, ts.Minutes, "Minutes");
281                 Assert.AreEqual (0, ts.Seconds, "Seconds");
282                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
283                 Assert.AreEqual (-21474836400000000, ts.Ticks, "Ticks");
284 #endif
285         }
286
287         [Test]
288 #if NET_2_0
289         [ExpectedException (typeof (ArgumentOutOfRangeException))]
290         [Category ("NotWorking")]
291 #endif
292         public void MaxMinutes_BreakPoint () 
293         {
294                 TimeSpan ts = new TimeSpan (0, Int32.MaxValue - 35791394, 0, 0, 0);
295                 Assert.AreEqual (0, ts.Days, "Days");
296                 Assert.AreEqual (0, ts.Hours, "Hours");
297                 Assert.AreEqual (-52, ts.Minutes, "Minutes");
298                 Assert.AreEqual (0, ts.Seconds, "Seconds");
299                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
300                 Assert.AreEqual (-31200000000, ts.Ticks, "Ticks");
301         }
302
303         [Test]
304         [Ignore ("too long")]
305         public void MinMinutes_TooLong () 
306         {
307                 // LAMESPEC: the highest minutes are "special"
308                 for (int i=Int32.MinValue; i < -2111692253; i++) {
309                         TimeSpan ts = new TimeSpan (0, 0, i, 0, 0);
310                         long h = i + Int32.MaxValue + 1;
311                         string prefix = i.ToString () + '-';
312                         Assert.AreEqual ((h / 1440), ts.Days, prefix + "Days");
313                         Assert.AreEqual (((h / 60) % 24), ts.Hours, prefix + "Hours");
314                         Assert.AreEqual ((h % 60), ts.Minutes, prefix + "Minutes");
315                         Assert.AreEqual (0, ts.Seconds, prefix + "Seconds");
316                         Assert.AreEqual (0, ts.Milliseconds, prefix + "Milliseconds");
317                         Assert.AreEqual ((600000000L * h), ts.Ticks, prefix + "Ticks");
318                 }
319         }
320
321         [Test]
322 #if NET_2_0
323         [Category ("NotWorking")]
324 #endif
325         public void MinMinutes () 
326         {
327                 TimeSpan ts;
328 #if NET_2_0
329                 ts = new TimeSpan (0, 0, Int32.MinValue, 0, 0);
330                 Assert.AreEqual (-1491308, ts.Days, "Days");
331                 Assert.AreEqual (-2, ts.Hours, "Hours");
332                 Assert.AreEqual (-8, ts.Minutes, "Minutes");
333                 Assert.AreEqual (0, ts.Seconds, "Seconds");
334                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
335                 Assert.AreEqual (-1288490188800000000, ts.Ticks, "Ticks");
336 #else
337                 // LAMESPEC: the highest minutes are "special"
338                 ts = new TimeSpan (0, 0, Int32.MinValue, 0, 0);
339                 Assert.AreEqual (0, ts.Days, "Min-Days");
340                 Assert.AreEqual (0, ts.Hours, "Min-Hours");
341                 Assert.AreEqual (0, ts.Minutes, "Min-Minutes");
342                 Assert.AreEqual (0, ts.Seconds, "Min-Seconds");
343                 Assert.AreEqual (0, ts.Milliseconds, "Min-Milliseconds");
344                 Assert.AreEqual (0, ts.Ticks, "Min-Ticks");
345
346                 ts = new TimeSpan (0, 0, -2111692254, 0, 0);
347                 Assert.AreEqual (24855, ts.Days, "Days");
348                 Assert.AreEqual (3, ts.Hours, "Hours");
349                 Assert.AreEqual (14, ts.Minutes, "Minutes");
350                 Assert.AreEqual (0, ts.Seconds, "Seconds");
351                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
352                 Assert.AreEqual (21474836400000000, ts.Ticks, "Ticks");
353 #endif
354         }
355
356         [Test]
357 #if NET_2_0
358         [Category ("NotWorking")]
359 #endif
360         public void MinMinutes_BreakPoint () 
361         {
362 #if NET_2_0
363                 TimeSpan ts = new TimeSpan (0, 0, -2111692253, 0, 0);
364                 Assert.AreEqual (-1466452, ts.Days, "Days");
365                 Assert.AreEqual (-22, ts.Hours, "Hours");
366                 Assert.AreEqual (-53, ts.Minutes, "Minutes");
367                 Assert.AreEqual (-0, ts.Seconds, "Seconds");
368                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
369                 Assert.AreEqual (-1267015351800000000, ts.Ticks, "Ticks");
370 #else
371                 TimeSpan ts = new TimeSpan (0, 0, -2111692253, 0, 0);
372                 Assert.AreEqual (-24855, ts.Days, "Days");
373                 Assert.AreEqual (-3, ts.Hours, "Hours");
374                 Assert.AreEqual (-13, ts.Minutes, "Minutes");
375                 Assert.AreEqual (-16, ts.Seconds, "Seconds");
376                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
377                 Assert.AreEqual (-21474835960000000, ts.Ticks, "Ticks");
378 #endif
379         }
380
381         [Test]
382         public void MaxSeconds () 
383         {
384                 TimeSpan ts = new TimeSpan (0, 0, 0, Int32.MaxValue, 0);
385                 Assert.AreEqual (24855, ts.Days, "Days");
386                 Assert.AreEqual (3, ts.Hours, "Hours");
387                 Assert.AreEqual (14, ts.Minutes, "Minutes");
388                 Assert.AreEqual (7, ts.Seconds, "Seconds");
389                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
390                 Assert.AreEqual (21474836470000000, ts.Ticks, "Ticks");
391         }
392
393         [Test]
394         public void MinSeconds () 
395         {
396                 TimeSpan ts = new TimeSpan (0, 0, 0, Int32.MinValue, 0);
397                 Assert.AreEqual (-24855, ts.Days, "Days");
398                 Assert.AreEqual (-3, ts.Hours, "Hours");
399                 Assert.AreEqual (-14, ts.Minutes, "Minutes");
400                 Assert.AreEqual (-8, ts.Seconds, "Seconds");
401                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
402                 Assert.AreEqual (-21474836480000000, ts.Ticks, "Ticks");
403         }
404
405         [Test]
406         public void MaxMilliseconds () 
407         {
408                 TimeSpan ts = new TimeSpan (0, 0, 0, 0, Int32.MaxValue);
409                 Assert.AreEqual (24, ts.Days, "Days");
410                 Assert.AreEqual (20, ts.Hours, "Hours");
411                 Assert.AreEqual (31, ts.Minutes, "Minutes");
412                 Assert.AreEqual (23, ts.Seconds, "Seconds");
413                 Assert.AreEqual (647, ts.Milliseconds, "Milliseconds");
414                 Assert.AreEqual (21474836470000, ts.Ticks, "Ticks");
415         }
416
417         [Test]
418         public void MinMilliseconds () 
419         {
420                 TimeSpan ts = new TimeSpan (0, 0, 0, 0, Int32.MinValue);
421                 Assert.AreEqual (-24, ts.Days, "Days");
422                 Assert.AreEqual (-20, ts.Hours, "Hours");
423                 Assert.AreEqual (-31, ts.Minutes, "Minutes");
424                 Assert.AreEqual (-23, ts.Seconds, "Seconds");
425                 Assert.AreEqual (-648, ts.Milliseconds, "Milliseconds");
426                 Assert.AreEqual (-21474836480000, ts.Ticks, "Ticks");
427         }
428
429         [Test]
430         public void NegativeTimeSpan () 
431         {
432                 TimeSpan ts = new TimeSpan (-23, -59, -59);
433                 Assert.AreEqual (0, ts.Days, "Days");
434                 Assert.AreEqual (-23, ts.Hours, "Hours");
435                 Assert.AreEqual (-59, ts.Minutes, "Minutes");
436                 Assert.AreEqual (-59, ts.Seconds, "Seconds");
437                 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
438                 Assert.AreEqual (-863990000000, ts.Ticks, "Ticks");
439         }
440
441         public void TestProperties ()
442         {
443                 TimeSpan t1 = new TimeSpan (1,2,3,4,5);
444                 TimeSpan t2 = -t1;
445
446                 Assert.AreEqual (1, t1.Days, "A1");
447                 Assert.AreEqual (2, t1.Hours, "A2");
448                 Assert.AreEqual (3, t1.Minutes, "A3");
449                 Assert.AreEqual (4, t1.Seconds, "A4");
450                 Assert.AreEqual (5, t1.Milliseconds, "A5");
451                 Assert.AreEqual (-1, t2.Days, "A6");
452                 Assert.AreEqual (-2, t2.Hours, "A7");
453                 Assert.AreEqual (-3, t2.Minutes, "A8");
454                 Assert.AreEqual (-4, t2.Seconds, "A9");
455                 Assert.AreEqual (-5, t2.Milliseconds, "A10");
456         }
457
458         public void TestAdd ()
459         {
460                 TimeSpan t1 = new TimeSpan (2,3,4,5,6);
461                 TimeSpan t2 = new TimeSpan (1,2,3,4,5);
462                 TimeSpan t3 = t1 + t2;
463                 TimeSpan t4 = t1.Add (t2);
464                 TimeSpan t5;
465                 bool exception;
466
467                 Assert.AreEqual (3, t3.Days, "A1");
468                 Assert.AreEqual (5, t3.Hours, "A2");
469                 Assert.AreEqual (7, t3.Minutes, "A3");
470                 Assert.AreEqual (9, t3.Seconds, "A4");
471                 Assert.AreEqual (11, t3.Milliseconds, "A5");
472                 Assert.AreEqual ("3.05:07:09.0110000", t4.ToString (), "A6");
473                 try
474                 {
475                         t5 = TimeSpan.MaxValue + new TimeSpan (1);                      
476                         exception = false;
477                 }
478                 catch (OverflowException)
479                 {
480                         exception = true;
481                 }
482                 Assert.IsTrue (exception, "A7");
483         }
484
485         public void TestCompare ()
486         {
487                 TimeSpan t1 = new TimeSpan (-1);
488                 TimeSpan t2 = new TimeSpan (1);
489                 int res;
490                 bool exception;
491
492                 Assert.AreEqual (-1, TimeSpan.Compare (t1, t2), "A1");
493                 Assert.AreEqual (1, TimeSpan.Compare (t2, t1), "A2");
494                 Assert.AreEqual (0, TimeSpan.Compare (t2, t2), "A3");
495                 Assert.AreEqual (-1, TimeSpan.Compare (TimeSpan.MinValue, TimeSpan.MaxValue), "A4");
496                 Assert.AreEqual (-1, t1.CompareTo (t2), "A5");
497                 Assert.AreEqual (1, t2.CompareTo (t1), "A6");
498                 Assert.AreEqual (0, t2.CompareTo (t2), "A7");
499                 Assert.AreEqual (-1, TimeSpan.Compare (TimeSpan.MinValue, TimeSpan.MaxValue), "A8");
500
501                 Assert.AreEqual (1, TimeSpan.Zero.CompareTo (null), "A9");
502                 
503                 try
504                 {
505                         res = TimeSpan.Zero.CompareTo("");
506                         exception = false;      
507                 }
508                 catch (ArgumentException)
509                 {
510                         exception = true;
511                 }
512                 Assert.IsTrue (exception, "A10");
513
514                 Assert.AreEqual (false, t1 == t2, "A11");
515                 Assert.AreEqual (false, t1 > t2, "A12");
516                 Assert.AreEqual (false, t1 >= t2, "A13");
517                 Assert.AreEqual (true, t1 != t2, "A14");
518                 Assert.AreEqual (true, t1 < t2, "A15");
519                 Assert.AreEqual (true, t1 <= t2, "A16");
520         }
521
522         [Test]
523         [ExpectedException (typeof (OverflowException))]
524         public void NoNegateMinValue() {
525                 TimeSpan t1 = TimeSpan.MinValue.Negate ();
526         }
527
528         public void TestNegateAndDuration ()
529         {
530                 TimeSpan t1;
531                 bool exception;
532
533                 Assert.AreEqual ("-00:00:00.0012345", new TimeSpan (12345).Negate ().ToString (), "A1");
534                 Assert.AreEqual ("00:00:00.0012345", new TimeSpan (-12345).Duration ().ToString (), "A2");
535                         
536                 try
537                 {
538                         t1 = TimeSpan.MinValue.Duration ();
539                         exception = false;
540                 }
541                 catch (OverflowException) {
542                         exception = true;
543                 }
544                 Assert.IsTrue (exception, "A4");
545
546                 Assert.AreEqual ("-00:00:00.0000077", (-(new TimeSpan (77))).ToString (), "A5");
547                 Assert.AreEqual ("00:00:00.0000077", (+(new TimeSpan(77))).ToString(), "A6");
548         }
549
550         public void TestEquals ()
551         {
552                 TimeSpan t1 = new TimeSpan (1);
553                 TimeSpan t2 = new TimeSpan (2);
554                 string s = "justastring";
555
556                 Assert.AreEqual (true, t1.Equals (t1), "A1");
557                 Assert.AreEqual (false, t1.Equals (t2), "A2");
558                 Assert.AreEqual (false, t1.Equals (s), "A3");
559                 Assert.AreEqual (false, t1.Equals (null), "A4");
560                 Assert.AreEqual (true, TimeSpan.Equals (t1, t1), "A5");
561                 Assert.AreEqual (false, TimeSpan.Equals (t1, t2), "A6");
562                 Assert.AreEqual (false, TimeSpan.Equals (t1, null), "A7");
563                 Assert.AreEqual (false, TimeSpan.Equals (t1, s), "A8");
564                 Assert.AreEqual (false, TimeSpan.Equals (s, t2), "A9");
565                 Assert.AreEqual (true, TimeSpan.Equals (null, null), "A10");
566         }
567
568         [Test]
569         public void TestFromXXXX ()
570         {
571                 Assert.AreEqual ("12.08:16:48", TimeSpan.FromDays (12.345).ToString (), "A1");
572                 Assert.AreEqual ("12:20:42", TimeSpan.FromHours (12.345).ToString (), "A2");
573                 Assert.AreEqual ("00:12:20.7000000", TimeSpan.FromMinutes (12.345).ToString (), "A3");
574                 Assert.AreEqual ("00:00:12.3450000", TimeSpan.FromSeconds (12.345).ToString (), "A4");
575                 Assert.AreEqual ("00:00:00.0120000", TimeSpan.FromMilliseconds (12.345).ToString (), "A5");
576                 Assert.AreEqual ("00:00:00.0012345", TimeSpan.FromTicks (12345).ToString (), "A6");
577                 Assert.AreEqual ("-00:00:00.0010000", TimeSpan.FromMilliseconds (-0.5).ToString (), "A7");
578                 Assert.AreEqual ("00:00:00.0010000", TimeSpan.FromMilliseconds (0.5).ToString (), "A8");
579                 Assert.AreEqual ("-00:00:00.0030000", TimeSpan.FromMilliseconds (-2.5).ToString (), "A9");
580                 Assert.AreEqual ("00:00:00.0030000", TimeSpan.FromMilliseconds (2.5).ToString (), "A10");
581                 Assert.AreEqual ("00:00:00.0010000", TimeSpan.FromSeconds (0.0005).ToString (), "A11");
582         }
583
584         [Test]
585         [ExpectedException (typeof (OverflowException))]
586         public void FromDays_MinValue ()
587         {
588                 TimeSpan.FromDays (Double.MinValue);
589         }
590
591         [Test]
592         [ExpectedException (typeof (OverflowException))]
593         public void FromDays_MaxValue ()
594         {
595                 TimeSpan.FromDays (Double.MaxValue);
596         }
597
598         [Test]
599         [ExpectedException (typeof (ArgumentException))]
600         public void FromDays_NaN ()
601         {
602                 TimeSpan.FromDays (Double.NaN);
603         }
604
605         [Test]
606         [ExpectedException (typeof (OverflowException))]
607         public void FromDays_PositiveInfinity ()
608         {
609                 // LAMESPEC: Document to return TimeSpan.MaxValue
610                 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromDays (Double.PositiveInfinity));
611         }
612
613         [Test]
614         [ExpectedException (typeof (OverflowException))]
615         public void FromDays_NegativeInfinity ()
616         {
617                 // LAMESPEC: Document to return TimeSpan.MinValue
618                 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromDays (Double.NegativeInfinity));
619         }
620
621         [Test]
622         [ExpectedException (typeof (OverflowException))]
623         public void FromHours_MinValue ()
624         {
625                 TimeSpan.FromHours (Double.MinValue);
626         }
627
628         [Test]
629         [ExpectedException (typeof (OverflowException))]
630         public void FromHours_MaxValue ()
631         {
632                 TimeSpan.FromHours (Double.MaxValue);
633         }
634
635         [Test]
636         [ExpectedException (typeof (ArgumentException))]
637         public void FromHours_NaN ()
638         {
639                 TimeSpan.FromHours (Double.NaN);
640         }
641
642         [Test]
643         [ExpectedException (typeof (OverflowException))]
644         public void FromHours_PositiveInfinity ()
645         {
646                 // LAMESPEC: Document to return TimeSpan.MaxValue
647                 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromHours (Double.PositiveInfinity));
648         }
649
650         [Test]
651         [ExpectedException (typeof (OverflowException))]
652         public void FromHours_NegativeInfinity ()
653         {
654                 // LAMESPEC: Document to return TimeSpan.MinValue
655                 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromHours (Double.NegativeInfinity));
656         }
657
658         [Test]
659         [ExpectedException (typeof (OverflowException))]
660         public void FromMilliseconds_MinValue ()
661         {
662                 TimeSpan.FromMilliseconds (Double.MinValue);
663         }
664
665         [Test]
666         [ExpectedException (typeof (OverflowException))]
667         public void FromMilliseconds_MaxValue ()
668         {
669                 TimeSpan.FromMilliseconds (Double.MaxValue);
670         }
671
672         [Test]
673         [ExpectedException (typeof (ArgumentException))]
674         public void FromMilliseconds_NaN ()
675         {
676                 TimeSpan.FromMilliseconds (Double.NaN);
677         }
678
679         [Test]
680         [ExpectedException (typeof (OverflowException))]
681         public void FromMilliseconds_PositiveInfinity ()
682         {
683                 // LAMESPEC: Document to return TimeSpan.MaxValue
684                 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromMilliseconds (Double.PositiveInfinity));
685         }
686
687         [Test]
688         [ExpectedException (typeof (OverflowException))]
689         public void FromMilliseconds_NegativeInfinity ()
690         {
691                 // LAMESPEC: Document to return TimeSpan.MinValue
692                 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromMilliseconds (Double.NegativeInfinity));
693         }
694
695         [Test]
696         [ExpectedException (typeof (OverflowException))]
697         public void FromMinutes_MinValue ()
698         {
699                 TimeSpan.FromMinutes (Double.MinValue);
700         }
701
702         [Test]
703         [ExpectedException (typeof (OverflowException))]
704         public void FromMinutes_MaxValue ()
705         {
706                 TimeSpan.FromMinutes (Double.MaxValue);
707         }
708
709         [Test]
710         [ExpectedException (typeof (ArgumentException))]
711         public void FromMinutes_NaN ()
712         {
713                 TimeSpan.FromMinutes (Double.NaN);
714         }
715
716         [Test]
717         [ExpectedException (typeof (OverflowException))]
718         public void FromMinutes_PositiveInfinity ()
719         {
720                 // LAMESPEC: Document to return TimeSpan.MaxValue
721                 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromMinutes (Double.PositiveInfinity));
722         }
723
724         [Test]
725         [ExpectedException (typeof (OverflowException))]
726         public void FromMinutes_NegativeInfinity ()
727         {
728                 // LAMESPEC: Document to return TimeSpan.MinValue
729                 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromMinutes (Double.NegativeInfinity));
730         }
731
732         [Test]
733         [ExpectedException (typeof (OverflowException))]
734         public void FromSeconds_MinValue ()
735         {
736                 TimeSpan.FromSeconds (Double.MinValue);
737         }
738
739         [Test]
740         [ExpectedException (typeof (OverflowException))]
741         public void FromSeconds_MaxValue ()
742         {
743                 TimeSpan.FromSeconds (Double.MaxValue);
744         }
745
746         [Test]
747         [ExpectedException (typeof (ArgumentException))]
748         public void FromSeconds_NaN ()
749         {
750                 TimeSpan.FromSeconds (Double.NaN);
751         }
752
753         [Test]
754         [ExpectedException (typeof (OverflowException))]
755         public void FromSeconds_PositiveInfinity ()
756         {
757                 // LAMESPEC: Document to return TimeSpan.MaxValue
758                 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromSeconds (Double.PositiveInfinity));
759         }
760
761         [Test]
762         [ExpectedException (typeof (OverflowException))]
763         public void FromSeconds_NegativeInfinity ()
764         {
765                 // LAMESPEC: Document to return TimeSpan.MinValue
766                 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromSeconds (Double.NegativeInfinity));
767         }
768
769         public void TestGetHashCode ()
770         {
771                 Assert.AreEqual (77, new TimeSpan (77).GetHashCode (), "A1");
772         }
773
774         private void ParseHelper (string s, bool expectFormat, bool expectOverflow, string expect)
775         {
776                 bool formatException = false;
777                 bool overflowException = false;
778                 string result = "junk ";
779
780                 try {
781                         result =  TimeSpan.Parse (s).ToString ();
782                 }
783                 catch (OverflowException) {
784                         overflowException = true;
785                 }
786                 catch (FormatException) {
787                         formatException = true;
788                 }
789                 Assert.AreEqual (expectFormat, formatException, "A1 [" + s + "]");
790                 Assert.AreEqual (expectOverflow, overflowException, "A2 " + s + "]");
791
792                 if (!expectOverflow && !expectFormat) {
793                         Assert.AreEqual (expect, result, "A3 [" + s + "]");
794                 }
795         }
796
797         [Test]
798         public void TestParse ()
799         {
800                 ParseHelper (" 13:45:15 ",false, false, "13:45:15");
801                 ParseHelper (" -1:2:3 ", false, false, "-01:02:03");
802
803 #if NET_4_0
804                 // In 4.0 when the first part is out of range, it parses it as day.
805                 ParseHelper (" 25:11:12 ", false, false, "25.11:12:00");
806                 ParseHelper (" 24:11:12 ", false, false, "24.11:12:00");
807                 ParseHelper (" 23:11:12 ", false, false, "23:11:12");
808 #else
809                 ParseHelper (" 25:0:0 ",false, true, "dontcare");
810 #endif
811
812                 ParseHelper ("-21.23:59:59.9999999", false, false, "-21.23:59:59.9999999");
813                 ParseHelper ("10:12  ", false, false, "10:12:00");
814                 ParseHelper ("aaa", true, false, "dontcare");
815
816                 ParseHelper ("100000000000000.1:1:1", false, true, "dontcare");
817                 ParseHelper ("24:60:60", false, true, "dontcare");
818                 ParseHelper ("0001:0002:0003.12     ", false, false, "01:02:03.1200000");
819
820 #if NET_4_0
821                 // In 4.0 when a section has more than 7 digits an OverflowException is thrown.
822                 ParseHelper (" 1:2:3:12345678 ", false, true, "dontcare");
823 #else
824                 ParseHelper (" 1:2:3:12345678 ", true, false, "dontcare"); 
825 #endif
826
827 #if NET_4_0
828                 ParseHelper ("10:11:12:13", false, false, "10.11:12:13"); // Days using : instead of . as separator
829                 ParseHelper ("10.11", true, false, "dontcare"); // days+hours is invalid
830
831                 // Force the use of french culture -which is using a non common NumberDecimalSeparator-
832                 // as current culture, to show that the Parse method is *actually* being culture sensitive
833                 // *and* also keeping the compatibility with '.'
834                 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
835                 CultureInfo prev_culture = CultureInfo.CurrentCulture;
836                 try {
837                         Thread.CurrentThread.CurrentCulture = french_culture;
838                         ParseHelper ("10:10:10,006", false, false, "10:10:10.0060000");
839                         ParseHelper ("10:10:10.006", false, false, "10:10:10.0060000");
840                 } finally {
841                         // restore culture
842                         Thread.CurrentThread.CurrentCulture = prev_culture;
843                 }
844 #endif
845
846                 ParseHelper ("00:00:00", false, false, "00:00:00");
847                 ParseHelper ("00:10:00", false, false, "00:10:00");
848         }
849
850         // LAMESPEC: timespan in documentation is wrong - hh:mm:ss isn't mandatory
851         [Test]
852         public void Parse_Days_WithoutColon () 
853         {
854                 TimeSpan ts = TimeSpan.Parse ("1");
855                 Assert.AreEqual (1, ts.Days, "Days");
856         }
857
858         public void TestSubstract ()
859         {
860                 TimeSpan t1 = new TimeSpan (2,3,4,5,6);
861                 TimeSpan t2 = new TimeSpan (1,2,3,4,5);
862                 TimeSpan t3 = t1 - t2;
863                 TimeSpan t4 = t1.Subtract (t2);
864                 TimeSpan t5;
865                 bool exception;
866
867                 Assert.AreEqual ("1.01:01:01.0010000", t3.ToString (), "A1");
868                 Assert.AreEqual ("1.01:01:01.0010000", t4.ToString (), "A2");
869                 try {
870                         t5 = TimeSpan.MinValue - new TimeSpan (1);
871                         exception = false;
872                 }
873                 catch (OverflowException) {
874                         exception = true;
875                 }
876                 Assert.IsTrue (exception, "A3");
877         }
878
879         public void TestToString () 
880         {
881                 TimeSpan t1 = new TimeSpan (1,2,3,4,5);
882                 TimeSpan t2 = -t1;
883                 
884                 Assert.AreEqual ("1.02:03:04.0050000", t1.ToString (), "A1");
885                 Assert.AreEqual ("-1.02:03:04.0050000", t2.ToString (), "A2");
886                 Assert.AreEqual ("10675199.02:48:05.4775807", TimeSpan.MaxValue.ToString (), "A3");
887                 Assert.AreEqual ("-10675199.02:48:05.4775808", TimeSpan.MinValue.ToString (), "A4");
888         }
889
890         [Test]
891         public void ToString_Constants () 
892         {
893                 Assert.AreEqual ("00:00:00", TimeSpan.Zero.ToString (), "Zero");
894                 Assert.AreEqual ("10675199.02:48:05.4775807", TimeSpan.MaxValue.ToString (), "MaxValue");
895                 Assert.AreEqual ("-10675199.02:48:05.4775808", TimeSpan.MinValue.ToString (), "MinValue");
896         }
897
898         [Test]
899         public void Parse_InvalidValuesAndFormat_ExceptionOrder () 
900         {
901                 // hours should be between 0 and 23 but format is also invalid (too many dots)
902                 // In 2.0 overflow as precedence over format, but not in 4.0
903 #if NET_4_0
904                 try {
905                         TimeSpan.Parse ("0.99.99.0");
906                         Assert.Fail ("#A1");
907                 } catch (FormatException) {
908                 }
909 #else
910                 try {
911                         TimeSpan.Parse ("0.99.99.0");
912                         Assert.Fail ("#A1");
913                 } catch (OverflowException) {
914                 }
915 #endif
916                 try {
917                         TimeSpan.Parse ("0.999999999999.99.0");
918                         Assert.Fail ("#A2");
919                 } catch (OverflowException) {
920                 }
921         }
922
923         [Test]
924         public void Parse_MinMaxValues () 
925         {
926                 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.Parse ("10675199.02:48:05.4775807"), "MaxValue");
927                 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.Parse ("-10675199.02:48:05.4775808"), "MinValue");
928         }
929
930         [Test]
931         [ExpectedException (typeof (OverflowException))]
932         public void Parse_OverMaxValue() 
933         {
934                 TimeSpan.Parse ("10675199.02:48:05.4775808");
935         }
936
937         [Test]
938         [ExpectedException (typeof (OverflowException))]
939         public void Parse_UnderMinValue() 
940         {
941                 TimeSpan.Parse ("-10675199.02:48:05.4775809");
942         }
943
944         [Test]
945         public void ParseMissingSeconds ()
946         {
947                 // as seen in ML for http://resources.esri.com/arcgisserver/apis/silverlight/
948                 TimeSpan ts = TimeSpan.Parse ("0:0:.75");
949
950                 Assert.AreEqual (0, ts.Days, "Days");
951                 Assert.AreEqual (0, ts.Hours, "Hours");
952                 Assert.AreEqual (750, ts.Milliseconds, "Milliseconds");
953                 Assert.AreEqual (0, ts.Minutes, "Minutes");
954                 Assert.AreEqual (0, ts.Seconds, "Seconds");
955                 Assert.AreEqual (7500000, ts.Ticks, "Ticks");
956                 Assert.AreEqual (0.0000086805555555555555, ts.TotalDays, 0.00000000000000001, "TotalDays");
957                 Assert.AreEqual (0.00020833333333333332, ts.TotalHours, 0.00000000000000001, "TotalHours");
958                 Assert.AreEqual (750.0, ts.TotalMilliseconds, "TotalMilliseconds");
959                 Assert.AreEqual (0.0125, ts.TotalMinutes, "TotalMinutes");
960                 Assert.AreEqual (0.75, ts.TotalSeconds, "TotalSeconds");
961         }
962
963         // 'Ported' the Parse test to use TryParse
964         [Test]
965         public void TryParse ()
966         {
967                 TimeSpan result;
968
969                 Assert.AreEqual (true, TimeSpan.TryParse (" 13:45:15 ", out result), "#A1");
970                 Assert.AreEqual ("13:45:15", result.ToString (), "#A2");
971
972                 Assert.AreEqual (true, TimeSpan.TryParse (" -1:2:3 ", out result), "#B1");
973                 Assert.AreEqual ("-01:02:03", result.ToString (), "#B2");
974
975                 Assert.AreEqual (false, TimeSpan.TryParse ("aaa", out result), "#C2");
976
977                 Assert.AreEqual (true, TimeSpan.TryParse ("-21.23:59:59.9999999", out result), "#D1");
978                 Assert.AreEqual ("-21.23:59:59.9999999", result.ToString (), "#D2");
979
980                 Assert.AreEqual (false, TimeSpan.TryParse ("100000000000000.1:1:1", out result), "#E1");
981                 Assert.AreEqual (false, TimeSpan.TryParse ("24:60:60", out result), "#E2");
982
983 #if NET_4_0
984                 Assert.AreEqual (true, TimeSpan.TryParse ("0001:0002:0003.12     ", out result), "#F1");
985 #else
986                 Assert.AreEqual (true, TimeSpan.TryParse ("0001:0002:0003.12     ", out result), "#F1");
987                 Assert.AreEqual ("01:02:03.1200000", result.ToString (), "#F2");
988 #endif
989
990                 Assert.AreEqual (false, TimeSpan.TryParse (" 1:2:3:12345678 ", out result), "#G1");
991
992                 // Min and Max values
993                 Assert.AreEqual (true, TimeSpan.TryParse ("10675199.02:48:05.4775807", out result), "MaxValue#1");
994                 Assert.AreEqual (TimeSpan.MaxValue, result, "MaxValue#2");
995                 Assert.AreEqual (true, TimeSpan.TryParse ("-10675199.02:48:05.4775808", out result), "MinValue#1");
996                 Assert.AreEqual (TimeSpan.MinValue, result, "MinValue#2");
997
998 #if NET_4_0
999                 // Force the use of french culture -which is using a non common NumberDecimalSeparator-
1000                 // as current culture, to show that the Parse method is *actually* being culture sensitive
1001                 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
1002                 CultureInfo prev_culture = CultureInfo.CurrentCulture;
1003                 result = new TimeSpan (0, 10, 10, 10, 6);
1004                 try {
1005                         Thread.CurrentThread.CurrentCulture = french_culture;
1006                         Assert.AreEqual (true, TimeSpan.TryParse ("10:10:10,006", out result), "#CultureSensitive1");
1007                         Assert.AreEqual ("10:10:10.0060000", result.ToString (), "#CultureSensitive2");
1008                 } finally {
1009                         // restore culture
1010                         Thread.CurrentThread.CurrentCulture = prev_culture;
1011                 }
1012 #endif
1013         }
1014
1015         [Test]
1016         public void TryParseErrors ()
1017         {
1018                 TimeSpan result;
1019
1020                 Assert.AreEqual (false, TimeSpan.TryParse ("0.99.99.0", out result), "Format#1");
1021                 Assert.AreEqual (false, TimeSpan.TryParse ("10675199.02:48:05.4775808", out result), "OverMaxValue");
1022                 Assert.AreEqual (false, TimeSpan.TryParse ("-10675199.02:48:05.4775809", out result), "UnderMinValue");
1023         }
1024
1025 #if NET_4_0
1026         [Test]
1027         public void TryParseOverloads ()
1028         { 
1029                 TimeSpan result;
1030
1031                 // We use fr-FR culture since its NumericDecimalSeparator is not the same used by
1032                 // most cultures - including the invariant one.
1033                 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
1034                 Assert.AreEqual (true, TimeSpan.TryParse ("11:50:50,006", french_culture, out result), "#A1");
1035
1036                 // LAMESPEC - msdn states that an instance of DateTimeFormatInfo is retrieved to
1037                 // obtain culture sensitive information, but at least in the betas that's false
1038                 DateTimeFormatInfo format_info = new DateTimeFormatInfo ();
1039                 format_info.TimeSeparator = ";";
1040                 Assert.AreEqual (false, TimeSpan.TryParse ("11;50;50", format_info, out result), "#B1");
1041                 Assert.AreEqual (true, TimeSpan.TryParse ("11:50:50", format_info, out result), "#B2");
1042         }
1043
1044         [Test]
1045         public void ParseExact ()
1046         {
1047                 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
1048                 CultureInfo us_culture = CultureInfo.GetCultureInfo ("en-US");
1049
1050                 // At this point we are only missing the style bites and then we are
1051                 // pretty much done with the standard formats.
1052
1053                 //
1054                 // 'g' format - this is the short and culture sensitive format
1055                 //
1056                 string [] g_format = new string [] { "g" };
1057                 ParseExactHelper ("12", g_format, false, false, "12.00:00:00");
1058                 ParseExactHelper ("11:12", g_format, false, false, "11:12:00");
1059                 ParseExactHelper ("-11:12", g_format, false, false, "-11:12:00");
1060                 ParseExactHelper ("25:13", g_format, true, false, "dontcare");
1061                 ParseExactHelper ("11:66", g_format, true, false, "dontcare"); // I'd have expected OverflowExc here
1062                 ParseExactHelper ("11:12:13", g_format, false, false, "11:12:13");
1063                 ParseExactHelper ("-11:12:13", g_format, false, false, "-11:12:13");
1064                 ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare"); // this should work as well
1065                 ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare", us_culture);
1066                 ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare", CultureInfo.InvariantCulture);
1067                 ParseExactHelper ("10:11:12:66", g_format, true, false, "dontcare");
1068                 ParseExactHelper ("10:11:12:13", g_format, false, false, "10.11:12:13");
1069                 ParseExactHelper ("11:12:13.6", g_format, false, false, "11:12:13.6000000", CultureInfo.InvariantCulture);
1070                 ParseExactHelper ("11:12:13,6", g_format, false, false, "11:12:13.6000000", french_culture);
1071                 ParseExactHelper ("10:11:12:13.6", g_format, false, false, "10.11:12:13.6000000", us_culture);
1072                 ParseExactHelper (" 10:11:12:13.6 ", g_format, false, false, "10.11:12:13.6000000", us_culture);
1073                 ParseExactHelper ("10:11", g_format, false, false, "10:11:00", null, TimeSpanStyles.None);
1074                 ParseExactHelper ("10:11", g_format, false, false, "10:11:00", null, TimeSpanStyles.AssumeNegative); // no effect
1075
1076                 // 
1077                 // G format
1078                 //
1079                 string [] G_format = new string [] { "G" };
1080                 ParseExactHelper ("9:10:12", G_format, true, false, "dontcare");
1081                 ParseExactHelper ("9:10:12.6", G_format, true, false, "dontcare");
1082                 ParseExactHelper ("3.9:10:12", G_format, true, false, "dontcare");
1083                 ParseExactHelper ("3.9:10:12.153", G_format, true, false, "dontcare"); // this should be valid...
1084                 ParseExactHelper ("3:9:10:12.153", G_format, false, false, "3.09:10:12.1530000", us_culture);
1085                 ParseExactHelper ("0:9:10:12.153", G_format, false, false, "09:10:12.1530000", us_culture);
1086                 ParseExactHelper ("03:09:10:12.153", G_format, false, false, "3.09:10:12.1530000", us_culture);
1087                 ParseExactHelper ("003:009:0010:0012.00153", G_format, false, false, "3.09:10:12.0015300", us_culture);
1088                 ParseExactHelper ("3:9:10:66.153", G_format, true, false, "dontcare"); // seconds out of range
1089                 ParseExactHelper ("3:9:10:12.153", G_format, true, false, "dontcare", french_culture); // fr-FR uses ',' as decimal separator
1090                 ParseExactHelper ("3:9:10:12,153", G_format, false, false, "3.09:10:12.1530000", french_culture);
1091                 ParseExactHelper ("  3:9:10:12.153  ", G_format, false, false, "3.09:10:12.1530000", us_culture);
1092                 ParseExactHelper ("3:9:10:13.153", G_format, false, false, "3.09:10:13.1530000", us_culture, TimeSpanStyles.AssumeNegative);
1093
1094                 // c format
1095                 string [] c_format = new string [] { "c" };
1096                 ParseExactHelper ("12", c_format, false, false, "12.00:00:00");
1097                 ParseExactHelper ("12:11", c_format, false, false, "12:11:00");
1098                 ParseExactHelper ("12:66", c_format, true, false, "dontcare");
1099                 ParseExactHelper ("10.11:12", c_format, false, false, "10.11:12:00");
1100                 ParseExactHelper ("10.11:12:13", c_format, false, false, "10.11:12:13");
1101                 ParseExactHelper ("10:11:12:13", c_format, true, false, "dontcare"); // this is normally accepted in the Parse method
1102                 ParseExactHelper ("10.11:12:13.6", c_format, false, false, "10.11:12:13.6000000");
1103                 ParseExactHelper ("10:11:12,6", c_format, true, false, "dontcare");
1104                 ParseExactHelper ("10:11:12,6", c_format, true, false, "dontcare", french_culture);
1105                 ParseExactHelper ("  10:11:12.6  ", c_format, false, false, "10:11:12.6000000");
1106                 ParseExactHelper ("10:12", c_format, false, false, "10:12:00", null, TimeSpanStyles.AssumeNegative);
1107                 ParseExactHelper ("10:123456789999", c_format, true, false, "dontcare");
1108
1109                 ParseExactHelper ("10:12", new string [0], true, false, "dontcare");
1110                 ParseExactHelper ("10:12", new string [] { String.Empty }, true, false, "dontcare");
1111                 ParseExactHelper ("10:12", new string [] { null }, true, false, "dontcare");
1112         }
1113
1114         [Test]
1115         public void ParseExactMultipleFormats ()
1116         {
1117                 ParseExactHelper ("10:12", new string [] { "G", "g" }, false, false, "10:12:00");
1118                 ParseExactHelper ("10:12", new string [] { "g", "G" }, false, false, "10:12:00");
1119                 ParseExactHelper ("7.8:9:10", new string [] { "G", "g" }, true, false, "dontcare");
1120                 ParseExactHelper ("7.8:9:10", new string [] { "G", "g", "c" }, false, false, "7.08:09:10");
1121                 ParseExactHelper ("7:8:9:10", new string [] { "c", "g" }, false, false, "7.08:09:10");
1122                 ParseExactHelper ("7:8:9:10", new string [] { "c", "G" }, true, false, "dontcare");
1123                 ParseExactHelper ("7.123456789:1", new string [] { "c", "G", "g" }, true, false, "dontcare");
1124                 ParseExactHelper ("7.123456789:1", new string [] { "G", "g", "c" }, true, false, "dontcare");
1125                 ParseExactHelper ("1234567890123456", new string [] { "c", "g" }, true, false, "dontcare"); // I'd expect an OverflowException
1126                 ParseExactHelper ("10:12", new string [] { null, "c", "g" }, true, false, "10:12:00");
1127                 ParseExactHelper ("10:12", new string [] { String.Empty, "c", "g" }, true, false, "10:12:00");
1128         }
1129
1130         [Test]
1131         public void ParseExactCustomFormats ()
1132         {
1133                 // Days
1134                 ParseExactHelper ("33", new string [] { "%d" }, false, false, "33.00:00:00");
1135                 ParseExactHelper ("00", new string [] { "%d" }, false, false, "00:00:00");
1136                 ParseExactHelper ("33", new string [] { "%dd" }, false, false, "33.00:00:00");
1137                 ParseExactHelper ("3333", new string [] { "%d" }, false, false, "3333.00:00:00");
1138                 ParseExactHelper ("3333", new string [] { "%ddd" }, true, false, "3333.00:00:00"); // 'dd' mismatch the digit count
1139                 ParseExactHelper ("3333", new string [] { "%dddd" }, false, false, "3333.00:00:00");
1140                 ParseExactHelper ("00033", new string [] { "%ddddd" }, false, false, "33.00:00:00");
1141                 ParseExactHelper ("00033", new string [] { "%d" }, false, false, "33.00:00:00");
1142                 ParseExactHelper ("00000003", new string [] { "%dddddddd" }, false, false, "3.00:00:00"); // up to 8 'd'
1143                 ParseExactHelper ("000000003", new string [] { "%ddddddddd" }, true, false, "dontcare");
1144                 ParseExactHelper ("33", new string [] { "d" }, true, false, "33.00:00:00"); // This is sort of weird.
1145                 ParseExactHelper ("33", new string [] { "dd" }, false, false, "33.00:00:00");
1146                 ParseExactHelper ("-33", new string [] { "%d" }, true, false, "dontcare");
1147                 ParseExactHelper ("33", new string [] { "%d" }, false, false, "-33.00:00:00", null, TimeSpanStyles.AssumeNegative);
1148
1149                 // Hours
1150                 ParseExactHelper ("12", new string [] { "%h" }, false, false, "12:00:00");
1151                 ParseExactHelper ("00", new string [] { "%h" }, false, false, "00:00:00");
1152                 ParseExactHelper ("012", new string [] { "%h" }, true, false, "dontcare"); // more than 2 digits
1153                 ParseExactHelper ("00012", new string [] { "%hhhhh" }, true, false, "dontcare");
1154                 ParseExactHelper ("15", new string [] { "%h" }, false, false, "15:00:00");
1155                 ParseExactHelper ("24", new string [] { "%h" }, true, false, "dontcare");
1156                 ParseExactHelper ("15", new string [] { "%hh" }, false, false, "15:00:00");
1157                 ParseExactHelper ("1", new string [] { "%hh" }, true, false, "dontcare"); // 'hh' but a single digit
1158                 ParseExactHelper ("01", new string [] { "%hh" }, false, false, "01:00:00");
1159                 ParseExactHelper ("015", new string [] { "%hhh" }, true, false, "dontcare"); // Too many 'h'
1160                 ParseExactHelper ("12", new string [] { "h" }, true, false, "dontcare");
1161                 ParseExactHelper ("12", new string [] { "hh" }, false, false, "12:00:00");
1162                 ParseExactHelper ("-15", new string [] {"%h"}, true, false, "dontcare"); // Explicit - not accepted
1163                 ParseExactHelper ("15", new string [] { "%h" }, false, false, "-15:00:00", null, TimeSpanStyles.AssumeNegative);
1164                 ParseExactHelper ("15", new string [] { "%H" }, true, false, "dontcare"); // Uppercase is not accepted
1165
1166                 // Minutes
1167                 ParseExactHelper ("12", new string [] { "%m" }, false, false, "00:12:00");
1168                 ParseExactHelper ("00", new string [] { "%m" }, false, false, "00:00:00");
1169                 ParseExactHelper ("60", new string [] { "%m" }, true, false, "dontcare");
1170                 ParseExactHelper ("12", new string [] { "%mm" }, false, false, "00:12:00");
1171                 ParseExactHelper ("1", new string [] { "%mm" }, true, false, "dontcare");
1172                 ParseExactHelper ("12", new string [] { "%mmm" }, true, false, "dontcare");
1173                 ParseExactHelper ("12", new string [] { "m" }, true, false, "dontcare");
1174                 ParseExactHelper ("12", new string [] { "mm" }, false, false, "00:12:00");
1175                 ParseExactHelper ("-12", new string [] { "%m" }, true, false, "dontcare");
1176                 ParseExactHelper ("12", new string [] { "%m" }, false, false, "-00:12:00", null, TimeSpanStyles.AssumeNegative);
1177                 ParseExactHelper ("12", new string [] { "%M" }, true, false, "dontcare");
1178
1179                 // Seconds
1180                 ParseExactHelper ("12", new string [] { "%s" }, false, false, "00:00:12");
1181                 ParseExactHelper ("00", new string [] { "%s" }, false, false, "00:00:00");
1182                 ParseExactHelper ("000", new string [] { "%s" }, true, false, "dontcare");
1183                 ParseExactHelper ("12", new string [] { "%ss" }, false, false, "00:00:12");
1184                 ParseExactHelper ("12", new string [] { "%sss" }, true, false, "dontcare");
1185                 ParseExactHelper ("60", new string [] { "%s" }, true, false, "dontcare");
1186                 ParseExactHelper ("-12", new string [] { "%s" }, true, false, "dontcare");
1187                 ParseExactHelper ("12", new string [] { "%s" }, false, false, "-00:00:12", null, TimeSpanStyles.AssumeNegative);
1188
1189                 // Fractions of seconds - f
1190                 ParseExactHelper ("3", new string [] { "%f" }, false, false, "00:00:00.3000000");
1191                 ParseExactHelper ("0", new string [] { "%f" }, false, false, "00:00:00");
1192                 ParseExactHelper ("03", new string [] { "%f" }, true, false, "dontcare"); // This would work for other elements
1193                 ParseExactHelper ("10", new string [] { "%f" }, true, false, "dontcare"); // Only a digit is accepted with '%f'
1194                 ParseExactHelper ("3", new string [] { "%ff" }, true, false, "dontcare");
1195                 ParseExactHelper ("12", new string [] { "%ff" }, false, false, "00:00:00.1200000");
1196                 ParseExactHelper ("123", new string [] { "%ff" }, true, false, "dontcare");
1197                 ParseExactHelper ("123", new string [] { "%fff" }, false, false, "00:00:00.1230000");
1198                 ParseExactHelper ("1234", new string [] { "%ffff" }, false, false, "00:00:00.1234000");
1199                 ParseExactHelper ("1234567", new string [] { "%fffffff" }, false, false, "00:00:00.1234567");
1200                 ParseExactHelper ("1234567", new string [] { "%FfFFFFF" }, true, false, "dontcare"); // Mixed f and M
1201                 ParseExactHelper ("12345678", new string [] { "%ffffffff" }, true, false, "dontcare");
1202                 ParseExactHelper ("0000000", new string [] { "%fffffff" }, false, false, "00:00:00");
1203
1204                 // Fractions of second - F
1205                 ParseExactHelper ("3", new string [] { "%F" }, false, false, "00:00:00.3000000");
1206                 ParseExactHelper ("333", new string [] { "%FFFFF" }, false, false, "00:00:00.3330000");
1207                 ParseExactHelper ("1234567", new string [] { "%FFFFFFF" }, false, false, "00:00:00.1234567");
1208
1209                 // Multiple symbols
1210                 ParseExactHelper ("9:10", new string [] { @"h\:m" }, false, false, "09:10:00");
1211                 ParseExactHelper ("9;10", new string [] { @"h\;m" }, false, false, "09:10:00");
1212                 ParseExactHelper ("10:9", new string [] { @"m\:h" }, false, false, "09:10:00");
1213                 ParseExactHelper ("10:9", new string [] { @"%m\:%h" }, false, false, "09:10:00");
1214                 ParseExactHelper ("9 10", new string [] { @"h\ m" }, false, false, "09:10:00");
1215                 ParseExactHelper ("9   10", new string [] { @"h\ \ \ m" }, false, false, "09:10:00");
1216                 ParseExactHelper (" 9:10 ", new string [] { @"h\:m" }, true, false, "dontcare");
1217                 ParseExactHelper ("9:10:11", new string [] { @"h\:m\:s" }, false, false, "09:10:11");
1218                 ParseExactHelper ("9:10:11:6", new string [] { @"h\:m\:s\:f" }, false, false, "09:10:11.6000000");
1219                 ParseExactHelper ("9:10:11:666", new string [] { @"h\:m\:s\:f" }, true, false, "dontcare"); // fff with 1 digit
1220                 ParseExactHelper ("9:10:11:", new string [] { @"h\:m\:s\:F" }, false, false, "09:10:11"); // optional frac of seconds
1221                 ParseExactHelper ("9:10:11:", new string [] { @"h\:m\:s\:FF" }, false, false, "09:10:11");
1222                 ParseExactHelper ("9:10:11::", new string [] { @"h\:m\:s\:F\:" }, false, false, "09:10:11");
1223                 ParseExactHelper ("8:9:10:11:6666666", new string [] { @"d\:h\:m\:s\:fffffff" }, false, false, "8.09:10:11.6666666");
1224                 ParseExactHelper ("8:9:10:11:6666666", new string [] { @"d\:h\:m\:s\:fffffff" }, false, false, "-8.09:10:11.6666666", 
1225                                 null, TimeSpanStyles.AssumeNegative);
1226                 ParseExactHelper ("9:10", new string [] { @"h\:h" }, true, false, "dontcare"); // Repeated element
1227
1228                 // Misc
1229                 ParseExactHelper (" 0 ", new string [] { "%d" }, true, false, "dontcare");
1230                 ParseExactHelper (" 0 ", new string [] { " %d " }, true, false, "dontcare");
1231                 ParseExactHelper ("0", new string [] { " %d " }, true, false, "dontcare");
1232                 ParseExactHelper ("::", new string [] { @"\:\:" }, false, false, "00:00:00"); // funny
1233                 ParseExactHelper ("::", new string [] { @"\:\:" }, false, false, "00:00:00", null, TimeSpanStyles.AssumeNegative);
1234                 ParseExactHelper (" 0", new string [] { @"\ d" }, false, false, "00:00:00");
1235                 ParseExactHelper ("Interval = 12:13:14", new string [] { @"'Interval = 'h\:m\:s" }, false, false, "12:13:14");
1236         }
1237
1238         void ParseExactHelper (string input, string [] formats, bool format_error, bool overflow_error, string expected, 
1239         IFormatProvider formatProvider = null, TimeSpanStyles timeSpanStyles = TimeSpanStyles.None)
1240         {
1241                 bool overflow_exc = false;
1242                 bool format_exc = false;
1243                 TimeSpan result = TimeSpan.Zero;
1244
1245                 try {
1246                         result = TimeSpan.ParseExact (input, formats, formatProvider, timeSpanStyles);
1247                 } catch (OverflowException) {
1248                         overflow_exc = true;
1249                 } catch (FormatException) {
1250                         format_exc = true;
1251                 }
1252
1253                 Assert.AreEqual (format_error, format_exc, "A1");
1254                 Assert.AreEqual (overflow_error, overflow_exc, "A2");
1255                 if (!overflow_exc && !format_exc)
1256                         Assert.AreEqual (expected, result.ToString ());
1257         }
1258
1259         // 'Ported' the ParseExact test to use TryParseExact instead.
1260         [Test]
1261         public void TryParseExact ()
1262         {
1263                 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
1264                 CultureInfo us_culture = CultureInfo.GetCultureInfo ("en-US");
1265
1266                 //
1267                 // 'g' format - this is the short and culture sensitive format
1268                 //
1269                 string [] g_format = new string [] { "g" };
1270                 TryParseExactHelper ("12", g_format, false, "12.00:00:00");
1271                 TryParseExactHelper ("11:12", g_format, false, "11:12:00");
1272                 TryParseExactHelper ("-11:12", g_format, false, "-11:12:00");
1273                 TryParseExactHelper ("25:13", g_format, true, "dontcare");
1274                 TryParseExactHelper ("11:66", g_format, true, "dontcare"); // I'd have expected OverflowExc here
1275                 TryParseExactHelper ("11:12:13", g_format, false, "11:12:13");
1276                 TryParseExactHelper ("-11:12:13", g_format, false, "-11:12:13");
1277                 TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare"); // this should work as well
1278                 TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare", us_culture);
1279                 TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare", CultureInfo.InvariantCulture);
1280                 TryParseExactHelper ("10:11:12:66", g_format, true, "dontcare");
1281                 TryParseExactHelper ("10:11:12:13", g_format, false, "10.11:12:13");
1282                 TryParseExactHelper ("11:12:13.6", g_format, false, "11:12:13.6000000", CultureInfo.InvariantCulture);
1283                 TryParseExactHelper ("11:12:13,6", g_format, false, "11:12:13.6000000", french_culture);
1284                 TryParseExactHelper ("10:11:12:13.6", g_format, false, "10.11:12:13.6000000", us_culture);
1285                 TryParseExactHelper (" 10:11:12:13.6 ", g_format, false, "10.11:12:13.6000000", us_culture);
1286                 TryParseExactHelper ("10:11", g_format, false, "10:11:00", null, TimeSpanStyles.None);
1287                 TryParseExactHelper ("10:11", g_format, false, "10:11:00", null, TimeSpanStyles.AssumeNegative); // no effect
1288
1289                 // 
1290                 // G format
1291                 //
1292                 string [] G_format = new string [] { "G" };
1293                 TryParseExactHelper ("9:10:12", G_format, true, "dontcare");
1294                 TryParseExactHelper ("9:10:12.6", G_format, true, "dontcare");
1295                 TryParseExactHelper ("3.9:10:12", G_format, true, "dontcare");
1296                 TryParseExactHelper ("3.9:10:12.153", G_format, true, "dontcare"); // this should be valid...
1297                 TryParseExactHelper ("3:9:10:12.153", G_format, false, "3.09:10:12.1530000", us_culture);
1298                 TryParseExactHelper ("0:9:10:12.153", G_format, false, "09:10:12.1530000", us_culture);
1299                 TryParseExactHelper ("03:09:10:12.153", G_format, false, "3.09:10:12.1530000", us_culture);
1300                 TryParseExactHelper ("003:009:0010:0012.00153", G_format, false, "3.09:10:12.0015300", us_culture);
1301                 TryParseExactHelper ("3:9:10:66.153", G_format, true, "dontcare"); // seconds out of range
1302                 TryParseExactHelper ("3:9:10:12.153", G_format, true, "dontcare", french_culture); // fr-FR uses ',' as decimal separator
1303                 TryParseExactHelper ("3:9:10:12,153", G_format, false, "3.09:10:12.1530000", french_culture);
1304                 TryParseExactHelper ("  3:9:10:12.153  ", G_format, false, "3.09:10:12.1530000", us_culture);
1305                 TryParseExactHelper ("3:9:10:13.153", G_format, false, "3.09:10:13.1530000", us_culture, TimeSpanStyles.AssumeNegative);
1306
1307                 // c format
1308                 string [] c_format = new string [] { "c" };
1309                 TryParseExactHelper ("12", c_format, false, "12.00:00:00");
1310                 TryParseExactHelper ("12:11", c_format, false, "12:11:00");
1311                 TryParseExactHelper ("12:66", c_format, true, "dontcare");
1312                 TryParseExactHelper ("10.11:12", c_format, false, "10.11:12:00");
1313                 TryParseExactHelper ("10.11:12:13", c_format, false, "10.11:12:13");
1314                 TryParseExactHelper ("10:11:12:13", c_format, true, "dontcare"); // this is normally accepted in the Parse method
1315                 TryParseExactHelper ("10.11:12:13.6", c_format, false, "10.11:12:13.6000000");
1316                 TryParseExactHelper ("10:11:12,6", c_format, true, "dontcare");
1317                 TryParseExactHelper ("10:11:12,6", c_format, true, "dontcare", french_culture);
1318                 TryParseExactHelper ("  10:11:12.6  ", c_format, false, "10:11:12.6000000");
1319                 TryParseExactHelper ("10:12", c_format, false, "10:12:00", null, TimeSpanStyles.AssumeNegative);
1320                 TryParseExactHelper ("10:123456789999", c_format, true, "dontcare");
1321
1322                 TryParseExactHelper ("10:12", new string [0], true, "dontcare");
1323                 TryParseExactHelper ("10:12", new string [] { String.Empty }, true, "dontcare");
1324                 TryParseExactHelper ("10:12", new string [] { null }, true, "dontcare");
1325
1326                 TryParseExactHelper (null, new string [] { null }, true, "dontcare");
1327         }
1328
1329         void TryParseExactHelper (string input, string [] formats, bool error, string expected, IFormatProvider formatProvider = null,
1330                         TimeSpanStyles styles = TimeSpanStyles.None)
1331         {
1332                 TimeSpan result;
1333                 bool success;
1334
1335                 success = TimeSpan.TryParseExact (input, formats, formatProvider, styles, out result);
1336                 Assert.AreEqual (!error, success);
1337                 if (!error)
1338                         Assert.AreEqual (expected, result.ToString ());
1339         }
1340
1341         [Test]
1342         public void ParseExactExceptions ()
1343         {
1344                 try {
1345                         TimeSpan.ParseExact (null, "g", null);
1346                         Assert.Fail ("#A1");
1347                 } catch (ArgumentNullException) {
1348                 }
1349
1350                 try {
1351                         TimeSpan.ParseExact ("10:12", (string)null, null);
1352                         Assert.Fail ("#A2");
1353                 } catch (ArgumentNullException) {
1354                 }
1355
1356                 try {
1357                         TimeSpan.ParseExact ("10:12", (string [])null, null);
1358                         Assert.Fail ("#A3");
1359                 } catch (ArgumentNullException) {
1360                 }
1361         }
1362
1363         [Test]
1364         public void ToStringOverloads ()
1365         {
1366                 TimeSpan ts = new TimeSpan (1, 2, 3, 4, 6);
1367
1368                 // Simple version - culture invariant
1369                 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (), "#A1");
1370                 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("c"), "#A2");
1371                 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (null), "#A3");
1372                 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (String.Empty), "#A4");
1373
1374                 //
1375                 // IFormatProvider ones - use a culture changing numeric format.
1376                 // Also, we use fr-FR as culture, since it uses some elements different to invariant culture
1377                 //
1378                 CultureInfo culture = CultureInfo.GetCultureInfo ("fr-FR");
1379
1380                 Assert.AreEqual ("1:2:03:04,006", ts.ToString ("g", culture), "#B1");
1381                 Assert.AreEqual ("1:02:03:04,0060000", ts.ToString ("G", culture), "#B2");
1382                 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("c", culture), "#B3"); // 'c' format ignores CultureInfo
1383                 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("t", culture), "#B4"); // 't' and 'T' are the same as 'c'
1384                 Assert.AreEqual("1.02:03:04.0060000", ts.ToString("T", culture), "#B5");
1385
1386                 ts = new TimeSpan (4, 5, 6);
1387                 Assert.AreEqual ("4:05:06", ts.ToString ("g", culture), "#C1");
1388                 Assert.AreEqual ("0:04:05:06,0000000", ts.ToString ("G", culture), "#C2");
1389         }
1390
1391         [Test]
1392         public void ToStringCustomFormats ()
1393         {
1394                 TimeSpan ts = new TimeSpan (1, 3, 5, 7);
1395
1396                 Assert.AreEqual ("1", ts.ToString ("%d"), "#A0");
1397                 Assert.AreEqual ("3", ts.ToString ("%h"), "#A1");
1398                 Assert.AreEqual ("5", ts.ToString ("%m"), "#A2");
1399                 Assert.AreEqual ("7", ts.ToString ("%s"), "#A3");
1400                 Assert.AreEqual ("0", ts.ToString ("%f"), "#A4");
1401                 Assert.AreEqual (String.Empty, ts.ToString ("%F"), "#A5"); // Nothing to display
1402
1403                 Assert.AreEqual ("01", ts.ToString ("dd"), "#B0");
1404                 Assert.AreEqual ("00000001", ts.ToString ("dddddddd"), "#B1");
1405                 Assert.AreEqual ("03", ts.ToString ("hh"), "#B2");
1406                 Assert.AreEqual ("05", ts.ToString ("mm"), "#B3");
1407                 Assert.AreEqual ("07", ts.ToString ("ss"), "#B4");
1408                 Assert.AreEqual ("00", ts.ToString ("ff"), "#B5");
1409                 Assert.AreEqual ("0000000", ts.ToString ("fffffff"), "#B6");
1410                 Assert.AreEqual (String.Empty, ts.ToString ("FF"), "#B7");
1411
1412                 Assert.AreEqual ("01;03;05", ts.ToString (@"dd\;hh\;mm"), "#C0");
1413                 Assert.AreEqual ("05 07", ts.ToString (@"mm\ ss"), "#C1");
1414                 Assert.AreEqual ("05 07 ", ts.ToString (@"mm\ ss\ FF"), "#C2");
1415                 Assert.AreEqual ("Result = 3 hours with 5 minutes and 7 seconds",
1416                                 ts.ToString (@"'Result = 'h' hours with 'm' minutes and 's' seconds'"), "#C3");
1417                 Assert.AreEqual ("  ", ts.ToString (@"\ \ "), "#C4");
1418
1419                 ts = new TimeSpan (1, 3, 5, 7, 153);
1420                 Assert.AreEqual ("1", ts.ToString ("%F"), "#D0");
1421                 Assert.AreEqual ("15", ts.ToString ("FF"), "#D1"); // Don't use %, as the parser gets confused here
1422                 Assert.AreEqual ("153", ts.ToString ("FFFFFFF"), "#D2");
1423
1424                 // Negative values are shown without sign
1425                 ts = new TimeSpan (-1, -3, -5);
1426                 Assert.AreEqual ("1", ts.ToString ("%h"), "#E0");
1427                 Assert.AreEqual ("3", ts.ToString ("%m"), "#E1");
1428                 Assert.AreEqual ("5", ts.ToString ("%s"), "#E2");
1429
1430                 ts = new TimeSpan (123456789);
1431                 Assert.AreEqual ("12.3", ts.ToString ("s\\.f"), "#F0");
1432                 Assert.AreEqual ("12.3", ts.ToString ("s\\.F"), "#F1");
1433         }
1434
1435         [Test]
1436         public void ToStringOverloadsErrors ()
1437         {
1438                 TimeSpan ts = new TimeSpan (10, 10, 10);
1439                 string result;
1440
1441                 try {
1442                         result = ts.ToString ("non-valid");
1443                         Assert.Fail ("#1");
1444                 } catch (FormatException) {
1445                 }
1446
1447                 try {
1448                         result = ts.ToString ("C");
1449                         Assert.Fail ("#2");
1450                 } catch (FormatException) {
1451                 }
1452
1453                 try
1454                 {
1455                         ts.ToString ("m");
1456                         Assert.Fail ("#3");
1457                 } catch (FormatException) {
1458                 }
1459
1460                 try
1461                 {
1462                         ts.ToString ("d"); // Missing % for single char
1463                         Assert.Fail ("#4");
1464                 } catch (FormatException)
1465                 {
1466                 }
1467
1468                 try
1469                 {
1470                         ts.ToString ("ddddddddd");
1471                         Assert.Fail ("#5");
1472                 } catch (FormatException)
1473                 {
1474                 }
1475
1476                 try
1477                 {
1478                         ts.ToString ("hhh");
1479                         Assert.Fail ("#5");
1480                 } catch (FormatException)
1481                 {
1482                 }
1483
1484                 try
1485                 {
1486                         ts.ToString ("ffffffff");
1487                         Assert.Fail ("6");
1488                 } catch (FormatException)
1489                 {
1490                 }
1491         }
1492 #endif
1493 }
1494
1495 }