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 Debug(TimeSpan ts)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 [Test] TestCtors()34 public void TestCtors () 35 { 36 TimeSpan t1 = new TimeSpan (1234567890); 37 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"); 49 } 50 51 [Test] 52 [ExpectedException (typeof (ArgumentOutOfRangeException))] DaysOverflow()53 public void DaysOverflow () 54 { 55 int days = (int) (Int64.MaxValue / TimeSpan.TicksPerDay) + 1; 56 TimeSpan ts = new TimeSpan (days, 0, 0, 0, 0); 57 } 58 59 [Test] 60 [ExpectedException (typeof (ArgumentOutOfRangeException))] TemporaryOverflow()61 public void TemporaryOverflow () 62 { 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"); 73 } 74 75 [Test] 76 [ExpectedException (typeof (ArgumentOutOfRangeException))] NoOverflowInHoursMinsSecondsMS()77 public void NoOverflowInHoursMinsSecondsMS () 78 { 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"); 86 } 87 88 [Test] 89 [ExpectedException (typeof (ArgumentOutOfRangeException))] MaxDays()90 public void MaxDays () 91 { 92 new TimeSpan (Int32.MaxValue, 0, 0, 0, 0); 93 } 94 95 [Test] 96 [ExpectedException (typeof (ArgumentOutOfRangeException))] MinDays()97 public void MinDays () 98 { 99 new TimeSpan (Int32.MinValue, 0, 0, 0, 0); 100 } 101 102 [Test] 103 [ExpectedException (typeof (ArgumentOutOfRangeException))] MaxHours()104 public void MaxHours () 105 { 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"); 114 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"); 122 } 123 124 [Test] 125 [ExpectedException (typeof (ArgumentOutOfRangeException))] MaxHours_BreakPoint()126 public void MaxHours_BreakPoint () 127 { 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"); 135 } 136 137 [Test] MinHours()138 public void MinHours () 139 { 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"); 147 } 148 149 [Test] 150 [ExpectedException (typeof (ArgumentOutOfRangeException))] MinHours_BreakPoint()151 public void MinHours_BreakPoint () 152 { 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"); 160 } 161 162 [Test] MaxMinutes()163 public void MaxMinutes () 164 { 165 TimeSpan ts; 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"); 173 } 174 175 [Test] 176 [ExpectedException (typeof (ArgumentOutOfRangeException))] MaxMinutes_BreakPoint()177 public void MaxMinutes_BreakPoint () 178 { 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"); 186 } 187 188 [Test] MinMinutes()189 public void MinMinutes () 190 { 191 TimeSpan ts; 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"); 199 } 200 201 [Test] MinMinutes_BreakPoint()202 public void MinMinutes_BreakPoint () 203 { 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"); 211 } 212 213 [Test] MaxSeconds()214 public void MaxSeconds () 215 { 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"); 223 } 224 225 [Test] MinSeconds()226 public void MinSeconds () 227 { 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"); 235 } 236 237 [Test] MaxMilliseconds()238 public void MaxMilliseconds () 239 { 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"); 247 } 248 249 [Test] MinMilliseconds()250 public void MinMilliseconds () 251 { 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"); 259 } 260 261 [Test] NegativeTimeSpan()262 public void NegativeTimeSpan () 263 { 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"); 271 } 272 273 [Test] TestProperties()274 public void TestProperties () 275 { 276 TimeSpan t1 = new TimeSpan (1,2,3,4,5); 277 TimeSpan t2 = -t1; 278 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"); 289 } 290 291 [Test] TestAdd()292 public void TestAdd () 293 { 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); 298 TimeSpan t5; 299 bool exception; 300 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"); 307 try 308 { 309 t5 = TimeSpan.MaxValue + new TimeSpan (1); 310 exception = false; 311 } 312 catch (OverflowException) 313 { 314 exception = true; 315 } 316 Assert.IsTrue (exception, "A7"); 317 } 318 319 [Test] TestCompare()320 public void TestCompare () 321 { 322 TimeSpan t1 = new TimeSpan (-1); 323 TimeSpan t2 = new TimeSpan (1); 324 int res; 325 bool exception; 326 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"); 335 336 Assert.AreEqual (1, TimeSpan.Zero.CompareTo (null), "A9"); 337 338 try 339 { 340 res = TimeSpan.Zero.CompareTo(""); 341 exception = false; 342 } 343 catch (ArgumentException) 344 { 345 exception = true; 346 } 347 Assert.IsTrue (exception, "A10"); 348 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"); 355 } 356 357 [Test] 358 [ExpectedException (typeof (OverflowException))] NoNegateMinValue()359 public void NoNegateMinValue() { 360 TimeSpan t1 = TimeSpan.MinValue.Negate (); 361 } 362 363 [Test] TestNegateAndDuration()364 public void TestNegateAndDuration () 365 { 366 TimeSpan t1; 367 bool exception; 368 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"); 371 372 try 373 { 374 t1 = TimeSpan.MinValue.Duration (); 375 exception = false; 376 } 377 catch (OverflowException) { 378 exception = true; 379 } 380 Assert.IsTrue (exception, "A4"); 381 382 Assert.AreEqual ("-00:00:00.0000077", (-(new TimeSpan (77))).ToString (), "A5"); 383 Assert.AreEqual ("00:00:00.0000077", (+(new TimeSpan(77))).ToString(), "A6"); 384 } 385 386 [Test] TestEquals()387 public void TestEquals () 388 { 389 TimeSpan t1 = new TimeSpan (1); 390 TimeSpan t2 = new TimeSpan (2); 391 string s = "justastring"; 392 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"); 403 } 404 405 [Test] TestFromXXXX()406 public void TestFromXXXX () 407 { 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"); 419 } 420 421 [Test] 422 [ExpectedException (typeof (OverflowException))] FromDays_MinValue()423 public void FromDays_MinValue () 424 { 425 TimeSpan.FromDays (Double.MinValue); 426 } 427 428 [Test] 429 [ExpectedException (typeof (OverflowException))] FromDays_MaxValue()430 public void FromDays_MaxValue () 431 { 432 TimeSpan.FromDays (Double.MaxValue); 433 } 434 435 [Test] 436 [ExpectedException (typeof (ArgumentException))] FromDays_NaN()437 public void FromDays_NaN () 438 { 439 TimeSpan.FromDays (Double.NaN); 440 } 441 442 [Test] 443 [ExpectedException (typeof (OverflowException))] FromDays_PositiveInfinity()444 public void FromDays_PositiveInfinity () 445 { 446 // LAMESPEC: Document to return TimeSpan.MaxValue 447 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromDays (Double.PositiveInfinity)); 448 } 449 450 [Test] 451 [ExpectedException (typeof (OverflowException))] FromDays_NegativeInfinity()452 public void FromDays_NegativeInfinity () 453 { 454 // LAMESPEC: Document to return TimeSpan.MinValue 455 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromDays (Double.NegativeInfinity)); 456 } 457 458 [Test] 459 [ExpectedException (typeof (OverflowException))] FromHours_MinValue()460 public void FromHours_MinValue () 461 { 462 TimeSpan.FromHours (Double.MinValue); 463 } 464 465 [Test] 466 [ExpectedException (typeof (OverflowException))] FromHours_MaxValue()467 public void FromHours_MaxValue () 468 { 469 TimeSpan.FromHours (Double.MaxValue); 470 } 471 472 [Test] 473 [ExpectedException (typeof (ArgumentException))] FromHours_NaN()474 public void FromHours_NaN () 475 { 476 TimeSpan.FromHours (Double.NaN); 477 } 478 479 [Test] 480 [ExpectedException (typeof (OverflowException))] FromHours_PositiveInfinity()481 public void FromHours_PositiveInfinity () 482 { 483 // LAMESPEC: Document to return TimeSpan.MaxValue 484 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromHours (Double.PositiveInfinity)); 485 } 486 487 [Test] 488 [ExpectedException (typeof (OverflowException))] FromHours_NegativeInfinity()489 public void FromHours_NegativeInfinity () 490 { 491 // LAMESPEC: Document to return TimeSpan.MinValue 492 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromHours (Double.NegativeInfinity)); 493 } 494 495 [Test] 496 [ExpectedException (typeof (OverflowException))] FromMilliseconds_MinValue()497 public void FromMilliseconds_MinValue () 498 { 499 TimeSpan.FromMilliseconds (Double.MinValue); 500 } 501 502 [Test] 503 [ExpectedException (typeof (OverflowException))] FromMilliseconds_MaxValue()504 public void FromMilliseconds_MaxValue () 505 { 506 TimeSpan.FromMilliseconds (Double.MaxValue); 507 } 508 509 [Test] 510 [ExpectedException (typeof (ArgumentException))] FromMilliseconds_NaN()511 public void FromMilliseconds_NaN () 512 { 513 TimeSpan.FromMilliseconds (Double.NaN); 514 } 515 516 [Test] 517 [ExpectedException (typeof (OverflowException))] FromMilliseconds_PositiveInfinity()518 public void FromMilliseconds_PositiveInfinity () 519 { 520 // LAMESPEC: Document to return TimeSpan.MaxValue 521 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromMilliseconds (Double.PositiveInfinity)); 522 } 523 524 [Test] 525 [ExpectedException (typeof (OverflowException))] FromMilliseconds_NegativeInfinity()526 public void FromMilliseconds_NegativeInfinity () 527 { 528 // LAMESPEC: Document to return TimeSpan.MinValue 529 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromMilliseconds (Double.NegativeInfinity)); 530 } 531 532 [Test] 533 [ExpectedException (typeof (OverflowException))] FromMinutes_MinValue()534 public void FromMinutes_MinValue () 535 { 536 TimeSpan.FromMinutes (Double.MinValue); 537 } 538 539 [Test] 540 [ExpectedException (typeof (OverflowException))] FromMinutes_MaxValue()541 public void FromMinutes_MaxValue () 542 { 543 TimeSpan.FromMinutes (Double.MaxValue); 544 } 545 546 [Test] 547 [ExpectedException (typeof (ArgumentException))] FromMinutes_NaN()548 public void FromMinutes_NaN () 549 { 550 TimeSpan.FromMinutes (Double.NaN); 551 } 552 553 [Test] 554 [ExpectedException (typeof (OverflowException))] FromMinutes_PositiveInfinity()555 public void FromMinutes_PositiveInfinity () 556 { 557 // LAMESPEC: Document to return TimeSpan.MaxValue 558 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromMinutes (Double.PositiveInfinity)); 559 } 560 561 [Test] 562 [ExpectedException (typeof (OverflowException))] FromMinutes_NegativeInfinity()563 public void FromMinutes_NegativeInfinity () 564 { 565 // LAMESPEC: Document to return TimeSpan.MinValue 566 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromMinutes (Double.NegativeInfinity)); 567 } 568 569 [Test] 570 [ExpectedException (typeof (OverflowException))] FromSeconds_MinValue()571 public void FromSeconds_MinValue () 572 { 573 TimeSpan.FromSeconds (Double.MinValue); 574 } 575 576 [Test] 577 [ExpectedException (typeof (OverflowException))] FromSeconds_MaxValue()578 public void FromSeconds_MaxValue () 579 { 580 TimeSpan.FromSeconds (Double.MaxValue); 581 } 582 583 [Test] 584 [ExpectedException (typeof (ArgumentException))] FromSeconds_NaN()585 public void FromSeconds_NaN () 586 { 587 TimeSpan.FromSeconds (Double.NaN); 588 } 589 590 [Test] 591 [ExpectedException (typeof (OverflowException))] FromSeconds_PositiveInfinity()592 public void FromSeconds_PositiveInfinity () 593 { 594 // LAMESPEC: Document to return TimeSpan.MaxValue 595 Assert.AreEqual (TimeSpan.MaxValue, TimeSpan.FromSeconds (Double.PositiveInfinity)); 596 } 597 598 [Test] 599 [ExpectedException (typeof (OverflowException))] FromSeconds_NegativeInfinity()600 public void FromSeconds_NegativeInfinity () 601 { 602 // LAMESPEC: Document to return TimeSpan.MinValue 603 Assert.AreEqual (TimeSpan.MinValue, TimeSpan.FromSeconds (Double.NegativeInfinity)); 604 } 605 606 [Test] TestGetHashCode()607 public void TestGetHashCode () 608 { 609 Assert.AreEqual (77, new TimeSpan (77).GetHashCode (), "A1"); 610 } 611 ParseHelper(string s, bool expectFormat, bool expectOverflow, string expect)612 private void ParseHelper (string s, bool expectFormat, bool expectOverflow, string expect) 613 { 614 bool formatException = false; 615 bool overflowException = false; 616 string result = "junk "; 617 618 try { 619 result = TimeSpan.Parse (s).ToString (); 620 } 621 catch (OverflowException) { 622 overflowException = true; 623 } 624 catch (FormatException) { 625 formatException = true; 626 } 627 Assert.AreEqual (expectFormat, formatException, "A1 [" + s + "]"); 628 Assert.AreEqual (expectOverflow, overflowException, "A2 " + s + "]"); 629 630 if (!expectOverflow && !expectFormat) { 631 Assert.AreEqual (expect, result, "A3 [" + s + "]"); 632 } 633 } 634 635 [Test] TestParse()636 public void TestParse () 637 { 638 ParseHelper (" 13:45:15 ",false, false, "13:45:15"); 639 ParseHelper (" -1:2:3 ", false, false, "-01:02:03"); 640 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"); 645 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"); 649 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"); 653 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"); 656 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 659 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; 665 try { 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"); 669 } finally { 670 // restore culture 671 Thread.CurrentThread.CurrentCulture = prev_culture; 672 } 673 674 ParseHelper ("00:00:00", false, false, "00:00:00"); 675 ParseHelper ("00:10:00", false, false, "00:10:00"); 676 } 677 678 // LAMESPEC: timespan in documentation is wrong - hh:mm:ss isn't mandatory 679 [Test] Parse_Days_WithoutColon()680 public void Parse_Days_WithoutColon () 681 { 682 TimeSpan ts = TimeSpan.Parse ("1"); 683 Assert.AreEqual (1, ts.Days, "Days"); 684 } 685 686 [Test] TestSubstract()687 public void TestSubstract () 688 { 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); 693 TimeSpan t5; 694 bool exception; 695 696 Assert.AreEqual ("1.01:01:01.0010000", t3.ToString (), "A1"); 697 Assert.AreEqual ("1.01:01:01.0010000", t4.ToString (), "A2"); 698 try { 699 t5 = TimeSpan.MinValue - new TimeSpan (1); 700 exception = false; 701 } 702 catch (OverflowException) { 703 exception = true; 704 } 705 Assert.IsTrue (exception, "A3"); 706 } 707 708 [Test] TestToString()709 public void TestToString () 710 { 711 TimeSpan t1 = new TimeSpan (1,2,3,4,5); 712 TimeSpan t2 = -t1; 713 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"); 718 } 719 720 [Test] ToString_Constants()721 public void ToString_Constants () 722 { 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"); 726 } 727 728 [Test] Parse_InvalidValuesAndFormat_ExceptionOrder()729 public void Parse_InvalidValuesAndFormat_ExceptionOrder () 730 { 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 733 try { 734 TimeSpan.Parse ("0.99.99.0"); 735 Assert.Fail ("#A1"); 736 } catch (FormatException) { 737 } 738 try { 739 TimeSpan.Parse ("0.999999999999.99.0"); 740 Assert.Fail ("#A2"); 741 } catch (OverflowException) { 742 } 743 } 744 745 [Test] Parse_MinMaxValues()746 public void Parse_MinMaxValues () 747 { 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"); 750 } 751 752 [Test] 753 [ExpectedException (typeof (OverflowException))] Parse_OverMaxValue()754 public void Parse_OverMaxValue() 755 { 756 TimeSpan.Parse ("10675199.02:48:05.4775808"); 757 } 758 759 [Test] 760 [ExpectedException (typeof (OverflowException))] Parse_UnderMinValue()761 public void Parse_UnderMinValue() 762 { 763 TimeSpan.Parse ("-10675199.02:48:05.4775809"); 764 } 765 766 [Test] ParseMissingSeconds()767 public void ParseMissingSeconds () 768 { 769 // as seen in ML for http://resources.esri.com/arcgisserver/apis/silverlight/ 770 TimeSpan ts = TimeSpan.Parse ("0:0:.75"); 771 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"); 783 } 784 785 // 'Ported' the Parse test to use TryParse 786 [Test] TryParse()787 public void TryParse () 788 { 789 TimeSpan result; 790 791 Assert.AreEqual (true, TimeSpan.TryParse (" 13:45:15 ", out result), "#A1"); 792 Assert.AreEqual ("13:45:15", result.ToString (), "#A2"); 793 794 Assert.AreEqual (true, TimeSpan.TryParse (" -1:2:3 ", out result), "#B1"); 795 Assert.AreEqual ("-01:02:03", result.ToString (), "#B2"); 796 797 Assert.AreEqual (false, TimeSpan.TryParse ("aaa", out result), "#C2"); 798 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"); 801 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"); 804 805 Assert.AreEqual (true, TimeSpan.TryParse ("0001:0002:0003.12 ", out result), "#F1"); 806 807 Assert.AreEqual (false, TimeSpan.TryParse (" 1:2:3:12345678 ", out result), "#G1"); 808 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"); 814 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); 820 try { 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"); 824 } finally { 825 // restore culture 826 Thread.CurrentThread.CurrentCulture = prev_culture; 827 } 828 } 829 830 [Test] TryParseErrors()831 public void TryParseErrors () 832 { 833 TimeSpan result; 834 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"); 838 } 839 840 [Test] TryParseOverloads()841 public void TryParseOverloads () 842 { 843 TimeSpan result; 844 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"); 849 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"); 856 } 857 858 [Test] ParseExact()859 public void ParseExact () 860 { 861 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR"); 862 CultureInfo us_culture = CultureInfo.GetCultureInfo ("en-US"); 863 864 // At this point we are only missing the style bites and then we are 865 // pretty much done with the standard formats. 866 867 // 868 // 'g' format - this is the short and culture sensitive format 869 // 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 889 890 // 891 // G format 892 // 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); 907 908 // c format 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"); 922 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"); 926 } 927 928 [Test] ParseExactMultipleFormats()929 public void ParseExactMultipleFormats () 930 { 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"); 942 } 943 944 [Test] ParseExactCustomFormats()945 public void ParseExactCustomFormats () 946 { 947 // Days 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); 962 963 // Hours 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 979 980 // Minutes 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"); 992 993 // Seconds 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); 1002 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"); 1017 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"); 1022 1023 // Multiple symbols 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 1041 1042 // Misc 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"); 1050 } 1051 ParseExactHelper(string input, string [] formats, bool format_error, bool overflow_error, string expected, IFormatProvider formatProvider = null, TimeSpanStyles timeSpanStyles = TimeSpanStyles.None)1052 void ParseExactHelper (string input, string [] formats, bool format_error, bool overflow_error, string expected, 1053 IFormatProvider formatProvider = null, TimeSpanStyles timeSpanStyles = TimeSpanStyles.None) 1054 { 1055 bool overflow_exc = false; 1056 bool format_exc = false; 1057 TimeSpan result = TimeSpan.Zero; 1058 1059 try { 1060 result = TimeSpan.ParseExact (input, formats, formatProvider, timeSpanStyles); 1061 } catch (OverflowException) { 1062 overflow_exc = true; 1063 } catch (FormatException) { 1064 format_exc = true; 1065 } 1066 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 ()); 1071 } 1072 1073 // 'Ported' the ParseExact test to use TryParseExact instead. 1074 [Test] TryParseExact()1075 public void TryParseExact () 1076 { 1077 CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR"); 1078 CultureInfo us_culture = CultureInfo.GetCultureInfo ("en-US"); 1079 1080 // 1081 // 'g' format - this is the short and culture sensitive format 1082 // 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 1102 1103 // 1104 // G format 1105 // 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); 1120 1121 // c format 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"); 1135 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"); 1139 1140 TryParseExactHelper (null, new string [] { null }, true, "dontcare"); 1141 } 1142 TryParseExactHelper(string input, string [] formats, bool error, string expected, IFormatProvider formatProvider = null, TimeSpanStyles styles = TimeSpanStyles.None)1143 void TryParseExactHelper (string input, string [] formats, bool error, string expected, IFormatProvider formatProvider = null, 1144 TimeSpanStyles styles = TimeSpanStyles.None) 1145 { 1146 TimeSpan result; 1147 bool success; 1148 1149 success = TimeSpan.TryParseExact (input, formats, formatProvider, styles, out result); 1150 Assert.AreEqual (!error, success); 1151 if (!error) 1152 Assert.AreEqual (expected, result.ToString ()); 1153 } 1154 1155 [Test] ParseExactExceptions()1156 public void ParseExactExceptions () 1157 { 1158 try { 1159 TimeSpan.ParseExact (null, "g", null); 1160 Assert.Fail ("#A1"); 1161 } catch (ArgumentNullException) { 1162 } 1163 1164 try { 1165 TimeSpan.ParseExact ("10:12", (string)null, null); 1166 Assert.Fail ("#A2"); 1167 } catch (ArgumentNullException) { 1168 } 1169 1170 try { 1171 TimeSpan.ParseExact ("10:12", (string [])null, null); 1172 Assert.Fail ("#A3"); 1173 } catch (ArgumentNullException) { 1174 } 1175 } 1176 1177 [Test] ToStringOverloads()1178 public void ToStringOverloads () 1179 { 1180 TimeSpan ts = new TimeSpan (1, 2, 3, 4, 6); 1181 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"); 1187 1188 // 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 1191 // 1192 CultureInfo culture = CultureInfo.GetCultureInfo ("fr-FR"); 1193 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"); 1199 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"); 1203 } 1204 1205 [Test] ToStringCustomFormats()1206 public void ToStringCustomFormats () 1207 { 1208 TimeSpan ts = new TimeSpan (1, 3, 5, 7); 1209 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 1216 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"); 1225 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"); 1232 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"); 1237 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"); 1243 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"); 1249 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"); 1255 1256 ts = TimeSpan.FromSeconds (0.05); 1257 Assert.AreEqual (".0", ts.ToString ("\\.f"), "#H0"); 1258 Assert.AreEqual (".", ts.ToString ("\\.F"), "#H1"); 1259 } 1260 1261 [Test] ToStringOverloadsErrors()1262 public void ToStringOverloadsErrors () 1263 { 1264 TimeSpan ts = new TimeSpan (10, 10, 10); 1265 string result; 1266 1267 try { 1268 result = ts.ToString ("non-valid"); 1269 Assert.Fail ("#1"); 1270 } catch (FormatException) { 1271 } 1272 1273 try { 1274 result = ts.ToString ("C"); 1275 Assert.Fail ("#2"); 1276 } catch (FormatException) { 1277 } 1278 1279 try 1280 { 1281 ts.ToString ("m"); 1282 Assert.Fail ("#3"); 1283 } catch (FormatException) { 1284 } 1285 1286 try 1287 { 1288 ts.ToString ("d"); // Missing % for single char 1289 Assert.Fail ("#4"); 1290 } catch (FormatException) 1291 { 1292 } 1293 1294 try 1295 { 1296 ts.ToString ("ddddddddd"); 1297 Assert.Fail ("#5"); 1298 } catch (FormatException) 1299 { 1300 } 1301 1302 try 1303 { 1304 ts.ToString ("hhh"); 1305 Assert.Fail ("#5"); 1306 } catch (FormatException) 1307 { 1308 } 1309 1310 try 1311 { 1312 ts.ToString ("ffffffff"); 1313 Assert.Fail ("6"); 1314 } catch (FormatException) 1315 { 1316 } 1317 } 1318 } 1319 1320 } 1321