in Elfie/Elfie/Model/Strings/String8.cs [1157:1227]
public bool TryToTimeSpan(out TimeSpan result)
{
const string TimeSpanMinValue = "-10675199.02:48:05.4775808";
result = TimeSpan.Zero;
if (this.IsEmpty()) return false;
// If the TimeSpan is negative, parse the rest and negate
bool isNegative = this.StartsWith(UTF8.Dash);
if(isNegative)
{
// Handle TimeSpan.MinValue separately since it will overflow as a positive value
if(this.Length == TimeSpanMinValue.Length && this.Equals(TimeSpanMinValue))
{
result = TimeSpan.MinValue;
return true;
}
bool succeeded = this.Substring(1).TryToTimeSpan(out result);
result = -result;
return succeeded;
}
uint days = 0, hours = 0, minutes = 0, seconds = 0, ticks = 0;
// Find the first colon (hour:minute)
int hourIndex = this.IndexOf(UTF8.Colon) - 2;
// If this is a days-only TimeSpan, try to parse it
if (hourIndex < 0)
{
if (!this.TryToUInt(out days)) return false;
}
else
{
// Use length to infer components which must be present
bool hasDays = (hourIndex > 0);
bool hasSeconds = (Length - hourIndex > 5); // HH:MMx
bool hasPartialSeconds = (Length - hourIndex > 8); // HH:MM:SSx
// Validate separators
if (hasDays && this[hourIndex - 1] != UTF8.Period) return false;
if (hasSeconds && this[hourIndex + 5] != UTF8.Colon) return false;
if (hasPartialSeconds && this[hourIndex + 8] != UTF8.Period) return false;
// Parse Days, Hours, Minutes, Seconds
if (hasDays && !this.Substring(0, hourIndex - 1).TryToUInt(out days)) return false;
if (!this.Substring(hourIndex, 2).TryToUInt(out hours)) return false;
if (!this.Substring(hourIndex + 3, 2).TryToUInt(out minutes)) return false;
if (hasSeconds && !this.Substring(hourIndex + 6, 2).TryToUInt(out seconds)) return false;
// Parse Partial Seconds and normalize to ticks (0.1s -> 100k ticks, ticks are millionths of a second)
if (hasPartialSeconds)
{
String8 partialSeconds = this.Substring(hourIndex + 9);
if (partialSeconds.Length > 7) return false;
if (!partialSeconds.TryToUInt(out ticks)) return false;
if (partialSeconds.Length < 7) ticks *= (uint)Math.Pow(10, 7 - partialSeconds.Length);
}
}
// Validate number ranges
if (days > 10675199) return false;
if (hours > 23) return false;
if (minutes > 59) return false;
if (seconds > 59) return false;
// Construct the TimeSpan
result = new TimeSpan((int)days, (int)hours, (int)minutes, (int)seconds).Add(new TimeSpan(ticks));
return true;
}