internal Exception TryToTimeSpan(DurationType durationType, out TimeSpan result) {
Exception exception = null;
ulong ticks = 0;
// Throw error if result cannot fit into a long
try {
checked {
// Discard year and month parts if constructing TimeSpan for DayTimeDuration
if (durationType != DurationType.DayTimeDuration) {
ticks += ((ulong) this.years + (ulong) this.months / 12) * 365;
ticks += ((ulong) this.months % 12) * 30;
}
// Discard day and time parts if constructing TimeSpan for YearMonthDuration
if (durationType != DurationType.YearMonthDuration) {
ticks += (ulong) this.days;
ticks *= 24;
ticks += (ulong) this.hours;
ticks *= 60;
ticks += (ulong) this.minutes;
ticks *= 60;
ticks += (ulong) this.seconds;
// Tick count interval is in 100 nanosecond intervals (7 digits)
ticks *= (ulong) TimeSpan.TicksPerSecond;
ticks += (ulong) Nanoseconds / 100;
}
else {
// Multiply YearMonth duration by number of ticks per day
ticks *= (ulong) TimeSpan.TicksPerDay;
}
if (IsNegative) {
// Handle special case of Int64.MaxValue + 1 before negation, since it would otherwise overflow
if (ticks == (ulong) Int64.MaxValue + 1) {
result = new TimeSpan(Int64.MinValue);
}
else {
result = new TimeSpan(-((long) ticks));
}
}
else {
result = new TimeSpan((long) ticks);
}
return null;
}
}
catch (OverflowException) {
result = TimeSpan.MinValue;
exception = new OverflowException(Res.GetString(Res.XmlConvert_Overflow, durationType, "TimeSpan"));
}
return exception;
}