5 // Duco Fijma (duco@lorentz.xs4all.nl)
6 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 // Sebastien Pouliot <sebastien@ximian.com>
10 // (C) 2004 Andreas Nahr
11 // Copyright (C) 2004 Novell (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System
.Threading
;
35 using System
.Globalization
;
40 [System
.Runtime
.InteropServices
.ComVisible (true)]
41 public struct TimeSpan
: IComparable
, IComparable
<TimeSpan
>, IEquatable
<TimeSpan
>
48 if (MonoTouchAOTHelper
.FalseFlag
) {
49 var comparer
= new System
.Collections
.Generic
.GenericComparer
<TimeSpan
> ();
50 var eqcomparer
= new System
.Collections
.Generic
.GenericEqualityComparer
<TimeSpan
> ();
54 public static readonly TimeSpan MaxValue
= new TimeSpan (long.MaxValue
);
55 public static readonly TimeSpan MinValue
= new TimeSpan (long.MinValue
);
56 public static readonly TimeSpan Zero
= new TimeSpan (0L);
58 public const long TicksPerDay
= 864000000000L;
59 public const long TicksPerHour
= 36000000000L;
60 public const long TicksPerMillisecond
= 10000L;
61 public const long TicksPerMinute
= 600000000L;
62 public const long TicksPerSecond
= 10000000L;
66 public TimeSpan (long ticks
)
71 public TimeSpan (int hours
, int minutes
, int seconds
)
73 CalculateTicks (0, hours
, minutes
, seconds
, 0, true, out _ticks
);
76 public TimeSpan (int days
, int hours
, int minutes
, int seconds
)
78 CalculateTicks (days
, hours
, minutes
, seconds
, 0, true, out _ticks
);
81 public TimeSpan (int days
, int hours
, int minutes
, int seconds
, int milliseconds
)
83 CalculateTicks (days
, hours
, minutes
, seconds
, milliseconds
, true, out _ticks
);
86 internal static bool CalculateTicks (int days
, int hours
, int minutes
, int seconds
, int milliseconds
, bool throwExc
, out long result
)
88 // there's no overflow checks for hours, minutes, ...
89 // so big hours/minutes values can overflow at some point and change expected values
90 int hrssec
= (hours
* 3600); // break point at (Int32.MaxValue - 596523)
91 int minsec
= (minutes
* 60);
92 long t
= ((long)(hrssec
+ minsec
+ seconds
) * 1000L + (long)milliseconds
);
97 bool overflow
= false;
98 // days is problematic because it can overflow but that overflow can be
99 // "legal" (i.e. temporary) (e.g. if other parameters are negative) or
100 // illegal (e.g. sign change).
102 long td
= TicksPerDay
* days
;
106 // positive days -> total ticks should be lower
107 overflow
= (ticks
> t
);
111 // positive + positive != negative result
116 long td
= TicksPerDay
* days
;
119 // negative + negative != positive result
125 // negative days -> total ticks should be lower
126 overflow
= (t
> ticks
);
132 throw new ArgumentOutOfRangeException (Locale
.GetText ("The timespan is too big or too small."));
142 return (int) (_ticks
/ TicksPerDay
);
148 return (int) (_ticks
% TicksPerDay
/ TicksPerHour
);
152 public int Milliseconds
{
154 return (int) (_ticks
% TicksPerSecond
/ TicksPerMillisecond
);
160 return (int) (_ticks
% TicksPerHour
/ TicksPerMinute
);
166 return (int) (_ticks
% TicksPerMinute
/ TicksPerSecond
);
176 public double TotalDays
{
178 return (double) _ticks
/ TicksPerDay
;
182 public double TotalHours
{
184 return (double) _ticks
/ TicksPerHour
;
188 public double TotalMilliseconds
{
190 return (double) _ticks
/ TicksPerMillisecond
;
194 public double TotalMinutes
{
196 return (double) _ticks
/ TicksPerMinute
;
200 public double TotalSeconds
{
202 return (double) _ticks
/ TicksPerSecond
;
206 public TimeSpan
Add (TimeSpan ts
)
210 return new TimeSpan (_ticks
+ ts
.Ticks
);
213 catch (OverflowException
) {
214 throw new OverflowException (Locale
.GetText ("Resulting timespan is too big."));
218 public static int Compare (TimeSpan t1
, TimeSpan t2
)
220 if (t1
._ticks
< t2
._ticks
)
222 if (t1
._ticks
> t2
._ticks
)
227 public int CompareTo (object value)
232 if (!(value is TimeSpan
)) {
233 throw new ArgumentException (Locale
.GetText ("Argument has to be a TimeSpan."), "value");
236 return Compare (this, (TimeSpan
) value);
239 public int CompareTo (TimeSpan
value)
241 return Compare (this, value);
244 public bool Equals (TimeSpan obj
)
246 return obj
._ticks
== _ticks
;
249 public TimeSpan
Duration ()
253 return new TimeSpan (Math
.Abs (_ticks
));
256 catch (OverflowException
) {
257 throw new OverflowException (Locale
.GetText (
258 "This TimeSpan value is MinValue so you cannot get the duration."));
262 public override bool Equals (object value)
264 if (!(value is TimeSpan
))
267 return _ticks
== ((TimeSpan
) value)._ticks
;
270 public static bool Equals (TimeSpan t1
, TimeSpan t2
)
272 return t1
._ticks
== t2
._ticks
;
275 public static TimeSpan
FromDays (double value)
277 return From (value, TicksPerDay
);
280 public static TimeSpan
FromHours (double value)
282 return From (value, TicksPerHour
);
285 public static TimeSpan
FromMinutes (double value)
287 return From (value, TicksPerMinute
);
290 public static TimeSpan
FromSeconds (double value)
292 return From (value, TicksPerSecond
);
295 public static TimeSpan
FromMilliseconds (double value)
297 return From (value, TicksPerMillisecond
);
300 private static TimeSpan
From (double value, long tickMultiplicator
)
302 if (Double
.IsNaN (value))
303 throw new ArgumentException (Locale
.GetText ("Value cannot be NaN."), "value");
304 if (Double
.IsNegativeInfinity (value) || Double
.IsPositiveInfinity (value) ||
305 (value < MinValue
.Ticks
) || (value > MaxValue
.Ticks
))
306 throw new OverflowException (Locale
.GetText ("Outside range [MinValue,MaxValue]"));
309 value = (value * (tickMultiplicator
/ TicksPerMillisecond
));
312 long val
= (long) Math
.Round(value);
313 return new TimeSpan (val
* TicksPerMillisecond
);
316 catch (OverflowException
) {
317 throw new OverflowException (Locale
.GetText ("Resulting timespan is too big."));
321 public static TimeSpan
FromTicks (long value)
323 return new TimeSpan (value);
326 public override int GetHashCode ()
328 return _ticks
.GetHashCode ();
331 public TimeSpan
Negate ()
333 if (_ticks
== MinValue
._ticks
)
334 throw new OverflowException (Locale
.GetText (
335 "This TimeSpan value is MinValue and cannot be negated."));
336 return new TimeSpan (-_ticks
);
339 public static TimeSpan
Parse (string s
)
342 throw new ArgumentNullException ("s");
346 Parser p
= new Parser (s
);
347 p
.Execute (false, out result
);
351 public static bool TryParse (string s
, out TimeSpan result
)
354 result
= TimeSpan
.Zero
;
358 Parser p
= new Parser (s
);
359 return p
.Execute (true, out result
);
363 public static TimeSpan
Parse (string s
, IFormatProvider formatProvider
)
366 throw new ArgumentNullException ("s");
369 Parser p
= new Parser (s
, formatProvider
);
370 p
.Execute (false, out result
);
374 public static bool TryParse (string s
, IFormatProvider formatProvider
, out TimeSpan result
)
376 if (s
== null || s
.Length
== 0) {
377 result
= TimeSpan
.Zero
;
381 Parser p
= new Parser (s
, formatProvider
);
382 return p
.Execute (true, out result
);
385 public static TimeSpan
ParseExact (string input
, string format
, IFormatProvider formatProvider
)
388 throw new ArgumentNullException ("format");
390 return ParseExact (input
, new string [] { format }
, formatProvider
, TimeSpanStyles
.None
);
393 public static TimeSpan
ParseExact (string input
, string format
, IFormatProvider formatProvider
, TimeSpanStyles styles
)
396 throw new ArgumentNullException ("format");
398 return ParseExact (input
, new string [] { format }
, formatProvider
, styles
);
401 public static TimeSpan
ParseExact (string input
, string [] formats
, IFormatProvider formatProvider
)
403 return ParseExact (input
, formats
, formatProvider
, TimeSpanStyles
.None
);
406 public static TimeSpan
ParseExact (string input
, string [] formats
, IFormatProvider formatProvider
, TimeSpanStyles styles
)
409 throw new ArgumentNullException ("input");
411 throw new ArgumentNullException ("formats");
413 // All the errors found during the parsing process are reported as FormatException.
415 if (!TryParseExact (input
, formats
, formatProvider
, styles
, out result
))
416 throw new FormatException ("Invalid format.");
421 public static bool TryParseExact (string input
, string format
, IFormatProvider formatProvider
, out TimeSpan result
)
423 return TryParseExact (input
, new string [] { format }
, formatProvider
, TimeSpanStyles
.None
, out result
);
426 public static bool TryParseExact (string input
, string format
, IFormatProvider formatProvider
, TimeSpanStyles styles
,
429 return TryParseExact (input
, new string [] { format }
, formatProvider
, styles
, out result
);
432 public static bool TryParseExact (string input
, string [] formats
, IFormatProvider formatProvider
, out TimeSpan result
)
434 return TryParseExact (input
, formats
, formatProvider
, TimeSpanStyles
.None
, out result
);
437 public static bool TryParseExact (string input
, string [] formats
, IFormatProvider formatProvider
, TimeSpanStyles styles
,
440 result
= TimeSpan
.Zero
;
442 if (formats
== null || formats
.Length
== 0)
445 Parser p
= new Parser (input
, formatProvider
);
448 foreach (string format
in formats
) {
449 if (format
== null || format
.Length
== 0)
450 return false; // wrong format, return immediately.
454 p
.AllMembersRequired
= false;
455 p
.CultureSensitive
= true;
456 p
.UseColonAsDaySeparator
= true;
459 p
.AllMembersRequired
= true;
460 p
.CultureSensitive
= true;
461 p
.UseColonAsDaySeparator
= true;
464 p
.AllMembersRequired
= false;
465 p
.CultureSensitive
= false;
466 p
.UseColonAsDaySeparator
= false;
468 default: // custom format
469 throw new NotImplementedException ();
472 if (p
.Execute (true, out result
))
480 public TimeSpan
Subtract (TimeSpan ts
)
484 return new TimeSpan (_ticks
- ts
.Ticks
);
487 catch (OverflowException
) {
488 throw new OverflowException (Locale
.GetText ("Resulting timespan is too big."));
492 public override string ToString ()
494 StringBuilder sb
= new StringBuilder (14);
499 // We need to take absolute values of all components.
500 // Can't handle negative timespans by negating the TimeSpan
501 // as a whole. This would lead to an overflow for the
502 // degenerate case "TimeSpan.MinValue.ToString()".
504 sb
.Append (Math
.Abs (Days
));
508 sb
.Append (Math
.Abs (Hours
).ToString ("D2"));
510 sb
.Append (Math
.Abs (Minutes
).ToString ("D2"));
512 sb
.Append (Math
.Abs (Seconds
).ToString ("D2"));
514 int fractional
= (int) Math
.Abs (_ticks
% TicksPerSecond
);
515 if (fractional
!= 0) {
517 sb
.Append (fractional
.ToString ("D7"));
520 return sb
.ToString ();
524 public string ToString (string format
)
526 return ToString (format
, null);
529 public string ToString (string format
, IFormatProvider formatProvider
)
531 if (format
== null || format
.Length
== 0 || format
== "c") // Default version
534 if (format
!= "g" && format
!= "G")
535 throw new FormatException ("The format is not recognized.");
537 NumberFormatInfo number_info
= null;
538 if (formatProvider
!= null)
539 number_info
= (NumberFormatInfo
)formatProvider
.GetFormat (typeof (NumberFormatInfo
));
540 if (number_info
== null)
541 number_info
= Thread
.CurrentThread
.CurrentCulture
.NumberFormat
;
543 string decimal_separator
= number_info
.NumberDecimalSeparator
;
544 int days
, hours
, minutes
, seconds
, milliseconds
, fractional
;
546 days
= Math
.Abs (Days
);
547 hours
= Math
.Abs (Hours
);
548 minutes
= Math
.Abs (Minutes
);
549 seconds
= Math
.Abs (Seconds
);
550 milliseconds
= Math
.Abs (Milliseconds
);
551 fractional
= (int) Math
.Abs (_ticks
% TicksPerSecond
);
553 // Set Capacity depending on whether it's long or shot format
554 StringBuilder sb
= new StringBuilder (format
== "g" ? 16 : 32);
559 case "g": // short version
561 sb
.Append (days
.ToString ());
564 sb
.Append (hours
.ToString ());
566 sb
.Append (minutes
.ToString ("D2"));
568 sb
.Append (seconds
.ToString ("D2"));
569 if (milliseconds
!= 0) {
570 sb
.Append (decimal_separator
);
571 sb
.Append (milliseconds
.ToString ("D3"));
574 case "G": // long version
575 sb
.Append (days
.ToString ("D1"));
577 sb
.Append (hours
.ToString ("D2"));
579 sb
.Append (minutes
.ToString ("D2"));
581 sb
.Append (seconds
.ToString ("D2"));
582 sb
.Append (decimal_separator
);
583 sb
.Append (fractional
.ToString ("D7"));
587 return sb
.ToString ();
591 public static TimeSpan
operator + (TimeSpan t1
, TimeSpan t2
)
596 public static bool operator == (TimeSpan t1
, TimeSpan t2
)
598 return t1
._ticks
== t2
._ticks
;
601 public static bool operator > (TimeSpan t1
, TimeSpan t2
)
603 return t1
._ticks
> t2
._ticks
;
606 public static bool operator >= (TimeSpan t1
, TimeSpan t2
)
608 return t1
._ticks
>= t2
._ticks
;
611 public static bool operator != (TimeSpan t1
, TimeSpan t2
)
613 return t1
._ticks
!= t2
._ticks
;
616 public static bool operator < (TimeSpan t1
, TimeSpan t2
)
618 return t1
._ticks
< t2
._ticks
;
621 public static bool operator <= (TimeSpan t1
, TimeSpan t2
)
623 return t1
._ticks
<= t2
._ticks
;
626 public static TimeSpan
operator - (TimeSpan t1
, TimeSpan t2
)
628 return t1
.Subtract (t2
);
631 public static TimeSpan
operator - (TimeSpan t
)
636 public static TimeSpan
operator + (TimeSpan t
)
647 // Class Parser implements parser for TimeSpan.Parse
651 private int _cur
= 0;
653 ParseError parse_error
;
656 NumberFormatInfo number_format
;
657 int parsed_numbers_count
;
658 bool parsed_days_separator
;
660 public bool Exact
; // no fallback, strict pattern.
661 public bool AllMembersRequired
;
662 public bool CultureSensitive
= true;
663 public bool UseColonAsDaySeparator
= true;
666 public Parser (string src
)
669 _length
= _src
.Length
;
671 number_format
= GetNumberFormatInfo (null);
676 // Reset state data, so we can execute another parse over the input.
680 parse_error
= ParseError
.None
;
681 parsed_ticks
= parsed_days_separator
= false;
682 parsed_numbers_count
= 0;
685 public Parser (string src
, IFormatProvider formatProvider
) :
688 number_format
= GetNumberFormatInfo (formatProvider
);
691 NumberFormatInfo
GetNumberFormatInfo (IFormatProvider formatProvider
)
693 NumberFormatInfo format
= null;
694 if (formatProvider
!= null)
695 format
= (NumberFormatInfo
) formatProvider
.GetFormat (typeof (NumberFormatInfo
));
697 format
= Thread
.CurrentThread
.CurrentCulture
.NumberFormat
;
705 return _cur
>= _length
;
709 // All "Parse" functions throw a FormatException on syntax error.
710 // Their return value is semantic value of the item parsed.
712 // Range checking is spread over three different places:
713 // 1) When parsing "int" values, an exception is thrown immediately
714 // when the value parsed exceeds the maximum value for an int.
715 // 2) An explicit check is built in that checks for hours > 23 and
716 // for minutes and seconds > 59.
717 // 3) Throwing an exceptions for a final TimeSpan value > MaxValue
718 // or < MinValue is left to the TimeSpan constructor called.
720 // Parse zero or more whitespace chars.
721 private void ParseWhiteSpace ()
723 while (!AtEnd
&& Char
.IsWhiteSpace (_src
, _cur
)) {
728 // Parse optional sign character.
729 private bool ParseSign ()
733 if (!AtEnd
&& _src
[_cur
] == '-') {
741 // Parse simple int value
742 private int ParseInt (bool optional
)
744 if (optional
&& AtEnd
)
750 while (!AtEnd
&& Char
.IsDigit (_src
, _cur
)) {
751 res
= res
* 10 + _src
[_cur
] - '0';
753 // more than one preceding zero will case an OverflowException
754 if (res
> Int32
.MaxValue
|| (count
>= 1 && res
== 0)) {
756 if (res
> Int32
.MaxValue
) {
758 SetParseError (ParseError
.Overflow
);
765 if (!optional
&& (count
== 0))
766 SetParseError (ParseError
.Format
);
769 parsed_numbers_count
++;
775 // Parse optional dot
776 private bool ParseOptDot ()
781 if (_src
[_cur
] == '.') {
789 // This behaves pretty much like ParseOptDot, but we need to have it
790 // as a separated routine for both days and decimal separators.
791 private bool ParseOptDaysSeparator ()
796 if (_src
[_cur
] == '.') {
798 parsed_days_separator
= true;
804 // Just as ParseOptDot, but for decimal separator
805 private bool ParseOptDecimalSeparator ()
810 // we may need to provide compatibility with old versions using '.'
811 // for culture insensitve and non exact formats.
812 if (!Exact
|| !CultureSensitive
)
813 if (_src
[_cur
] == '.') {
818 string decimal_separator
= number_format
.NumberDecimalSeparator
;
819 if (CultureSensitive
&& String
.Compare (_src
, _cur
, decimal_separator
, 0, decimal_separator
.Length
) == 0) {
820 _cur
+= decimal_separator
.Length
;
828 private void ParseColon (bool optional
)
831 if (_src
[_cur
] == ':')
834 SetParseError (ParseError
.Format
);
838 // Parse [1..7] digits, representing fractional seconds (ticks)
839 // In 4.0 more than 7 digits will cause an OverflowException
840 private long ParseTicks ()
844 bool digitseen
= false;
846 while (mag
> 0 && !AtEnd
&& Char
.IsDigit (_src
, _cur
)) {
847 res
= res
+ (_src
[_cur
] - '0') * mag
;
854 SetParseError (ParseError
.Format
);
856 else if (!AtEnd
&& Char
.IsDigit (_src
, _cur
))
857 SetParseError (ParseError
.Overflow
);
865 void SetParseError (ParseError error
)
867 // We preserve the very first error.
868 if (parse_error
!= ParseError
.None
)
875 bool CheckParseSuccess (bool tryParse
)
877 bool CheckParseSuccess (int hours
, int minutes
, int seconds
, bool tryParse
)
880 // We always report the first error, but for 2.0 we need to give a higher
881 // precence to per-element overflow (as opposed to int32 overflow).
883 if (parse_error
== ParseError
.Overflow
) {
885 if (parse_error
== ParseError
.Overflow
|| hours
> 23 || minutes
> 59 || seconds
> 59) {
889 throw new OverflowException (
890 Locale
.GetText ("Invalid time data."));
893 if (parse_error
== ParseError
.Format
) {
896 throw new FormatException (
897 Locale
.GetText ("Invalid format for TimeSpan.Parse."));
904 // We are using a different parse approach in 4.0, due to some changes in the behaviour
905 // of the parse routines.
906 // The input string is documented as:
907 // Parse [ws][-][dd.]hh:mm:ss[.ff][ws]
909 // There are some special cases as part of 4.0, however:
910 // 1. ':' *can* be used as days separator, instead of '.', making valid the format 'dd:hh:mm:ss'
911 // 2. A input in the format 'hh:mm:ss' will end up assigned as 'dd.hh:mm' if the first int has a value
912 // exceeding the valid range for hours: 0-23.
913 // 3. The decimal separator can be retrieved from the current culture, as well as keeping support
914 // for the '.' value as part of keeping compatibility.
916 // So we take the approach to parse, if possible, 4 integers, and depending on both how many were
917 // actually parsed and what separators were read, assign the values to days/hours/minutes/seconds.
919 public bool Execute (bool tryParse
, out TimeSpan result
)
922 int value1
, value2
, value3
, value4
;
923 int days
, hours
, minutes
, seconds
;
926 result
= TimeSpan
.Zero
;
927 value1
= value2
= value3
= value4
= 0;
928 days
= hours
= minutes
= seconds
= 0;
935 // Parse 4 integers, making only the first one non-optional.
936 value1
= ParseInt (false);
937 if (!ParseOptDaysSeparator ()) // Parse either day separator or colon
939 value2
= ParseInt (true);
941 value3
= ParseInt (true);
943 value4
= ParseInt (true);
945 // We know the precise separator for ticks, so there's no need to guess.
946 if (ParseOptDecimalSeparator ())
947 ticks
= ParseTicks ();
952 SetParseError (ParseError
.Format
);
955 // In Exact mode we cannot allow both ':' and '.' as day separator.
956 if (UseColonAsDaySeparator
&& parsed_days_separator
||
957 AllMembersRequired
&& (parsed_numbers_count
< 4 || !parsed_ticks
))
958 SetParseError (ParseError
.Format
);
960 switch (parsed_numbers_count
) {
964 case 2: // Two elements are valid only if they are *exactly* in the format: 'hh:mm'
965 if (parsed_days_separator
)
966 SetParseError (ParseError
.Format
);
972 case 3: // Assign the first value to days if we parsed a day separator or the value
973 // is not in the valid range for hours.
974 if (parsed_days_separator
|| value1
> 23) {
984 case 4: // We are either on 'dd.hh:mm:ss' or 'dd:hh:mm:ss'
985 if (!UseColonAsDaySeparator
&& !parsed_days_separator
)
986 SetParseError (ParseError
.Format
);
996 if (hours
> 23 || minutes
> 59 || seconds
> 59)
997 SetParseError (ParseError
.Overflow
);
999 if (!CheckParseSuccess (tryParse
))
1003 if (!TimeSpan
.CalculateTicks (days
, hours
, minutes
, seconds
, 0, false, out t
))
1007 t
= checked ((sign
) ? (-t
- ticks
) : (t
+ ticks
));
1008 } catch (OverflowException
) {
1014 result
= new TimeSpan (t
);
1018 public bool Execute (bool tryParse
, out TimeSpan result
)
1027 result
= TimeSpan
.Zero
;
1030 // Parse [ws][-][dd.]hh:mm:ss[.ff][ws]
1031 // ... but not entirely true as an lonely
1032 // integer will be parsed as a number of days
1034 sign
= ParseSign ();
1035 days
= ParseInt (false);
1036 if (ParseOptDot ()) {
1037 hours
= ParseInt (true);
1044 minutes
= ParseInt (true);
1046 seconds
= ParseInt (true);
1048 if ( ParseOptDot () ) {
1049 ticks
= ParseTicks ();
1057 SetParseError (ParseError
.Format
);
1059 if (!CheckParseSuccess (hours
, minutes
, seconds
, tryParse
))
1063 if (!TimeSpan
.CalculateTicks (days
, hours
, minutes
, seconds
, 0, false, out t
))
1067 t
= checked ((sign
) ? (-t
- ticks
) : (t
+ ticks
));
1068 } catch (OverflowException
) {
1074 result
= new TimeSpan (t
);