コード例 #1
0
        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());
        }
コード例 #2
0
        private 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);
        }
コード例 #3
0
 public static bool TryParse(string value, out XsdDuration result)
 {
     return(TryParseInternal(value, out result) == ParseResult.Ok);
 }