示例#1
0
 public void MatchCaseInsensitive_MatchAndMove()
 {
     var value = new ValueCursor("abcd");
     Assert.True(value.MoveNext(), "GetNext() 1");
     Assert.True(value.MatchCaseInsensitive("AbC", CultureInfo.InvariantCulture.CompareInfo, true));
     ValidateCurrentCharacter(value, 3, 'd');
 }
示例#2
0
 public void MatchCaseInsensitive_StringNotMatched()
 {
     var value = new ValueCursor("xabcdef");
     Assert.True(value.MoveNext(), "GetNext() 1");
     Assert.False(value.MatchCaseInsensitive("abc", CultureInfo.InvariantCulture.CompareInfo, true));
     ValidateCurrentCharacter(value, 0, 'x');
 }
示例#3
0
 public void TestMatchCaseInsensitive_string()
 {
     var value = new ValueCursor("abc");
     Assert.True(value.MoveNext(), "GetNext() 1");
     Assert.True(value.MatchCaseInsensitive("AbC", CultureInfo.InvariantCulture.CompareInfo));
     Assert.False(value.MoveNext(), "GetNext() end");
 }
示例#4
0
 public void Match_String()
 {
     var value = new ValueCursor("abc");
     Assert.True(value.MoveNext(), "GetNext() 1");
     Assert.True(value.Match("abc"));
     Assert.False(value.MoveNext(), "GetNext() end");
 }
示例#5
0
 public void Match_StringNotMatched()
 {
     var value = new ValueCursor("xabcdef");
     Assert.True(value.MoveNext(), "GetNext() 1");
     Assert.False(value.Match("abc"));
     ValidateCurrentCharacter(value, 0, 'x');
 }
示例#6
0
 public void Match_StringOverLongStringToMatch()
 {
     var value = new ValueCursor("x");
     Assert.True(value.MoveNext());
     Assert.False(value.Match("long string"));
     ValidateCurrentCharacter(value, 0, 'x');
 }
 public void Parse_Partial_Invalid()
 {
     var value = new ValueCursor("x17:y");
     value.MoveNext();
     value.MoveNext();
     var result = SimpleOffsetPattern.ParsePartial(value);
     Assert.Throws<UnparsableValueException>(() => result.GetValueOrThrow());
 }
示例#8
0
 public void MatchCaseInsensitive_MatchWithoutMoving()
 {
     var value = new ValueCursor("abcd");
     Assert.True(value.MoveNext(), "GetNext() 1");
     Assert.True(value.MatchCaseInsensitive("AbC", CultureInfo.InvariantCulture.CompareInfo, false));
     // We're still looking at the start
     ValidateCurrentCharacter(value, 0, 'a');
 }
示例#9
0
 public void Match_Char()
 {
     var value = new ValueCursor("abc");
     Assert.True(value.MoveNext(), "GetNext() 1");
     Assert.True(value.Match('a'), "First character");
     Assert.True(value.Match('b'), "Second character");
     Assert.True(value.Match('c'), "Third character");
     Assert.False(value.MoveNext(), "GetNext() end");
 }
 public void ParsePartial_ValidAtEnd()
 {
     var value = new ValueCursor("x17:30");
     value.MoveNext();
     value.MoveNext();
     var result = SimpleOffsetPattern.ParsePartial(value);
     Assert.AreEqual(Offset.FromHoursAndMinutes(17, 30), result.Value);
     // Finish just after the value, which in this case is at the end.
     Assert.AreEqual(TextCursor.Nul, value.Current);
 }
            internal ParseResult <ZonedDateTime> ParseZone(ValueCursor value)
            {
                DateTimeZone zone = TryParseFixedZone(value) ?? TryParseProviderZone(value);

                if (zone == null)
                {
                    return(ParseResult <ZonedDateTime> .NoMatchingZoneId(value));
                }
                Zone = zone;
                return(null);
            }
示例#12
0
 internal static ParseResult <T> ForInvalidValue(ValueCursor cursor, string formatString, params object[] parameters)
 {
     return(ForInvalidValue(() =>
     {
         // Format the message which is specific to the kind of parse error.
         string detailMessage = string.Format(CultureInfo.CurrentCulture, formatString, parameters);
         // Format the overall message, containing the parse error and the value itself.
         string overallMessage = string.Format(CultureInfo.CurrentCulture, Messages.Parse_UnparsableValue, detailMessage, cursor);
         return new UnparsableValueException(overallMessage);
     }));
 }
            /// <summary>
            /// Attempts to parse a fixed time zone from "UTC" with an optional
            /// offset, expressed as +HH, +HH:mm, +HH:mm:ss or +HH:mm:ss.fff - i.e. the
            /// general format. If it manages, it will move the cursor and return the
            /// zone. Otherwise, it will return null and the cursor will remain where
            /// it was.
            /// </summary>
            private DateTimeZone TryParseFixedZone(ValueCursor value)
            {
                if (value.CompareOrdinal(DateTimeZone.UtcId) != 0)
                {
                    return(null);
                }
                value.Move(value.Index + 3);
                var pattern     = OffsetPattern.GeneralInvariant.UnderlyingPattern;
                var parseResult = pattern.ParsePartial(value);

                return(parseResult.Success ? DateTimeZone.ForOffset(parseResult.Value) : DateTimeZone.Utc);
            }
 public void ParsePartial_ValidInMiddle()
 {
     var value = new ValueCursor("x17:30y");
     value.MoveNext();
     value.MoveNext();
     // Start already looking at the value to parse
     Assert.AreEqual('1', value.Current);
     var result = SimpleOffsetPattern.ParsePartial(value);
     Assert.AreEqual(Offset.FromHoursAndMinutes(17, 30), result.Value);
     // Finish just after the value
     Assert.AreEqual('y', value.Current);
 }
示例#15
0
            public ParseResult <T> ParsePartial(ValueCursor cursor)
            {
                int index = cursor.Index;

                foreach (IPartialPattern <T> pattern in patterns)
                {
                    cursor.Move(index);
                    ParseResult <T> result = pattern.ParsePartial(cursor);
                    if (result.Success || !result.ContinueAfterErrorWithMultipleFormats)
                    {
                        return(result);
                    }
                }
                cursor.Move(index);
                return(ParseResult <T> .NoMatchingFormat(cursor));
            }
            /// <summary>
            /// Tries to parse a time zone ID from the provider. Returns the zone
            /// on success (after moving the cursor to the end of the ID) or null on failure
            /// (leaving the cursor where it was).
            /// </summary>
            private DateTimeZone TryParseProviderZone(ValueCursor value)
            {
                // The IDs from the provider are guaranteed to be in order (using ordinal comparisons).
                // Use a binary search to find a match, then make sure it's the longest possible match.
                var ids        = zoneProvider.Ids;
                int lowerBound = 0;         // Inclusive
                int upperBound = ids.Count; // Exclusive

                while (lowerBound < upperBound)
                {
                    int guess  = (lowerBound + upperBound) / 2;
                    int result = value.CompareOrdinal(ids[guess]);
                    if (result < 0)
                    {
                        // Guess is later than our text: lower the upper bound
                        upperBound = guess;
                    }
                    else if (result > 0)
                    {
                        // Guess is earlier than our text: raise the lower bound
                        lowerBound = guess + 1;
                    }
                    else
                    {
                        // We've found a match! But it may not be as long as it
                        // could be. Keep looking until we find a value which isn't a match...
                        while (guess + 1 < upperBound && value.CompareOrdinal(ids[guess + 1]) == 0)
                        {
                            guess++;
                        }
                        string id = ids[guess];
                        value.Move(value.Index + id.Length);
                        return(zoneProvider[id]);
                    }
                }
                return(null);
            }
示例#17
0
            public ParseResult <Offset> ParsePartial(ValueCursor cursor)
            {
                // TODO: Do better than this. It's horrible, and may well be invalid
                // for some cultures. Or just remove the NumberPattern from 2.0...
                int longestPossible = Math.Min(maxLength, cursor.Length - cursor.Index);

                for (int length = longestPossible; length >= 0; length--)
                {
                    string candidate = cursor.Value.Substring(cursor.Index, length);
                    int    milliseconds;
                    if (Int32.TryParse(candidate, NumberStyles.Integer | NumberStyles.AllowThousands,
                                       formatInfo.NumberFormat, out milliseconds))
                    {
                        if (milliseconds < -NodaConstants.MillisecondsPerStandardDay ||
                            NodaConstants.MillisecondsPerStandardDay < milliseconds)
                        {
                            return(ParseResult <Offset> .ValueOutOfRange(milliseconds));
                        }
                        cursor.Move(cursor.Index + length);
                        return(ParseResult <Offset> .ForValue(Offset.FromMilliseconds(milliseconds)));
                    }
                }
                return(ParseResult <Offset> .CannotParseValue(cursor.Value, "n"));
            }
示例#18
0
 public void ParseInt64_Simple()
 {
     var value = new ValueCursor("56x");
     Assert.True(value.MoveNext());
     long result;
     Assert.IsNull(value.ParseInt64<string>(out result));
     Assert.AreEqual(56L, result);
     // Cursor ends up post-number
     Assert.AreEqual(2, value.Index);
 }
示例#19
0
 internal static ParseResult <T> EscapedCharacterMismatch(ValueCursor cursor, char patternCharacter) => ForInvalidValue(cursor, Messages.Parse_EscapedCharacterMismatch, patternCharacter);
示例#20
0
 public void ParseInt64Digits_Minimum()
 {
     var value = new ValueCursor("1");
     value.MoveNext();
     long actual;
     Assert.True(value.ParseInt64Digits(1, 2, out actual));
     Assert.AreEqual(1, actual);
     ValidateEndOfString(value);
 }
示例#21
0
 public void ParseInt64Digits_LargeNumber()
 {
     var value = new ValueCursor("9999999999999");
     Assert.True(value.MoveNext());
     long actual;
     Assert.True(value.ParseInt64Digits(1, 13, out actual));
     Assert.AreEqual(actual, 9999999999999L);
     Assert.Greater(9999999999999L, int.MaxValue);
 }
示例#22
0
 internal static ParseResult <T> FieldValueOutOfRange(ValueCursor cursor, long value, char field) =>
 ForInvalidValue(cursor, Messages.Parse_FieldValueOutOfRange, value, field, typeof(T));
示例#23
0
 public void ParseInt64Digits_Maximum()
 {
     var value = new ValueCursor("12");
     Assert.True(value.MoveNext());
     long actual;
     Assert.True(value.ParseInt64Digits(1, 2, out actual));
     Assert.AreEqual(12, actual);
 }
示例#24
0
 internal static ParseResult <T> MissingSign(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_MissingSign);
示例#25
0
 public void CompareOrdinal_LongMatch_ValueIsEarlier()
 {
     var value = new ValueCursor("xabc");
     value.Move(1);
     Assert.Less(value.CompareOrdinal("cccc"), 0);
     Assert.AreEqual(1, value.Index); // Cursor hasn't moved
 }
示例#26
0
 internal static ParseResult <T> NoMatchingCalendarSystem(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_NoMatchingCalendarSystem);
示例#27
0
 internal static ParseResult <T> MissingAmPmDesignator(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_MissingAmPmDesignator);
示例#28
0
            internal ParseResult <TResult> ParseEra <TResult>(NodaFormatInfo formatInfo, ValueCursor cursor)
            {
                var compareInfo = formatInfo.CompareInfo;

                foreach (var era in Calendar.Eras)
                {
                    foreach (string eraName in formatInfo.GetEraNames(era))
                    {
                        if (cursor.MatchCaseInsensitive(eraName, compareInfo, true))
                        {
                            Era = era;
                            return(null);
                        }
                    }
                }
                return(ParseResult <TResult> .MismatchedText(cursor, 'g'));
            }
示例#29
0
            /// <summary>
            /// Tries to parse a time zone ID from the provider. Returns the zone
            /// on success (after moving the cursor to the end of the ID) or null on failure
            /// (leaving the cursor where it was).
            /// </summary>
            private DateTimeZone TryParseProviderZone(ValueCursor value)
            {
                // The IDs from the provider are guaranteed to be in order (using ordinal comparisons).
                // Use a binary search to find a match, then make sure it's the longest possible match.
                var ids        = zoneProvider.Ids;
                int lowerBound = 0;         // Inclusive
                int upperBound = ids.Count; // Exclusive

                while (lowerBound < upperBound)
                {
                    int guess  = (lowerBound + upperBound) / 2;
                    int result = value.CompareOrdinal(ids[guess]);
                    if (result < 0)
                    {
                        // Guess is later than our text: lower the upper bound
                        upperBound = guess;
                    }
                    else if (result > 0)
                    {
                        // Guess is earlier than our text: raise the lower bound
                        lowerBound = guess + 1;
                    }
                    else
                    {
                        // We've found a match! But it may not be as long as it
                        // could be. Keep track of a "longest match so far" (starting with the match we've found),
                        // and keep looking through the IDs until we find an ID which doesn't start with that "longest
                        // match so far", at which point we know we're done.
                        //
                        // We can't just look through all the IDs from "guess" to "lowerBound" and stop when we hit
                        // a non-match against "value", because of situations like this:
                        // value=Etc/GMT-12
                        // guess=Etc/GMT-1
                        // IDs includes { Etc/GMT-1, Etc/GMT-10, Etc/GMT-11, Etc/GMT-12, Etc/GMT-13 }
                        // We can't stop when we hit Etc/GMT-10, because otherwise we won't find Etc/GMT-12.
                        // We *can* stop when we get to Etc/GMT-13, because by then our longest match so far will
                        // be Etc/GMT-12, and we know that anything beyond Etc/GMT-13 won't match that.
                        // We can also stop when we hit upperBound, without any more comparisons.

                        string longestSoFar = ids[guess];
                        for (int i = guess + 1; i < upperBound; i++)
                        {
                            string candidate = ids[i];
                            if (candidate.Length < longestSoFar.Length)
                            {
                                break;
                            }
                            if (string.CompareOrdinal(longestSoFar, 0, candidate, 0, longestSoFar.Length) != 0)
                            {
                                break;
                            }
                            if (value.CompareOrdinal(candidate) == 0)
                            {
                                longestSoFar = candidate;
                            }
                        }
                        value.Move(value.Index + longestSoFar.Length);
                        return(zoneProvider[longestSoFar]);
                    }
                }
                return(null);
            }
示例#30
0
 /// <summary>
 /// We'd expected to get to the end of the string now, but we haven't.
 /// </summary>
 internal static ParseResult <T> ExpectedEndOfString(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_ExpectedEndOfString);
示例#31
0
 public void ParseInt64_NumberOutOfRange_MinValueLeadingDigits()
 {
     var value = new ValueCursor("-9223372036854775809");
     Assert.True(value.MoveNext());
     long result;
     Assert.IsNotNull(value.ParseInt64<string>(out result));
     // Cursor has not moved
     Assert.AreEqual(0, value.Index);
 }
 private static ParseResult <ZonedDateTime> ParseZone(ValueCursor value, ZonedDateTimeParseBucket bucket) => bucket.ParseZone(value);
示例#33
0
 internal static ParseResult <T> QuotedStringMismatch(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_QuotedStringMismatch);
示例#34
0
 internal static ParseResult <T> ValueOutOfRange(ValueCursor cursor, object value) => ForInvalidValue(cursor, Messages.Parse_ValueOutOfRange, value, typeof(T));
示例#35
0
 internal static ParseResult <T> ExtraValueCharacters(ValueCursor cursor, string remainder) => ForInvalidValue(cursor, Messages.Parse_ExtraValueCharacters, remainder);
示例#36
0
 internal static ParseResult <T> MismatchedText(ValueCursor cursor, char field) => ForInvalidValue(cursor, Messages.Parse_MismatchedText, field);
示例#37
0
 public void ParseInt64Digits_NoNumber()
 {
     var value = new ValueCursor("abc");
     Assert.True(value.MoveNext());
     long actual;
     Assert.False(value.ParseInt64Digits(1, 2, out actual));
     ValidateCurrentCharacter(value, 0, 'a');
 }
示例#38
0
 internal static ParseResult <T> MismatchedCharacter(ValueCursor cursor, char patternCharacter) => ForInvalidValue(cursor, Messages.Parse_MismatchedCharacter, patternCharacter);
示例#39
0
 public void ParseInt64Digits_MaximumMoreDigits()
 {
     var value = new ValueCursor("1234");
     Assert.True(value.MoveNext());
     long actual;
     Assert.True(value.ParseInt64Digits(1, 2, out actual));
     Assert.AreEqual(12, actual);
     ValidateCurrentCharacter(value, 2, '3');
 }
示例#40
0
 internal static ParseResult <T> MismatchedNumber(ValueCursor cursor, string pattern) => ForInvalidValue(cursor, Messages.Parse_MismatchedNumber, pattern);
示例#41
0
 public void ParseInt64Digits_MinimumNonDigits()
 {
     var value = new ValueCursor("1abc");
     Assert.True(value.MoveNext());
     long actual;
     Assert.True(value.ParseInt64Digits(1, 2, out actual));
     Assert.AreEqual(1, actual);
     ValidateCurrentCharacter(value, 1, 'a');
 }
示例#42
0
 internal static ParseResult <T> UnexpectedNegative(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_UnexpectedNegative);
示例#43
0
 public void ParseFraction_NonAscii_NeverMatches()
 {
     // Arabic-Indic digits 0 and 1. See
     // http://www.unicode.org/charts/PDF/U0600.pdf
     var value = new ValueCursor("\u0660\u0661");
     Assert.True(value.MoveNext());
     int actual;
     Assert.False(value.ParseFraction(2, 2, out actual, 2));
 }
示例#44
0
            public ParseResult <Period> Parse(string text)
            {
                if (text is null)
                {
                    return(ParseResult <Period> .ArgumentNull("text"));
                }
                if (text.Length == 0)
                {
                    return(ParseResult <Period> .ValueStringEmpty);
                }

                ValueCursor valueCursor = new ValueCursor(text);

                valueCursor.MoveNext();
                if (valueCursor.Current != 'P')
                {
                    return(ParseResult <Period> .MismatchedCharacter(valueCursor, 'P'));
                }
                bool          inDate     = true;
                PeriodBuilder builder    = new PeriodBuilder();
                PeriodUnits   unitsSoFar = 0;

                while (valueCursor.MoveNext())
                {
                    if (inDate && valueCursor.Current == 'T')
                    {
                        inDate = false;
                        continue;
                    }
                    var failure = valueCursor.ParseInt64 <Period>(out long unitValue);
                    if (failure != null)
                    {
                        return(failure);
                    }
                    if (valueCursor.Length == valueCursor.Index)
                    {
                        return(ParseResult <Period> .EndOfString(valueCursor));
                    }
                    // Various failure cases:
                    // - Repeated unit (e.g. P1M2M)
                    // - Time unit is in date part (e.g. P5M)
                    // - Date unit is in time part (e.g. PT1D)
                    // - Unit is in incorrect order (e.g. P5D1Y)
                    // - Unit is invalid (e.g. P5J)
                    // - Unit is missing (e.g. P5)
                    PeriodUnits unit;
                    switch (valueCursor.Current)
                    {
                    case 'Y': unit = PeriodUnits.Years; break;

                    case 'M': unit = inDate ? PeriodUnits.Months : PeriodUnits.Minutes; break;

                    case 'W': unit = PeriodUnits.Weeks; break;

                    case 'D': unit = PeriodUnits.Days; break;

                    case 'H': unit = PeriodUnits.Hours; break;

                    case 'S': unit = PeriodUnits.Seconds; break;

                    case 's': unit = PeriodUnits.Milliseconds; break;

                    case 't': unit = PeriodUnits.Ticks; break;

                    case 'n': unit = PeriodUnits.Nanoseconds; break;

                    default: return(InvalidUnit(valueCursor, valueCursor.Current));
                    }
                    if ((unit & unitsSoFar) != 0)
                    {
                        return(RepeatedUnit(valueCursor, valueCursor.Current));
                    }

                    // This handles putting months before years, for example. Less significant units
                    // have higher integer representations.
                    if (unit < unitsSoFar)
                    {
                        return(MisplacedUnit(valueCursor, valueCursor.Current));
                    }
                    // The result of checking "there aren't any time units in this unit" should be
                    // equal to "we're still in the date part".
                    if ((unit & PeriodUnits.AllTimeUnits) == 0 != inDate)
                    {
                        return(MisplacedUnit(valueCursor, valueCursor.Current));
                    }
                    builder[unit] = unitValue;
                    unitsSoFar   |= unit;
                }
                return(ParseResult <Period> .ForValue(builder.Build()));
            }
示例#45
0
 public void ParseInt64_Negative()
 {
     var value = new ValueCursor("-56x");
     Assert.True(value.MoveNext());
     long result;
     Assert.IsNull(value.ParseInt64<string>(out result));
     Assert.AreEqual(-56L, result);
 }
示例#46
0
            // TODO(misc): Tidy this up a *lot*.
            public ParseResult <Period> Parse(string text)
            {
                if (text is null)
                {
                    return(ParseResult <Period> .ArgumentNull("text"));
                }
                if (text.Length == 0)
                {
                    return(ParseResult <Period> .ValueStringEmpty);
                }

                ValueCursor valueCursor = new ValueCursor(text);

                valueCursor.MoveNext();
                if (valueCursor.Current != 'P')
                {
                    return(ParseResult <Period> .MismatchedCharacter(valueCursor, 'P'));
                }
                bool          inDate     = true;
                PeriodBuilder builder    = new PeriodBuilder();
                PeriodUnits   unitsSoFar = 0;

                while (valueCursor.MoveNext())
                {
                    if (inDate && valueCursor.Current == 'T')
                    {
                        inDate = false;
                        continue;
                    }
                    bool negative = valueCursor.Current == '-';
                    var  failure  = valueCursor.ParseInt64 <Period>(out long unitValue);
                    if (failure != null)
                    {
                        return(failure);
                    }
                    if (valueCursor.Length == valueCursor.Index)
                    {
                        return(ParseResult <Period> .EndOfString(valueCursor));
                    }
                    // Various failure cases:
                    // - Repeated unit (e.g. P1M2M)
                    // - Time unit is in date part (e.g. P5M)
                    // - Date unit is in time part (e.g. PT1D)
                    // - Unit is in incorrect order (e.g. P5D1Y)
                    // - Unit is invalid (e.g. P5J)
                    // - Unit is missing (e.g. P5)
                    PeriodUnits unit;
                    switch (valueCursor.Current)
                    {
                    case 'Y': unit = PeriodUnits.Years; break;

                    case 'M': unit = inDate ? PeriodUnits.Months : PeriodUnits.Minutes; break;

                    case 'W': unit = PeriodUnits.Weeks; break;

                    case 'D': unit = PeriodUnits.Days; break;

                    case 'H': unit = PeriodUnits.Hours; break;

                    case 'S': unit = PeriodUnits.Seconds; break;

                    case ',':
                    case '.': unit = PeriodUnits.Nanoseconds; break;     // Special handling below

                    default: return(InvalidUnit(valueCursor, valueCursor.Current));
                    }
                    if ((unit & unitsSoFar) != 0)
                    {
                        return(RepeatedUnit(valueCursor, valueCursor.Current));
                    }

                    // This handles putting months before years, for example. Less significant units
                    // have higher integer representations.
                    if (unit < unitsSoFar)
                    {
                        return(MisplacedUnit(valueCursor, valueCursor.Current));
                    }

                    // The result of checking "there aren't any time units in this unit" should be
                    // equal to "we're still in the date part".
                    if ((unit & PeriodUnits.AllTimeUnits) == 0 != inDate)
                    {
                        return(MisplacedUnit(valueCursor, valueCursor.Current));
                    }

                    // Seen a . or , which need special handling.
                    if (unit == PeriodUnits.Nanoseconds)
                    {
                        // Check for already having seen seconds, e.g. PT5S0.5
                        if ((unitsSoFar & PeriodUnits.Seconds) != 0)
                        {
                            return(MisplacedUnit(valueCursor, valueCursor.Current));
                        }
                        builder.Seconds = unitValue;

                        if (!valueCursor.MoveNext())
                        {
                            return(ParseResult <Period> .MissingNumber(valueCursor));
                        }
                        // Can cope with at most 999999999 nanoseconds
                        if (!valueCursor.ParseFraction(9, 9, out int totalNanoseconds, 1))
                        {
                            return(ParseResult <Period> .MissingNumber(valueCursor));
                        }
                        // Use whether or not the seconds value was negative (even if 0)
                        // as the indication of whether this value is negative.
                        if (negative)
                        {
                            totalNanoseconds = -totalNanoseconds;
                        }
                        builder.Milliseconds = (totalNanoseconds / NanosecondsPerMillisecond) % MillisecondsPerSecond;
                        builder.Ticks        = (totalNanoseconds / NanosecondsPerTick) % TicksPerMillisecond;
                        builder.Nanoseconds  = totalNanoseconds % NanosecondsPerTick;

                        if (valueCursor.Current != 'S')
                        {
                            return(ParseResult <Period> .MismatchedCharacter(valueCursor, 'S'));
                        }
                        if (valueCursor.MoveNext())
                        {
                            return(ParseResult <Period> .ExpectedEndOfString(valueCursor));
                        }
                        return(ParseResult <Period> .ForValue(builder.Build()));
                    }

                    builder[unit] = unitValue;
                    unitsSoFar   |= unit;
                }
                if (unitsSoFar == 0)
                {
                    return(ParseResult <Period> .ForInvalidValue(valueCursor, TextErrorMessages.EmptyPeriod));
                }
                return(ParseResult <Period> .ForValue(builder.Build()));
            }
示例#47
0
 public void ParseInt64_NegativeThenNonDigit()
 {
     var value = new ValueCursor("-x");
     Assert.True(value.MoveNext());
     long result;
     Assert.IsNotNull(value.ParseInt64<string>(out result));
     // Cursor has not moved
     Assert.AreEqual(0, value.Index);
 }
示例#48
0
 private static ParseResult <Period> RepeatedUnit(ValueCursor cursor, char unitCharacter) => ParseResult <Period> .ForInvalidValue(cursor, TextErrorMessages.RepeatedUnitSpecifier, unitCharacter);
示例#49
0
 public void ParseInt64_MinValue()
 {
     var value = new ValueCursor("-9223372036854775808");
     Assert.True(value.MoveNext());
     long result;
     Assert.IsNull(value.ParseInt64<string>(out result));
     Assert.AreEqual(long.MinValue, result);
 }
            internal ParseResult <TResult> ParseEra <TResult>(NodaFormatInfo formatInfo, ValueCursor cursor)
            {
                var compareInfo = formatInfo.CompareInfo;
                var eras        = Calendar.Eras;

                for (int i = 0; i < eras.Count; i++)
                {
                    foreach (string eraName in formatInfo.GetEraNames(eras[i]))
                    {
                        if (cursor.MatchCaseInsensitive(eraName, compareInfo, true))
                        {
                            EraIndex = i;
                            return(null);
                        }
                    }
                }
                return(ParseResult <TResult> .MismatchedText('g'));
            }
示例#51
0
 public void CompareOrdinal_ExactMatchValueContinues()
 {
     var value = new ValueCursor("xabc");
     value.Move(1);
     Assert.AreEqual(0, value.CompareOrdinal("ab"));
     Assert.AreEqual(1, value.Index); // Cursor hasn't moved
 }
示例#52
0
 public void ParseInt64Digits_TooFewDigits()
 {
     var value = new ValueCursor("a12b");
     Assert.True(value.MoveNext());
     ValidateCurrentCharacter(value, 0, 'a');
     Assert.True(value.MoveNext());
     long actual;
     Assert.False(value.ParseInt64Digits(3, 3, out actual));
     ValidateCurrentCharacter(value, 1, '1');
 }
示例#53
0
 public void CompareOrdinal_LongMatch_ValueIsLater()
 {
     var value = new ValueCursor("xabc");
     value.Move(1);
     Assert.Greater(value.CompareOrdinal("aaaa"), 0);
     Assert.AreEqual(1, value.Index); // Cursor hasn't moved
 }
示例#54
0
 internal static ParseResult <T> DateSeparatorMismatch(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_DateSeparatorMismatch);
示例#55
0
 public void MatchCaseInsensitive_StringOverLongStringToMatch()
 {
     var value = new ValueCursor("x");
     Assert.True(value.MoveNext());
     Assert.False(value.MatchCaseInsensitive("long string", CultureInfo.InvariantCulture.CompareInfo, true));
     ValidateCurrentCharacter(value, 0, 'x');
 }
示例#56
0
 internal static ParseResult <T> NoMatchingZoneId(ValueCursor cursor) => ForInvalidValue(cursor, Messages.Parse_NoMatchingZoneId);
示例#57
0
 private static ParseResult <Period> InvalidUnit(ValueCursor cursor, char unitCharacter) => ParseResult <Period> .ForInvalidValue(cursor, Messages.Parse_InvalidUnitSpecifier, unitCharacter);
示例#58
0
 private static ParseResult <Period> MisplacedUnit(ValueCursor cursor, char unitCharacter)
 {
     return(ParseResult <Period> .ForInvalidValue(cursor, Messages.Parse_MisplacedUnitSpecifier, unitCharacter));
 }
示例#59
0
 public void Match_StringPartial()
 {
     var value = new ValueCursor("abcdef");
     Assert.True(value.MoveNext(), "GetNext() 1");
     Assert.True(value.Match("abc"));
     ValidateCurrentCharacter(value, 3, 'd');
 }
示例#60
0
 public void TestParseDigit_nonASCII_NeverMatches()
 {
     // Arabic-Indic digits 0 and 1. See
     // http://www.unicode.org/charts/PDF/U0600.pdf
     var value = new ValueCursor("\u0660\u0661");
     Assert.True(value.MoveNext());
     int actual;
     Assert.False(value.ParseDigits(1, 2, out actual));
 }