2 // TimeSpanTest.cs - NUnit Test Cases for the System.TimeSpan struct
5 // Duco Fijma (duco@lorentz.xs4all.nl)
6 // Sebastien Pouliot <sebastien@ximian.com>
9 // Copyright (C) 2004 Novell (http://www.novell.com)
12 using NUnit.Framework;
14 using System.Globalization;
15 using System.Threading;
17 namespace MonoTests.System
21 public class TimeSpanTest {
23 private void Debug (TimeSpan ts)
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);
34 public void TestCtors ()
36 TimeSpan t1 = new TimeSpan (1234567890);
38 Assert.AreEqual ("00:02:03.4567890", t1.ToString (), "A1");
39 t1 = new TimeSpan (1,2,3);
40 Assert.AreEqual ("01:02:03", t1.ToString (), "A2");
41 t1 = new TimeSpan (1,2,3,4);
42 Assert.AreEqual ("1.02:03:04", t1.ToString (), "A3");
43 t1 = new TimeSpan (1,2,3,4,5);
44 Assert.AreEqual ("1.02:03:04.0050000", t1.ToString (), "A4");
45 t1 = new TimeSpan (-1,2,-3,4,-5);
46 Assert.AreEqual ("-22:02:56.0050000", t1.ToString (), "A5");
47 t1 = new TimeSpan (0,25,0,0,0);
48 Assert.AreEqual ("1.01:00:00", t1.ToString (), "A6");
52 [ExpectedException (typeof (ArgumentOutOfRangeException))]
53 public void DaysOverflow ()
55 int days = (int) (Int64.MaxValue / TimeSpan.TicksPerDay) + 1;
56 TimeSpan ts = new TimeSpan (days, 0, 0, 0, 0);
60 [ExpectedException (typeof (ArgumentOutOfRangeException))]
61 public void TemporaryOverflow ()
63 // calculating part of this results in overflow (days)
64 // but the negative hours, minutes, seconds & ms correct this
65 int days = (int) (Int64.MaxValue / TimeSpan.TicksPerDay) + 1;
66 TimeSpan ts = new TimeSpan (days, Int32.MinValue, Int32.MinValue, Int32.MinValue, Int32.MinValue);
67 Assert.AreEqual (10650320, ts.Days, "Days");
68 Assert.AreEqual (0, ts.Hours, "Hours");
69 Assert.AreEqual (14, ts.Minutes, "Minutes");
70 Assert.AreEqual (28, ts.Seconds, "Seconds");
71 Assert.AreEqual (352, ts.Milliseconds, "Milliseconds");
72 Assert.AreEqual (9201876488683520000, ts.Ticks, "Ticks");
76 [ExpectedException (typeof (ArgumentOutOfRangeException))]
77 public void NoOverflowInHoursMinsSecondsMS ()
79 TimeSpan ts = new TimeSpan (0, Int32.MaxValue, Int32.MaxValue, Int32.MaxValue, Int32.MaxValue);
80 Assert.AreEqual (24879, ts.Days, "Days");
81 Assert.AreEqual (22, ts.Hours, "Hours");
82 Assert.AreEqual (44, ts.Minutes, "Minutes");
83 Assert.AreEqual (30, ts.Seconds, "Seconds");
84 Assert.AreEqual (647, ts.Milliseconds, "Milliseconds");
85 Assert.AreEqual (21496274706470000, ts.Ticks, "Ticks");
89 [ExpectedException (typeof (ArgumentOutOfRangeException))]
90 public void MaxDays ()
92 new TimeSpan (Int32.MaxValue, 0, 0, 0, 0);
96 [ExpectedException (typeof (ArgumentOutOfRangeException))]
97 public void MinDays ()
99 new TimeSpan (Int32.MinValue, 0, 0, 0, 0);
103 [ExpectedException (typeof (ArgumentOutOfRangeException))]
104 public void MaxHours ()
106 // LAMESPEC: the highest hours are "special"
107 TimeSpan ts = new TimeSpan (0, Int32.MaxValue, 0, 0, 0);
108 Assert.AreEqual (0, ts.Days, "Max-Days");
109 Assert.AreEqual (-1, ts.Hours, "Max-Hours");
110 Assert.AreEqual (0, ts.Minutes, "Max-Minutes");
111 Assert.AreEqual (0, ts.Seconds, "Max-Seconds");
112 Assert.AreEqual (0, ts.Milliseconds, "Max-Milliseconds");
113 Assert.AreEqual (-36000000000, ts.Ticks, "Max-Ticks");
115 ts = new TimeSpan (0, Int32.MaxValue - 596522, 0, 0, 0);
116 Assert.AreEqual (-24855, ts.Days, "Days");
117 Assert.AreEqual (-3, ts.Hours, "Hours");
118 Assert.AreEqual (0, ts.Minutes, "Minutes");
119 Assert.AreEqual (0, ts.Seconds, "Seconds");
120 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
121 Assert.AreEqual (-21474828000000000, ts.Ticks, "Ticks");
125 [ExpectedException (typeof (ArgumentOutOfRangeException))]
126 public void MaxHours_BreakPoint ()
128 TimeSpan ts = new TimeSpan (0, Int32.MaxValue - 596523, 0, 0, 0);
129 Assert.AreEqual (24855, ts.Days, "Days");
130 Assert.AreEqual (2, ts.Hours, "Hours");
131 Assert.AreEqual (28, ts.Minutes, "Minutes");
132 Assert.AreEqual (16, ts.Seconds, "Seconds");
133 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
134 Assert.AreEqual (21474808960000000, ts.Ticks, "Ticks");
138 public void MinHours ()
140 TimeSpan ts = new TimeSpan (0, -256204778, 0, 0, 0);
141 Assert.AreEqual (-10675199, ts.Days, "Days");
142 Assert.AreEqual (-2, ts.Hours, "Hours");
143 Assert.AreEqual (0, ts.Minutes, "Minutes");
144 Assert.AreEqual (0, ts.Seconds, "Seconds");
145 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
146 Assert.AreEqual (-9223372008000000000, ts.Ticks, "Ticks");
150 [ExpectedException (typeof (ArgumentOutOfRangeException))]
151 public void MinHours_BreakPoint ()
153 TimeSpan ts = new TimeSpan (0, -2146887124, 0, 0, 0);
154 Assert.AreEqual (-24855, ts.Days, "Days");
155 Assert.AreEqual (-2, ts.Hours, "Hours");
156 Assert.AreEqual (-28, ts.Minutes, "Minutes");
157 Assert.AreEqual (-16, ts.Seconds, "Seconds");
158 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
159 Assert.AreEqual (-21474808960000000, ts.Ticks, "Ticks");
163 public void MaxMinutes ()
166 ts = new TimeSpan (0, 0, 256204778, 0, 0);
167 Assert.AreEqual (177919, ts.Days, "Max-Days");
168 Assert.AreEqual (23, ts.Hours, "Max-Hours");
169 Assert.AreEqual (38, ts.Minutes, "Max-Minutes");
170 Assert.AreEqual (0, ts.Seconds, "Max-Seconds");
171 Assert.AreEqual (0, ts.Milliseconds, "Max-Milliseconds");
172 Assert.AreEqual (153722866800000000, ts.Ticks, "Max-Ticks");
176 [ExpectedException (typeof (ArgumentOutOfRangeException))]
177 public void MaxMinutes_BreakPoint ()
179 TimeSpan ts = new TimeSpan (0, Int32.MaxValue - 35791394, 0, 0, 0);
180 Assert.AreEqual (0, ts.Days, "Days");
181 Assert.AreEqual (0, ts.Hours, "Hours");
182 Assert.AreEqual (-52, ts.Minutes, "Minutes");
183 Assert.AreEqual (0, ts.Seconds, "Seconds");
184 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
185 Assert.AreEqual (-31200000000, ts.Ticks, "Ticks");
189 public void MinMinutes ()
192 ts = new TimeSpan (0, 0, Int32.MinValue, 0, 0);
193 Assert.AreEqual (-1491308, ts.Days, "Days");
194 Assert.AreEqual (-2, ts.Hours, "Hours");
195 Assert.AreEqual (-8, ts.Minutes, "Minutes");
196 Assert.AreEqual (0, ts.Seconds, "Seconds");
197 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
198 Assert.AreEqual (-1288490188800000000, ts.Ticks, "Ticks");
202 public void MinMinutes_BreakPoint ()
204 TimeSpan ts = new TimeSpan (0, 0, -2111692253, 0, 0);
205 Assert.AreEqual (-1466452, ts.Days, "Days");
206 Assert.AreEqual (-22, ts.Hours, "Hours");
207 Assert.AreEqual (-53, ts.Minutes, "Minutes");
208 Assert.AreEqual (-0, ts.Seconds, "Seconds");
209 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
210 Assert.AreEqual (-1267015351800000000, ts.Ticks, "Ticks");
214 public void MaxSeconds ()
216 TimeSpan ts = new TimeSpan (0, 0, 0, Int32.MaxValue, 0);
217 Assert.AreEqual (24855, ts.Days, "Days");
218 Assert.AreEqual (3, ts.Hours, "Hours");
219 Assert.AreEqual (14, ts.Minutes, "Minutes");
220 Assert.AreEqual (7, ts.Seconds, "Seconds");
221 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
222 Assert.AreEqual (21474836470000000, ts.Ticks, "Ticks");
226 public void MinSeconds ()
228 TimeSpan ts = new TimeSpan (0, 0, 0, Int32.MinValue, 0);
229 Assert.AreEqual (-24855, ts.Days, "Days");
230 Assert.AreEqual (-3, ts.Hours, "Hours");
231 Assert.AreEqual (-14, ts.Minutes, "Minutes");
232 Assert.AreEqual (-8, ts.Seconds, "Seconds");
233 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
234 Assert.AreEqual (-21474836480000000, ts.Ticks, "Ticks");
238 public void MaxMilliseconds ()
240 TimeSpan ts = new TimeSpan (0, 0, 0, 0, Int32.MaxValue);
241 Assert.AreEqual (24, ts.Days, "Days");
242 Assert.AreEqual (20, ts.Hours, "Hours");
243 Assert.AreEqual (31, ts.Minutes, "Minutes");
244 Assert.AreEqual (23, ts.Seconds, "Seconds");
245 Assert.AreEqual (647, ts.Milliseconds, "Milliseconds");
246 Assert.AreEqual (21474836470000, ts.Ticks, "Ticks");
250 public void MinMilliseconds ()
252 TimeSpan ts = new TimeSpan (0, 0, 0, 0, Int32.MinValue);
253 Assert.AreEqual (-24, ts.Days, "Days");
254 Assert.AreEqual (-20, ts.Hours, "Hours");
255 Assert.AreEqual (-31, ts.Minutes, "Minutes");
256 Assert.AreEqual (-23, ts.Seconds, "Seconds");
257 Assert.AreEqual (-648, ts.Milliseconds, "Milliseconds");
258 Assert.AreEqual (-21474836480000, ts.Ticks, "Ticks");
262 public void NegativeTimeSpan ()
264 TimeSpan ts = new TimeSpan (-23, -59, -59);
265 Assert.AreEqual (0, ts.Days, "Days");
266 Assert.AreEqual (-23, ts.Hours, "Hours");
267 Assert.AreEqual (-59, ts.Minutes, "Minutes");
268 Assert.AreEqual (-59, ts.Seconds, "Seconds");
269 Assert.AreEqual (0, ts.Milliseconds, "Milliseconds");
270 Assert.AreEqual (-863990000000, ts.Ticks, "Ticks");
274 public void TestProperties ()
276 TimeSpan t1 = new TimeSpan (1,2,3,4,5);
279 Assert.AreEqual (1, t1.Days, "A1");
280 Assert.AreEqual (2, t1.Hours, "A2");
281 Assert.AreEqual (3, t1.Minutes, "A3");
282 Assert.AreEqual (4, t1.Seconds, "A4");
283 Assert.AreEqual (5, t1.Milliseconds, "A5");
284 Assert.AreEqual (-1, t2.Days, "A6");
285 Assert.AreEqual (-2, t2.Hours, "A7");
286 Assert.AreEqual (-3, t2.Minutes, "A8");
287 Assert.AreEqual (-4, t2.Seconds, "A9");
288 Assert.AreEqual (-5, t2.Milliseconds, "A10");
292 public void TestAdd ()
294 TimeSpan t1 = new TimeSpan (2,3,4,5,6);
295 TimeSpan t2 = new TimeSpan (1,2,3,4,5);
296 TimeSpan t3 = t1 + t2;
297 TimeSpan t4 = t1.Add (t2);
301 Assert.AreEqual (3, t3.Days, "A1");
302 Assert.AreEqual (5, t3.Hours, "A2");
303 Assert.AreEqual (7, t3.Minutes, "A3");
304 Assert.AreEqual (9, t3.Seconds, "A4");
305 Assert.AreEqual (11, t3.Milliseconds, "A5");
306 Assert.AreEqual ("3.05:07:09.0110000", t4.ToString (), "A6");
309 t5 = TimeSpan.MaxValue + new TimeSpan (1);
312 catch (OverflowException)
316 Assert.IsTrue (exception, "A7");
320 public void TestCompare ()
322 TimeSpan t1 = new TimeSpan (-1);
323 TimeSpan t2 = new TimeSpan (1);
327 Assert.AreEqual (-1, TimeSpan.Compare (t1, t2), "A1");
328 Assert.AreEqual (1, TimeSpan.Compare (t2, t1), "A2");
329 Assert.AreEqual (0, TimeSpan.Compare (t2, t2), "A3");
330 Assert.AreEqual (-1, TimeSpan.Compare (TimeSpan.MinValue, TimeSpan.MaxValue), "A4");
331 Assert.AreEqual (-1, t1.CompareTo (t2), "A5");
332 Assert.AreEqual (1, t2.CompareTo (t1), "A6");
333 Assert.AreEqual (0, t2.CompareTo (t2), "A7");
334 Assert.AreEqual (-1, TimeSpan.Compare (TimeSpan.MinValue, TimeSpan.MaxValue), "A8");
336 Assert.AreEqual (1, TimeSpan.Zero.CompareTo (null), "A9");
340 res = TimeSpan.Zero.CompareTo("");
343 catch (ArgumentException)
347 Assert.IsTrue (exception, "A10");
349 Assert.AreEqual (false, t1 == t2, "A11");
350 Assert.AreEqual (false, t1 > t2, "A12");
351 Assert.AreEqual (false, t1 >= t2, "A13");
352 Assert.AreEqual (true, t1 != t2, "A14");
353 Assert.AreEqual (true, t1 < t2, "A15");
354 Assert.AreEqual (true, t1 <= t2, "A16");
358 [ExpectedException (typeof (OverflowException))]
359 public void NoNegateMinValue() {
360 TimeSpan t1 = TimeSpan.MinValue.Negate ();
364 public void TestNegateAndDuration ()
369 Assert.AreEqual ("-00:00:00.0012345", new TimeSpan (12345).Negate ().ToString (), "A1");
370 Assert.AreEqual ("00:00:00.0012345", new TimeSpan (-12345).Duration ().ToString (), "A2");
374 t1 = TimeSpan.MinValue.Duration ();
377 catch (OverflowException) {
380 Assert.IsTrue (exception, "A4");
382 Assert.AreEqual ("-00:00:00.0000077", (-(new TimeSpan (77))).ToString (), "A5");
383 Assert.AreEqual ("00:00:00.0000077", (+(new TimeSpan(77))).ToString(), "A6");
387 public void TestEquals ()
389 TimeSpan t1 = new TimeSpan (1);
390 TimeSpan t2 = new TimeSpan (2);
391 string s = "justastring";
393 Assert.AreEqual (true, t1.Equals (t1), "A1");
394 Assert.AreEqual (false, t1.Equals (t2), "A2");
395 Assert.AreEqual (false, t1.Equals (s), "A3");
396 Assert.AreEqual (false, t1.Equals (null), "A4");
397 Assert.AreEqual (true, TimeSpan.Equals (t1, t1), "A5");
398 Assert.AreEqual (false, TimeSpan.Equals (t1, t2), "A6");
399 Assert.AreEqual (false, TimeSpan.Equals (t1, null), "A7");
400 Assert.AreEqual (false, TimeSpan.Equals (t1, s), "A8");
401 Assert.AreEqual (false, TimeSpan.Equals (s, t2), "A9");
402 Assert.AreEqual (true, TimeSpan.Equals (null, null), "A10");
406 public void TestFromXXXX ()
408 Assert.AreEqual ("12.08:16:48", TimeSpan.FromDays (12.345).ToString (), "A1");
409 Assert.AreEqual ("12:20:42", TimeSpan.FromHours (12.345).ToString (), "A2");
410 Assert.AreEqual ("00:12:20.7000000", TimeSpan.FromMinutes (12.345).ToString (), "A3");
411 Assert.AreEqual ("00:00:12.3450000", TimeSpan.FromSeconds (12.345).ToString (), "A4");
412 Assert.AreEqual ("00:00:00.0120000", TimeSpan.FromMilliseconds (12.345).ToString (), "A5");
413 Assert.AreEqual ("00:00:00.0012345", TimeSpan.FromTicks (12345).ToString (), "A6");
414 Assert.AreEqual ("-00:00:00.0010000", TimeSpan.FromMilliseconds (-0.5).ToString (), "A7");
415 Assert.AreEqual ("00:00:00.0010000", TimeSpan.FromMilliseconds (0.5).ToString (), "A8");
416 Assert.AreEqual ("-00:00:00.0030000", TimeSpan.FromMilliseconds (-2.5).ToString (), "A9");
417 Assert.AreEqual ("00:00:00.0030000", TimeSpan.FromMilliseconds (2.5).ToString (), "A10");
418 Assert.AreEqual ("00:00:00.0010000", TimeSpan.FromSeconds (0.0005).ToString (), "A11");
422 [ExpectedException (typeof (OverflowException))]
423 public void FromDays_MinValue ()
425 TimeSpan.FromDays (Double.MinValue);
429 [ExpectedException (typeof (OverflowException))]
430 public void FromDays_MaxValue ()
432 TimeSpan.FromDays (Double.MaxValue);
436 [ExpectedException (typeof (ArgumentException))]
437 public void FromDays_NaN ()
439 TimeSpan.FromDays (Double.NaN);
443 [ExpectedException (typeof (OverflowException))]
444 public void FromDays_PositiveInfinity ()
446 // LAMESPEC: Document to return TimeSpan.MaxValue
447 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromDays (Double.PositiveInfinity));
451 [ExpectedException (typeof (OverflowException))]
452 public void FromDays_NegativeInfinity ()
454 // LAMESPEC: Document to return TimeSpan.MinValue
455 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromDays (Double.NegativeInfinity));
459 [ExpectedException (typeof (OverflowException))]
460 public void FromHours_MinValue ()
462 TimeSpan.FromHours (Double.MinValue);
466 [ExpectedException (typeof (OverflowException))]
467 public void FromHours_MaxValue ()
469 TimeSpan.FromHours (Double.MaxValue);
473 [ExpectedException (typeof (ArgumentException))]
474 public void FromHours_NaN ()
476 TimeSpan.FromHours (Double.NaN);
480 [ExpectedException (typeof (OverflowException))]
481 public void FromHours_PositiveInfinity ()
483 // LAMESPEC: Document to return TimeSpan.MaxValue
484 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromHours (Double.PositiveInfinity));
488 [ExpectedException (typeof (OverflowException))]
489 public void FromHours_NegativeInfinity ()
491 // LAMESPEC: Document to return TimeSpan.MinValue
492 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromHours (Double.NegativeInfinity));
496 [ExpectedException (typeof (OverflowException))]
497 public void FromMilliseconds_MinValue ()
499 TimeSpan.FromMilliseconds (Double.MinValue);
503 [ExpectedException (typeof (OverflowException))]
504 public void FromMilliseconds_MaxValue ()
506 TimeSpan.FromMilliseconds (Double.MaxValue);
510 [ExpectedException (typeof (ArgumentException))]
511 public void FromMilliseconds_NaN ()
513 TimeSpan.FromMilliseconds (Double.NaN);
517 [ExpectedException (typeof (OverflowException))]
518 public void FromMilliseconds_PositiveInfinity ()
520 // LAMESPEC: Document to return TimeSpan.MaxValue
521 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromMilliseconds (Double.PositiveInfinity));
525 [ExpectedException (typeof (OverflowException))]
526 public void FromMilliseconds_NegativeInfinity ()
528 // LAMESPEC: Document to return TimeSpan.MinValue
529 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromMilliseconds (Double.NegativeInfinity));
533 [ExpectedException (typeof (OverflowException))]
534 public void FromMinutes_MinValue ()
536 TimeSpan.FromMinutes (Double.MinValue);
540 [ExpectedException (typeof (OverflowException))]
541 public void FromMinutes_MaxValue ()
543 TimeSpan.FromMinutes (Double.MaxValue);
547 [ExpectedException (typeof (ArgumentException))]
548 public void FromMinutes_NaN ()
550 TimeSpan.FromMinutes (Double.NaN);
554 [ExpectedException (typeof (OverflowException))]
555 public void FromMinutes_PositiveInfinity ()
557 // LAMESPEC: Document to return TimeSpan.MaxValue
558 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromMinutes (Double.PositiveInfinity));
562 [ExpectedException (typeof (OverflowException))]
563 public void FromMinutes_NegativeInfinity ()
565 // LAMESPEC: Document to return TimeSpan.MinValue
566 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromMinutes (Double.NegativeInfinity));
570 [ExpectedException (typeof (OverflowException))]
571 public void FromSeconds_MinValue ()
573 TimeSpan.FromSeconds (Double.MinValue);
577 [ExpectedException (typeof (OverflowException))]
578 public void FromSeconds_MaxValue ()
580 TimeSpan.FromSeconds (Double.MaxValue);
584 [ExpectedException (typeof (ArgumentException))]
585 public void FromSeconds_NaN ()
587 TimeSpan.FromSeconds (Double.NaN);
591 [ExpectedException (typeof (OverflowException))]
592 public void FromSeconds_PositiveInfinity ()
594 // LAMESPEC: Document to return TimeSpan.MaxValue
595 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromSeconds (Double.PositiveInfinity));
599 [ExpectedException (typeof (OverflowException))]
600 public void FromSeconds_NegativeInfinity ()
602 // LAMESPEC: Document to return TimeSpan.MinValue
603 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromSeconds (Double.NegativeInfinity));
607 public void TestGetHashCode ()
609 Assert.AreEqual (77, new TimeSpan (77).GetHashCode (), "A1");
612 private void ParseHelper (string s, bool expectFormat, bool expectOverflow, string expect)
614 bool formatException = false;
615 bool overflowException = false;
616 string result = "junk ";
619 result = TimeSpan.Parse (s).ToString ();
621 catch (OverflowException) {
622 overflowException = true;
624 catch (FormatException) {
625 formatException = true;
627 Assert.AreEqual (expectFormat, formatException, "A1 [" + s + "]");
628 Assert.AreEqual (expectOverflow, overflowException, "A2 " + s + "]");
630 if (!expectOverflow && !expectFormat) {
631 Assert.AreEqual (expect, result, "A3 [" + s + "]");
636 public void TestParse ()
638 ParseHelper (" 13:45:15 ",false, false, "13:45:15");
639 ParseHelper (" -1:2:3 ", false, false, "-01:02:03");
641 // In 4.0 when the first part is out of range, it parses it as day.
642 ParseHelper (" 25:11:12 ", false, false, "25.11:12:00");
643 ParseHelper (" 24:11:12 ", false, false, "24.11:12:00");
644 ParseHelper (" 23:11:12 ", false, false, "23:11:12");
646 ParseHelper ("-21.23:59:59.9999999", false, false, "-21.23:59:59.9999999");
647 ParseHelper ("10:12 ", false, false, "10:12:00");
648 ParseHelper ("aaa", true, false, "dontcare");
650 ParseHelper ("100000000000000.1:1:1", false, true, "dontcare");
651 ParseHelper ("24:60:60", false, true, "dontcare");
652 ParseHelper ("0001:0002:0003.12 ", false, false, "01:02:03.1200000");
654 // In 4.0 when a section has more than 7 digits an OverflowException is thrown.
655 ParseHelper (" 1:2:3:12345678 ", false, true, "dontcare");
657 ParseHelper ("10:11:12:13", false, false, "10.11:12:13"); // Days using : instead of . as separator
658 ParseHelper ("10.11", true, false, "dontcare"); // days+hours is invalid
660 // Force the use of french culture -which is using a non common NumberDecimalSeparator-
661 // as current culture, to show that the Parse method is *actually* being culture sensitive
662 // *and* also keeping the compatibility with '.'
663 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
664 CultureInfo prev_culture = CultureInfo.CurrentCulture;
666 Thread.CurrentThread.CurrentCulture = french_culture;
667 ParseHelper ("10:10:10,006", false, false, "10:10:10.0060000");
668 ParseHelper ("10:10:10.006", false, false, "10:10:10.0060000");
671 Thread.CurrentThread.CurrentCulture = prev_culture;
674 ParseHelper ("00:00:00", false, false, "00:00:00");
675 ParseHelper ("00:10:00", false, false, "00:10:00");
678 // LAMESPEC: timespan in documentation is wrong - hh:mm:ss isn't mandatory
680 public void Parse_Days_WithoutColon ()
682 TimeSpan ts = TimeSpan.Parse ("1");
683 Assert.AreEqual (1, ts.Days, "Days");
687 public void TestSubstract ()
689 TimeSpan t1 = new TimeSpan (2,3,4,5,6);
690 TimeSpan t2 = new TimeSpan (1,2,3,4,5);
691 TimeSpan t3 = t1 - t2;
692 TimeSpan t4 = t1.Subtract (t2);
696 Assert.AreEqual ("1.01:01:01.0010000", t3.ToString (), "A1");
697 Assert.AreEqual ("1.01:01:01.0010000", t4.ToString (), "A2");
699 t5 = TimeSpan.MinValue - new TimeSpan (1);
702 catch (OverflowException) {
705 Assert.IsTrue (exception, "A3");
709 public void TestToString ()
711 TimeSpan t1 = new TimeSpan (1,2,3,4,5);
714 Assert.AreEqual ("1.02:03:04.0050000", t1.ToString (), "A1");
715 Assert.AreEqual ("-1.02:03:04.0050000", t2.ToString (), "A2");
716 Assert.AreEqual ("10675199.02:48:05.4775807", TimeSpan.MaxValue.ToString (), "A3");
717 Assert.AreEqual ("-10675199.02:48:05.4775808", TimeSpan.MinValue.ToString (), "A4");
721 public void ToString_Constants ()
723 Assert.AreEqual ("00:00:00", TimeSpan.Zero.ToString (), "Zero");
724 Assert.AreEqual ("10675199.02:48:05.4775807", TimeSpan.MaxValue.ToString (), "MaxValue");
725 Assert.AreEqual ("-10675199.02:48:05.4775808", TimeSpan.MinValue.ToString (), "MinValue");
729 public void Parse_InvalidValuesAndFormat_ExceptionOrder ()
731 // hours should be between 0 and 23 but format is also invalid (too many dots)
732 // In 2.0 overflow as precedence over format, but not in 4.0
734 TimeSpan.Parse ("0.99.99.0");
736 } catch (FormatException) {
739 TimeSpan.Parse ("0.999999999999.99.0");
741 } catch (OverflowException) {
746 public void Parse_MinMaxValues ()
748 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.Parse ("10675199.02:48:05.4775807"), "MaxValue");
749 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.Parse ("-10675199.02:48:05.4775808"), "MinValue");
753 [ExpectedException (typeof (OverflowException))]
754 public void Parse_OverMaxValue()
756 TimeSpan.Parse ("10675199.02:48:05.4775808");
760 [ExpectedException (typeof (OverflowException))]
761 public void Parse_UnderMinValue()
763 TimeSpan.Parse ("-10675199.02:48:05.4775809");
767 public void ParseMissingSeconds ()
769 // as seen in ML for http://resources.esri.com/arcgisserver/apis/silverlight/
770 TimeSpan ts = TimeSpan.Parse ("0:0:.75");
772 Assert.AreEqual (0, ts.Days, "Days");
773 Assert.AreEqual (0, ts.Hours, "Hours");
774 Assert.AreEqual (750, ts.Milliseconds, "Milliseconds");
775 Assert.AreEqual (0, ts.Minutes, "Minutes");
776 Assert.AreEqual (0, ts.Seconds, "Seconds");
777 Assert.AreEqual (7500000, ts.Ticks, "Ticks");
778 Assert.AreEqual (0.0000086805555555555555, ts.TotalDays, 0.00000000000000001, "TotalDays");
779 Assert.AreEqual (0.00020833333333333332, ts.TotalHours, 0.00000000000000001, "TotalHours");
780 Assert.AreEqual (750.0, ts.TotalMilliseconds, "TotalMilliseconds");
781 Assert.AreEqual (0.0125, ts.TotalMinutes, "TotalMinutes");
782 Assert.AreEqual (0.75, ts.TotalSeconds, "TotalSeconds");
785 // 'Ported' the Parse test to use TryParse
787 public void TryParse ()
791 Assert.AreEqual (true, TimeSpan.TryParse (" 13:45:15 ", out result), "#A1");
792 Assert.AreEqual ("13:45:15", result.ToString (), "#A2");
794 Assert.AreEqual (true, TimeSpan.TryParse (" -1:2:3 ", out result), "#B1");
795 Assert.AreEqual ("-01:02:03", result.ToString (), "#B2");
797 Assert.AreEqual (false, TimeSpan.TryParse ("aaa", out result), "#C2");
799 Assert.AreEqual (true, TimeSpan.TryParse ("-21.23:59:59.9999999", out result), "#D1");
800 Assert.AreEqual ("-21.23:59:59.9999999", result.ToString (), "#D2");
802 Assert.AreEqual (false, TimeSpan.TryParse ("100000000000000.1:1:1", out result), "#E1");
803 Assert.AreEqual (false, TimeSpan.TryParse ("24:60:60", out result), "#E2");
805 Assert.AreEqual (true, TimeSpan.TryParse ("0001:0002:0003.12 ", out result), "#F1");
807 Assert.AreEqual (false, TimeSpan.TryParse (" 1:2:3:12345678 ", out result), "#G1");
809 // Min and Max values
810 Assert.AreEqual (true, TimeSpan.TryParse ("10675199.02:48:05.4775807", out result), "MaxValue#1");
811 Assert.AreEqual (TimeSpan.MaxValue, result, "MaxValue#2");
812 Assert.AreEqual (true, TimeSpan.TryParse ("-10675199.02:48:05.4775808", out result), "MinValue#1");
813 Assert.AreEqual (TimeSpan.MinValue, result, "MinValue#2");
815 // Force the use of french culture -which is using a non common NumberDecimalSeparator-
816 // as current culture, to show that the Parse method is *actually* being culture sensitive
817 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
818 CultureInfo prev_culture = CultureInfo.CurrentCulture;
819 result = new TimeSpan (0, 10, 10, 10, 6);
821 Thread.CurrentThread.CurrentCulture = french_culture;
822 Assert.AreEqual (true, TimeSpan.TryParse ("10:10:10,006", out result), "#CultureSensitive1");
823 Assert.AreEqual ("10:10:10.0060000", result.ToString (), "#CultureSensitive2");
826 Thread.CurrentThread.CurrentCulture = prev_culture;
831 public void TryParseErrors ()
835 Assert.AreEqual (false, TimeSpan.TryParse ("0.99.99.0", out result), "Format#1");
836 Assert.AreEqual (false, TimeSpan.TryParse ("10675199.02:48:05.4775808", out result), "OverMaxValue");
837 Assert.AreEqual (false, TimeSpan.TryParse ("-10675199.02:48:05.4775809", out result), "UnderMinValue");
841 public void TryParseOverloads ()
845 // We use fr-FR culture since its NumericDecimalSeparator is not the same used by
846 // most cultures - including the invariant one.
847 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
848 Assert.AreEqual (true, TimeSpan.TryParse ("11:50:50,006", french_culture, out result), "#A1");
850 // LAMESPEC - msdn states that an instance of DateTimeFormatInfo is retrieved to
851 // obtain culture sensitive information, but at least in the betas that's false
852 DateTimeFormatInfo format_info = new DateTimeFormatInfo ();
853 format_info.TimeSeparator = ";";
854 Assert.AreEqual (false, TimeSpan.TryParse ("11;50;50", format_info, out result), "#B1");
855 Assert.AreEqual (true, TimeSpan.TryParse ("11:50:50", format_info, out result), "#B2");
859 public void ParseExact ()
861 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
862 CultureInfo us_culture = CultureInfo.GetCultureInfo ("en-US");
864 // At this point we are only missing the style bites and then we are
865 // pretty much done with the standard formats.
868 // 'g' format - this is the short and culture sensitive format
870 string [] g_format = new string [] { "g" };
871 ParseExactHelper ("12", g_format, false, false, "12.00:00:00");
872 ParseExactHelper ("11:12", g_format, false, false, "11:12:00");
873 ParseExactHelper ("-11:12", g_format, false, false, "-11:12:00");
874 ParseExactHelper ("25:13", g_format, true, false, "dontcare");
875 ParseExactHelper ("11:66", g_format, true, false, "dontcare"); // I'd have expected OverflowExc here
876 ParseExactHelper ("11:12:13", g_format, false, false, "11:12:13");
877 ParseExactHelper ("-11:12:13", g_format, false, false, "-11:12:13");
878 ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare"); // this should work as well
879 ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare", us_culture);
880 ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare", CultureInfo.InvariantCulture);
881 ParseExactHelper ("10:11:12:66", g_format, true, false, "dontcare");
882 ParseExactHelper ("10:11:12:13", g_format, false, false, "10.11:12:13");
883 ParseExactHelper ("11:12:13.6", g_format, false, false, "11:12:13.6000000", CultureInfo.InvariantCulture);
884 ParseExactHelper ("11:12:13,6", g_format, false, false, "11:12:13.6000000", french_culture);
885 ParseExactHelper ("10:11:12:13.6", g_format, false, false, "10.11:12:13.6000000", us_culture);
886 ParseExactHelper (" 10:11:12:13.6 ", g_format, false, false, "10.11:12:13.6000000", us_culture);
887 ParseExactHelper ("10:11", g_format, false, false, "10:11:00", null, TimeSpanStyles.None);
888 ParseExactHelper ("10:11", g_format, false, false, "10:11:00", null, TimeSpanStyles.AssumeNegative); // no effect
893 string [] G_format = new string [] { "G" };
894 ParseExactHelper ("9:10:12", G_format, true, false, "dontcare");
895 ParseExactHelper ("9:10:12.6", G_format, true, false, "dontcare");
896 ParseExactHelper ("3.9:10:12", G_format, true, false, "dontcare");
897 ParseExactHelper ("3.9:10:12.153", G_format, true, false, "dontcare"); // this should be valid...
898 ParseExactHelper ("3:9:10:12.153", G_format, false, false, "3.09:10:12.1530000", us_culture);
899 ParseExactHelper ("0:9:10:12.153", G_format, false, false, "09:10:12.1530000", us_culture);
900 ParseExactHelper ("03:09:10:12.153", G_format, false, false, "3.09:10:12.1530000", us_culture);
901 ParseExactHelper ("003:009:0010:0012.00153", G_format, false, false, "3.09:10:12.0015300", us_culture);
902 ParseExactHelper ("3:9:10:66.153", G_format, true, false, "dontcare"); // seconds out of range
903 ParseExactHelper ("3:9:10:12.153", G_format, true, false, "dontcare", french_culture); // fr-FR uses ',' as decimal separator
904 ParseExactHelper ("3:9:10:12,153", G_format, false, false, "3.09:10:12.1530000", french_culture);
905 ParseExactHelper (" 3:9:10:12.153 ", G_format, false, false, "3.09:10:12.1530000", us_culture);
906 ParseExactHelper ("3:9:10:13.153", G_format, false, false, "3.09:10:13.1530000", us_culture, TimeSpanStyles.AssumeNegative);
909 string [] c_format = new string [] { "c" };
910 ParseExactHelper ("12", c_format, false, false, "12.00:00:00");
911 ParseExactHelper ("12:11", c_format, false, false, "12:11:00");
912 ParseExactHelper ("12:66", c_format, true, false, "dontcare");
913 ParseExactHelper ("10.11:12", c_format, false, false, "10.11:12:00");
914 ParseExactHelper ("10.11:12:13", c_format, false, false, "10.11:12:13");
915 ParseExactHelper ("10:11:12:13", c_format, true, false, "dontcare"); // this is normally accepted in the Parse method
916 ParseExactHelper ("10.11:12:13.6", c_format, false, false, "10.11:12:13.6000000");
917 ParseExactHelper ("10:11:12,6", c_format, true, false, "dontcare");
918 ParseExactHelper ("10:11:12,6", c_format, true, false, "dontcare", french_culture);
919 ParseExactHelper (" 10:11:12.6 ", c_format, false, false, "10:11:12.6000000");
920 ParseExactHelper ("10:12", c_format, false, false, "10:12:00", null, TimeSpanStyles.AssumeNegative);
921 ParseExactHelper ("10:123456789999", c_format, true, false, "dontcare");
923 ParseExactHelper ("10:12", new string [0], true, false, "dontcare");
924 ParseExactHelper ("10:12", new string [] { String.Empty }, true, false, "dontcare");
925 ParseExactHelper ("10:12", new string [] { null }, true, false, "dontcare");
929 public void ParseExactMultipleFormats ()
931 ParseExactHelper ("10:12", new string [] { "G", "g" }, false, false, "10:12:00");
932 ParseExactHelper ("10:12", new string [] { "g", "G" }, false, false, "10:12:00");
933 ParseExactHelper ("7.8:9:10", new string [] { "G", "g" }, true, false, "dontcare");
934 ParseExactHelper ("7.8:9:10", new string [] { "G", "g", "c" }, false, false, "7.08:09:10");
935 ParseExactHelper ("7:8:9:10", new string [] { "c", "g" }, false, false, "7.08:09:10");
936 ParseExactHelper ("7:8:9:10", new string [] { "c", "G" }, true, false, "dontcare");
937 ParseExactHelper ("7.123456789:1", new string [] { "c", "G", "g" }, true, false, "dontcare");
938 ParseExactHelper ("7.123456789:1", new string [] { "G", "g", "c" }, true, false, "dontcare");
939 ParseExactHelper ("1234567890123456", new string [] { "c", "g" }, true, false, "dontcare"); // I'd expect an OverflowException
940 ParseExactHelper ("10:12", new string [] { null, "c", "g" }, true, false, "10:12:00");
941 ParseExactHelper ("10:12", new string [] { String.Empty, "c", "g" }, true, false, "10:12:00");
945 public void ParseExactCustomFormats ()
948 ParseExactHelper ("33", new string [] { "%d" }, false, false, "33.00:00:00");
949 ParseExactHelper ("00", new string [] { "%d" }, false, false, "00:00:00");
950 ParseExactHelper ("33", new string [] { "%dd" }, false, false, "33.00:00:00");
951 ParseExactHelper ("3333", new string [] { "%d" }, false, false, "3333.00:00:00");
952 ParseExactHelper ("3333", new string [] { "%ddd" }, true, false, "3333.00:00:00"); // 'dd' mismatch the digit count
953 ParseExactHelper ("3333", new string [] { "%dddd" }, false, false, "3333.00:00:00");
954 ParseExactHelper ("00033", new string [] { "%ddddd" }, false, false, "33.00:00:00");
955 ParseExactHelper ("00033", new string [] { "%d" }, false, false, "33.00:00:00");
956 ParseExactHelper ("00000003", new string [] { "%dddddddd" }, false, false, "3.00:00:00"); // up to 8 'd'
957 ParseExactHelper ("000000003", new string [] { "%ddddddddd" }, true, false, "dontcare");
958 ParseExactHelper ("33", new string [] { "d" }, true, false, "33.00:00:00"); // This is sort of weird.
959 ParseExactHelper ("33", new string [] { "dd" }, false, false, "33.00:00:00");
960 ParseExactHelper ("-33", new string [] { "%d" }, true, false, "dontcare");
961 ParseExactHelper ("33", new string [] { "%d" }, false, false, "-33.00:00:00", null, TimeSpanStyles.AssumeNegative);
964 ParseExactHelper ("12", new string [] { "%h" }, false, false, "12:00:00");
965 ParseExactHelper ("00", new string [] { "%h" }, false, false, "00:00:00");
966 ParseExactHelper ("012", new string [] { "%h" }, true, false, "dontcare"); // more than 2 digits
967 ParseExactHelper ("00012", new string [] { "%hhhhh" }, true, false, "dontcare");
968 ParseExactHelper ("15", new string [] { "%h" }, false, false, "15:00:00");
969 ParseExactHelper ("24", new string [] { "%h" }, true, false, "dontcare");
970 ParseExactHelper ("15", new string [] { "%hh" }, false, false, "15:00:00");
971 ParseExactHelper ("1", new string [] { "%hh" }, true, false, "dontcare"); // 'hh' but a single digit
972 ParseExactHelper ("01", new string [] { "%hh" }, false, false, "01:00:00");
973 ParseExactHelper ("015", new string [] { "%hhh" }, true, false, "dontcare"); // Too many 'h'
974 ParseExactHelper ("12", new string [] { "h" }, true, false, "dontcare");
975 ParseExactHelper ("12", new string [] { "hh" }, false, false, "12:00:00");
976 ParseExactHelper ("-15", new string [] {"%h"}, true, false, "dontcare"); // Explicit - not accepted
977 ParseExactHelper ("15", new string [] { "%h" }, false, false, "-15:00:00", null, TimeSpanStyles.AssumeNegative);
978 ParseExactHelper ("15", new string [] { "%H" }, true, false, "dontcare"); // Uppercase is not accepted
981 ParseExactHelper ("12", new string [] { "%m" }, false, false, "00:12:00");
982 ParseExactHelper ("00", new string [] { "%m" }, false, false, "00:00:00");
983 ParseExactHelper ("60", new string [] { "%m" }, true, false, "dontcare");
984 ParseExactHelper ("12", new string [] { "%mm" }, false, false, "00:12:00");
985 ParseExactHelper ("1", new string [] { "%mm" }, true, false, "dontcare");
986 ParseExactHelper ("12", new string [] { "%mmm" }, true, false, "dontcare");
987 ParseExactHelper ("12", new string [] { "m" }, true, false, "dontcare");
988 ParseExactHelper ("12", new string [] { "mm" }, false, false, "00:12:00");
989 ParseExactHelper ("-12", new string [] { "%m" }, true, false, "dontcare");
990 ParseExactHelper ("12", new string [] { "%m" }, false, false, "-00:12:00", null, TimeSpanStyles.AssumeNegative);
991 ParseExactHelper ("12", new string [] { "%M" }, true, false, "dontcare");
994 ParseExactHelper ("12", new string [] { "%s" }, false, false, "00:00:12");
995 ParseExactHelper ("00", new string [] { "%s" }, false, false, "00:00:00");
996 ParseExactHelper ("000", new string [] { "%s" }, true, false, "dontcare");
997 ParseExactHelper ("12", new string [] { "%ss" }, false, false, "00:00:12");
998 ParseExactHelper ("12", new string [] { "%sss" }, true, false, "dontcare");
999 ParseExactHelper ("60", new string [] { "%s" }, true, false, "dontcare");
1000 ParseExactHelper ("-12", new string [] { "%s" }, true, false, "dontcare");
1001 ParseExactHelper ("12", new string [] { "%s" }, false, false, "-00:00:12", null, TimeSpanStyles.AssumeNegative);
1003 // Fractions of seconds - f
1004 ParseExactHelper ("3", new string [] { "%f" }, false, false, "00:00:00.3000000");
1005 ParseExactHelper ("0", new string [] { "%f" }, false, false, "00:00:00");
1006 ParseExactHelper ("03", new string [] { "%f" }, true, false, "dontcare"); // This would work for other elements
1007 ParseExactHelper ("10", new string [] { "%f" }, true, false, "dontcare"); // Only a digit is accepted with '%f'
1008 ParseExactHelper ("3", new string [] { "%ff" }, true, false, "dontcare");
1009 ParseExactHelper ("12", new string [] { "%ff" }, false, false, "00:00:00.1200000");
1010 ParseExactHelper ("123", new string [] { "%ff" }, true, false, "dontcare");
1011 ParseExactHelper ("123", new string [] { "%fff" }, false, false, "00:00:00.1230000");
1012 ParseExactHelper ("1234", new string [] { "%ffff" }, false, false, "00:00:00.1234000");
1013 ParseExactHelper ("1234567", new string [] { "%fffffff" }, false, false, "00:00:00.1234567");
1014 ParseExactHelper ("1234567", new string [] { "%FfFFFFF" }, true, false, "dontcare"); // Mixed f and M
1015 ParseExactHelper ("12345678", new string [] { "%ffffffff" }, true, false, "dontcare");
1016 ParseExactHelper ("0000000", new string [] { "%fffffff" }, false, false, "00:00:00");
1018 // Fractions of second - F
1019 ParseExactHelper ("3", new string [] { "%F" }, false, false, "00:00:00.3000000");
1020 ParseExactHelper ("333", new string [] { "%FFFFF" }, false, false, "00:00:00.3330000");
1021 ParseExactHelper ("1234567", new string [] { "%FFFFFFF" }, false, false, "00:00:00.1234567");
1024 ParseExactHelper ("9:10", new string [] { @"h\:m" }, false, false, "09:10:00");
1025 ParseExactHelper ("9;10", new string [] { @"h\;m" }, false, false, "09:10:00");
1026 ParseExactHelper ("10:9", new string [] { @"m\:h" }, false, false, "09:10:00");
1027 ParseExactHelper ("10:9", new string [] { @"%m\:%h" }, false, false, "09:10:00");
1028 ParseExactHelper ("9 10", new string [] { @"h\ m" }, false, false, "09:10:00");
1029 ParseExactHelper ("9 10", new string [] { @"h\ \ \ m" }, false, false, "09:10:00");
1030 ParseExactHelper (" 9:10 ", new string [] { @"h\:m" }, true, false, "dontcare");
1031 ParseExactHelper ("9:10:11", new string [] { @"h\:m\:s" }, false, false, "09:10:11");
1032 ParseExactHelper ("9:10:11:6", new string [] { @"h\:m\:s\:f" }, false, false, "09:10:11.6000000");
1033 ParseExactHelper ("9:10:11:666", new string [] { @"h\:m\:s\:f" }, true, false, "dontcare"); // fff with 1 digit
1034 ParseExactHelper ("9:10:11:", new string [] { @"h\:m\:s\:F" }, false, false, "09:10:11"); // optional frac of seconds
1035 ParseExactHelper ("9:10:11:", new string [] { @"h\:m\:s\:FF" }, false, false, "09:10:11");
1036 ParseExactHelper ("9:10:11::", new string [] { @"h\:m\:s\:F\:" }, false, false, "09:10:11");
1037 ParseExactHelper ("8:9:10:11:6666666", new string [] { @"d\:h\:m\:s\:fffffff" }, false, false, "8.09:10:11.6666666");
1038 ParseExactHelper ("8:9:10:11:6666666", new string [] { @"d\:h\:m\:s\:fffffff" }, false, false, "-8.09:10:11.6666666",
1039 null, TimeSpanStyles.AssumeNegative);
1040 ParseExactHelper ("9:10", new string [] { @"h\:h" }, true, false, "dontcare"); // Repeated element
1043 ParseExactHelper (" 0 ", new string [] { "%d" }, true, false, "dontcare");
1044 ParseExactHelper (" 0 ", new string [] { " %d " }, true, false, "dontcare");
1045 ParseExactHelper ("0", new string [] { " %d " }, true, false, "dontcare");
1046 ParseExactHelper ("::", new string [] { @"\:\:" }, false, false, "00:00:00"); // funny
1047 ParseExactHelper ("::", new string [] { @"\:\:" }, false, false, "00:00:00", null, TimeSpanStyles.AssumeNegative);
1048 ParseExactHelper (" 0", new string [] { @"\ d" }, false, false, "00:00:00");
1049 ParseExactHelper ("Interval = 12:13:14", new string [] { @"'Interval = 'h\:m\:s" }, false, false, "12:13:14");
1052 void ParseExactHelper (string input, string [] formats, bool format_error, bool overflow_error, string expected,
1053 IFormatProvider formatProvider = null, TimeSpanStyles timeSpanStyles = TimeSpanStyles.None)
1055 bool overflow_exc = false;
1056 bool format_exc = false;
1057 TimeSpan result = TimeSpan.Zero;
1060 result = TimeSpan.ParseExact (input, formats, formatProvider, timeSpanStyles);
1061 } catch (OverflowException) {
1062 overflow_exc = true;
1063 } catch (FormatException) {
1067 Assert.AreEqual (format_error, format_exc, "A1");
1068 Assert.AreEqual (overflow_error, overflow_exc, "A2");
1069 if (!overflow_exc && !format_exc)
1070 Assert.AreEqual (expected, result.ToString ());
1073 // 'Ported' the ParseExact test to use TryParseExact instead.
1075 public void TryParseExact ()
1077 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
1078 CultureInfo us_culture = CultureInfo.GetCultureInfo ("en-US");
1081 // 'g' format - this is the short and culture sensitive format
1083 string [] g_format = new string [] { "g" };
1084 TryParseExactHelper ("12", g_format, false, "12.00:00:00");
1085 TryParseExactHelper ("11:12", g_format, false, "11:12:00");
1086 TryParseExactHelper ("-11:12", g_format, false, "-11:12:00");
1087 TryParseExactHelper ("25:13", g_format, true, "dontcare");
1088 TryParseExactHelper ("11:66", g_format, true, "dontcare"); // I'd have expected OverflowExc here
1089 TryParseExactHelper ("11:12:13", g_format, false, "11:12:13");
1090 TryParseExactHelper ("-11:12:13", g_format, false, "-11:12:13");
1091 TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare"); // this should work as well
1092 TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare", us_culture);
1093 TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare", CultureInfo.InvariantCulture);
1094 TryParseExactHelper ("10:11:12:66", g_format, true, "dontcare");
1095 TryParseExactHelper ("10:11:12:13", g_format, false, "10.11:12:13");
1096 TryParseExactHelper ("11:12:13.6", g_format, false, "11:12:13.6000000", CultureInfo.InvariantCulture);
1097 TryParseExactHelper ("11:12:13,6", g_format, false, "11:12:13.6000000", french_culture);
1098 TryParseExactHelper ("10:11:12:13.6", g_format, false, "10.11:12:13.6000000", us_culture);
1099 TryParseExactHelper (" 10:11:12:13.6 ", g_format, false, "10.11:12:13.6000000", us_culture);
1100 TryParseExactHelper ("10:11", g_format, false, "10:11:00", null, TimeSpanStyles.None);
1101 TryParseExactHelper ("10:11", g_format, false, "10:11:00", null, TimeSpanStyles.AssumeNegative); // no effect
1106 string [] G_format = new string [] { "G" };
1107 TryParseExactHelper ("9:10:12", G_format, true, "dontcare");
1108 TryParseExactHelper ("9:10:12.6", G_format, true, "dontcare");
1109 TryParseExactHelper ("3.9:10:12", G_format, true, "dontcare");
1110 TryParseExactHelper ("3.9:10:12.153", G_format, true, "dontcare"); // this should be valid...
1111 TryParseExactHelper ("3:9:10:12.153", G_format, false, "3.09:10:12.1530000", us_culture);
1112 TryParseExactHelper ("0:9:10:12.153", G_format, false, "09:10:12.1530000", us_culture);
1113 TryParseExactHelper ("03:09:10:12.153", G_format, false, "3.09:10:12.1530000", us_culture);
1114 TryParseExactHelper ("003:009:0010:0012.00153", G_format, false, "3.09:10:12.0015300", us_culture);
1115 TryParseExactHelper ("3:9:10:66.153", G_format, true, "dontcare"); // seconds out of range
1116 TryParseExactHelper ("3:9:10:12.153", G_format, true, "dontcare", french_culture); // fr-FR uses ',' as decimal separator
1117 TryParseExactHelper ("3:9:10:12,153", G_format, false, "3.09:10:12.1530000", french_culture);
1118 TryParseExactHelper (" 3:9:10:12.153 ", G_format, false, "3.09:10:12.1530000", us_culture);
1119 TryParseExactHelper ("3:9:10:13.153", G_format, false, "3.09:10:13.1530000", us_culture, TimeSpanStyles.AssumeNegative);
1122 string [] c_format = new string [] { "c" };
1123 TryParseExactHelper ("12", c_format, false, "12.00:00:00");
1124 TryParseExactHelper ("12:11", c_format, false, "12:11:00");
1125 TryParseExactHelper ("12:66", c_format, true, "dontcare");
1126 TryParseExactHelper ("10.11:12", c_format, false, "10.11:12:00");
1127 TryParseExactHelper ("10.11:12:13", c_format, false, "10.11:12:13");
1128 TryParseExactHelper ("10:11:12:13", c_format, true, "dontcare"); // this is normally accepted in the Parse method
1129 TryParseExactHelper ("10.11:12:13.6", c_format, false, "10.11:12:13.6000000");
1130 TryParseExactHelper ("10:11:12,6", c_format, true, "dontcare");
1131 TryParseExactHelper ("10:11:12,6", c_format, true, "dontcare", french_culture);
1132 TryParseExactHelper (" 10:11:12.6 ", c_format, false, "10:11:12.6000000");
1133 TryParseExactHelper ("10:12", c_format, false, "10:12:00", null, TimeSpanStyles.AssumeNegative);
1134 TryParseExactHelper ("10:123456789999", c_format, true, "dontcare");
1136 TryParseExactHelper ("10:12", new string [0], true, "dontcare");
1137 TryParseExactHelper ("10:12", new string [] { String.Empty }, true, "dontcare");
1138 TryParseExactHelper ("10:12", new string [] { null }, true, "dontcare");
1140 TryParseExactHelper (null, new string [] { null }, true, "dontcare");
1143 void TryParseExactHelper (string input, string [] formats, bool error, string expected, IFormatProvider formatProvider = null,
1144 TimeSpanStyles styles = TimeSpanStyles.None)
1149 success = TimeSpan.TryParseExact (input, formats, formatProvider, styles, out result);
1150 Assert.AreEqual (!error, success);
1152 Assert.AreEqual (expected, result.ToString ());
1156 public void ParseExactExceptions ()
1159 TimeSpan.ParseExact (null, "g", null);
1160 Assert.Fail ("#A1");
1161 } catch (ArgumentNullException) {
1165 TimeSpan.ParseExact ("10:12", (string)null, null);
1166 Assert.Fail ("#A2");
1167 } catch (ArgumentNullException) {
1171 TimeSpan.ParseExact ("10:12", (string [])null, null);
1172 Assert.Fail ("#A3");
1173 } catch (ArgumentNullException) {
1178 public void ToStringOverloads ()
1180 TimeSpan ts = new TimeSpan (1, 2, 3, 4, 6);
1182 // Simple version - culture invariant
1183 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (), "#A1");
1184 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("c"), "#A2");
1185 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (null), "#A3");
1186 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (String.Empty), "#A4");
1189 // IFormatProvider ones - use a culture changing numeric format.
1190 // Also, we use fr-FR as culture, since it uses some elements different to invariant culture
1192 CultureInfo culture = CultureInfo.GetCultureInfo ("fr-FR");
1194 Assert.AreEqual ("1:2:03:04,006", ts.ToString ("g", culture), "#B1");
1195 Assert.AreEqual ("1:02:03:04,0060000", ts.ToString ("G", culture), "#B2");
1196 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("c", culture), "#B3"); // 'c' format ignores CultureInfo
1197 Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("t", culture), "#B4"); // 't' and 'T' are the same as 'c'
1198 Assert.AreEqual("1.02:03:04.0060000", ts.ToString("T", culture), "#B5");
1200 ts = new TimeSpan (4, 5, 6);
1201 Assert.AreEqual ("4:05:06", ts.ToString ("g", culture), "#C1");
1202 Assert.AreEqual ("0:04:05:06,0000000", ts.ToString ("G", culture), "#C2");
1206 public void ToStringCustomFormats ()
1208 TimeSpan ts = new TimeSpan (1, 3, 5, 7);
1210 Assert.AreEqual ("1", ts.ToString ("%d"), "#A0");
1211 Assert.AreEqual ("3", ts.ToString ("%h"), "#A1");
1212 Assert.AreEqual ("5", ts.ToString ("%m"), "#A2");
1213 Assert.AreEqual ("7", ts.ToString ("%s"), "#A3");
1214 Assert.AreEqual ("0", ts.ToString ("%f"), "#A4");
1215 Assert.AreEqual (String.Empty, ts.ToString ("%F"), "#A5"); // Nothing to display
1217 Assert.AreEqual ("01", ts.ToString ("dd"), "#B0");
1218 Assert.AreEqual ("00000001", ts.ToString ("dddddddd"), "#B1");
1219 Assert.AreEqual ("03", ts.ToString ("hh"), "#B2");
1220 Assert.AreEqual ("05", ts.ToString ("mm"), "#B3");
1221 Assert.AreEqual ("07", ts.ToString ("ss"), "#B4");
1222 Assert.AreEqual ("00", ts.ToString ("ff"), "#B5");
1223 Assert.AreEqual ("0000000", ts.ToString ("fffffff"), "#B6");
1224 Assert.AreEqual (String.Empty, ts.ToString ("FF"), "#B7");
1226 Assert.AreEqual ("01;03;05", ts.ToString (@"dd\;hh\;mm"), "#C0");
1227 Assert.AreEqual ("05 07", ts.ToString (@"mm\ ss"), "#C1");
1228 Assert.AreEqual ("05 07 ", ts.ToString (@"mm\ ss\ FF"), "#C2");
1229 Assert.AreEqual ("Result = 3 hours with 5 minutes and 7 seconds",
1230 ts.ToString (@"'Result = 'h' hours with 'm' minutes and 's' seconds'"), "#C3");
1231 Assert.AreEqual (" ", ts.ToString (@"\ \ "), "#C4");
1233 ts = new TimeSpan (1, 3, 5, 7, 153);
1234 Assert.AreEqual ("1", ts.ToString ("%F"), "#D0");
1235 Assert.AreEqual ("15", ts.ToString ("FF"), "#D1"); // Don't use %, as the parser gets confused here
1236 Assert.AreEqual ("153", ts.ToString ("FFFFFFF"), "#D2");
1238 // Negative values are shown without sign
1239 ts = new TimeSpan (-1, -3, -5);
1240 Assert.AreEqual ("1", ts.ToString ("%h"), "#E0");
1241 Assert.AreEqual ("3", ts.ToString ("%m"), "#E1");
1242 Assert.AreEqual ("5", ts.ToString ("%s"), "#E2");
1244 ts = new TimeSpan (123456789);
1245 Assert.AreEqual ("12.3", ts.ToString ("s\\.f"), "#F0");
1246 Assert.AreEqual ("12.3", ts.ToString ("s\\.F"), "#F1");
1247 Assert.AreEqual ("12.3456789", ts.ToString ("s\\.fffffff"), "#F2");
1248 Assert.AreEqual ("12.345678", ts.ToString ("s\\.ffffff"), "#F3");
1250 ts = new TimeSpan (1234);
1251 Assert.AreEqual ("0.000123", ts.ToString ("s\\.ffffff"), "#G0");
1252 Assert.AreEqual ("0.0001", ts.ToString ("s\\.ffff"), "#G1");
1253 Assert.AreEqual ("0.", ts.ToString ("s\\.F"), "#G2");
1254 Assert.AreEqual ("0.", ts.ToString ("s\\.FFF"), "#G3");
1256 ts = TimeSpan.FromSeconds (0.05);
1257 Assert.AreEqual (".0", ts.ToString ("\\.f"), "#H0");
1258 Assert.AreEqual (".", ts.ToString ("\\.F"), "#H1");
1262 public void ToStringOverloadsErrors ()
1264 TimeSpan ts = new TimeSpan (10, 10, 10);
1268 result = ts.ToString ("non-valid");
1270 } catch (FormatException) {
1274 result = ts.ToString ("C");
1276 } catch (FormatException) {
1283 } catch (FormatException) {
1288 ts.ToString ("d"); // Missing % for single char
1290 } catch (FormatException)
1296 ts.ToString ("ddddddddd");
1298 } catch (FormatException)
1304 ts.ToString ("hhh");
1306 } catch (FormatException)
1312 ts.ToString ("ffffffff");
1314 } catch (FormatException)