public static string ToString(XsdDuration value) { var result = new StringBuilder(); if (value.Negative) { result.Append('-'); } result.Append('P'); int len = result.Length; if (value.Years != 0) { result.Append(value.Years); result.Append('Y'); } if (value.Months != 0) { result.Append(value.Months); result.Append('M'); } if (value.Days != 0) { result.Append(value.Days); result.Append('D'); } if (value.Hours != 0 || value.Minutes != 0 || value.Seconds != 0 || value.Nanoseconds != 0) { result.Append('T'); if (value.Hours != 0) { result.Append(value.Hours); result.Append('H'); } if (value.Minutes != 0) { result.Append(value.Minutes); result.Append('M'); } if (value.Nanoseconds != 0) { result.Append(value.Seconds); result.Append('.'); // nanoseconds are 10^-9s so pad up to 9 digits with leading zeroes // trailing zeroes are superfluous so can be trimmed // 010000000 = .01 // 000000010 = .000000010 // 100000000 = .1 // 120000000 = .12 // 123456789 = .123456789 string ns = value.Nanoseconds.ToString("000000000").TrimEnd(new char[] { '0' }); result.Append(ns); result.Append('S'); } else if (value.Seconds != 0) { result.Append(value.Seconds); result.Append('S'); } } if (result.Length == len) { result.Append("T0S"); } return(result.ToString()); }
static ParseResult TryParseInternal(string value, out XsdDuration result) { result = new XsdDuration(); if (value == null) { return(ParseResult.Empty); } // skip leading white space int pos = 0; for (; pos < value.Length && IsWhite(value[pos]); ++pos) { } // ignore trailing white space int length = value.Length; for (; length > 0 && IsWhite(value[length - 1]); --length) { } // check for an empty string if (pos >= length) { return(ParseResult.Empty); } // handle negative durations if (value[pos] == '-') { result.Negative = true; ++pos; } // P must be present if (pos >= length || value[pos] != 'P') { return(ParseResult.MissingP); } ++pos; // duration might be time only bool seenTime = false; if (pos < length && value[pos] == 'T') { seenTime = true; ++pos; } int?num = null; Func <ParseResult> getNumber = () => ParseNumber(value, ref pos, out num); // get the first component ParseResult parseResult = getNumber(); if (parseResult != ParseResult.Ok) { return(parseResult); } Func <ParseResult> nextComponent = () => { ++pos; if (pos < length) { if (value[pos] == 'T') { if (seenTime) { return(ParseResult.DuplicateTimeSeparator); } seenTime = true; ++pos; } return(getNumber()); } else { num = null; } return(ParseResult.Ok); }; if (!seenTime) { if (pos < length && value[pos] == 'Y') { result.Years = num.Value; if ((parseResult = nextComponent()) != ParseResult.Ok) { return(parseResult); } } if (!seenTime && (pos < length && value[pos] == 'M')) { result.Months = num.Value; if ((parseResult = nextComponent()) != ParseResult.Ok) { return(parseResult); } } if (!seenTime && (pos < length && value[pos] == 'D')) { result.Days = num.Value; if ((parseResult = nextComponent()) != ParseResult.Ok) { return(parseResult); } } if (!seenTime && num.HasValue) { return(ParseResult.MissingComponent); } } if (seenTime) { if (pos < length && value[pos] == 'H') { result.Hours = num.Value; if ((parseResult = nextComponent()) != ParseResult.Ok) { return(parseResult); } } if (pos < length && value[pos] == 'M') { result.Minutes = num.Value; if ((parseResult = nextComponent()) != ParseResult.Ok) { return(parseResult); } } if (pos < length && value[pos] == '.') { result.Seconds = num.Value; ++pos; int fraction = 0; int numDigits = 0; while (pos < length && IsDigit(value[pos])) { num = value[pos++] - '0'; if (fraction <= (Int32.MaxValue - num.Value) / 10) { fraction = fraction * 10 + num.Value; ++numDigits; } } if (numDigits == 0) { return(ParseResult.MissingNumber); } // if we've got more than 9 digits then truncate to nanosecond precision for (; numDigits > 9; --numDigits) { fraction /= 10; } // less than 9 digits means 10^(9-digits) nanoseconds, // .1 is 10^8 ns, .01 is 10^7ns, etc for (; numDigits < 9; ++numDigits) { fraction *= 10; } result.Nanoseconds = fraction; // we have to have 'S' after a decimal number if (pos >= length || value[pos] != 'S') { return(ParseResult.MissingComponent); } ++pos; num = null; } else if (pos < length && value[pos] == 'S') { result.Seconds = num.Value; ++pos; num = null; } if (num.HasValue) { return(ParseResult.MissingComponent); } } if (pos != length) { return(ParseResult.TrailingText); } return(ParseResult.Ok); }
public static bool TryParse(string value, out XsdDuration result) { return(TryParseInternal(value, out result) == ParseResult.Ok); }