public void ReadImpliedRelativeTimeSpan(ref DateTime baseTime, NumberToken num, TimeUnitToken units) { var number = num.Value; if (_tokeniser.ContainsToken <RelativeToken>(c => c.RelativeType == RelativeType.Ago)) { number *= -1; } try { baseTime = units.Unit switch { TimeUnit.Day => baseTime.AddDays(number), TimeUnit.Month => baseTime.AddMonths(number), TimeUnit.Week => baseTime.AddDays(7 * number), TimeUnit.Year => baseTime.AddYears(number), TimeUnit.Minute => baseTime.AddMinutes(number), TimeUnit.Second => baseTime.AddSeconds(number), TimeUnit.Hour => baseTime.AddHours(number), TimeUnit.Millisecond => baseTime.AddMilliseconds(number), _ => throw new ParseException(ParseFailReason.InvalidUnit, $"Invalid unit following '{num.Value}'.") }; } catch (ArgumentOutOfRangeException) { throw new ParseException(ParseFailReason.InvalidUnit, "Cannot add that much time to the current date."); } }
public void ReadRelativeDayTime(ref DateTime date, NumberToken firstNumberToken, TriviaToken specifierToken) { var hours = firstNumberToken.Value; var minutes = 0; var seconds = 0; switch (specifierToken.TriviaType) { case TriviaType.Am: if (hours == 12) { hours = 0; // 12 AM == 0000 hours } break; case TriviaType.Pm: if (hours != 12) { hours += 12; // 12 PM = 1200 hours } break; case TriviaType.Colon: if (!_tokeniser.MoveNext()) { throw new ParseException(ParseFailReason.NumberExpected, $"Expected a minute specifier to follow after a colon."); } if (!(_tokeniser.Current is NumberToken num)) { throw new ParseException(ParseFailReason.InvalidUnit, $"Expected a number to follow the colon."); } minutes = num.Value; if (_tokeniser.PeekNext() != null && _tokeniser.PeekNext() is TriviaToken t && t.TriviaType == TriviaType.Colon) { _tokeniser.MoveNext(); if (!_tokeniser.MoveNext()) { throw new ParseException(ParseFailReason.NumberExpected, $"Expected a second specifier to follow the colon."); } if (!(_tokeniser.Current is NumberToken msNum)) { throw new ParseException(ParseFailReason.InvalidUnit, "Expected a number to follow the colon."); } seconds = msNum.Value; } if (!_tokeniser.MoveNext() || !(_tokeniser.Current is TriviaToken t0)) { throw new ParseException(ParseFailReason.UnitExpected, "Expected an AM or PM specifier."); } switch (t0.TriviaType) { case TriviaType.Am: if (hours == 12) { hours = 0; // 12 AM == 0000 hours } break; case TriviaType.Pm: if (hours != 12) { hours += 12; // 12 PM = 1200 hours } break; default: throw new ParseException(ParseFailReason.InvalidUnit, $"Invalid unit '{t0.TriviaType.ToString()}', expected AM or PM."); } break; default: throw new ParseException(ParseFailReason.InvalidUnit, $"Invalid unit '{specifierToken.TriviaType.ToString()}', expected AM or PM."); } if (hours >= 24 || minutes >= 60 || seconds >= 60) { throw new ParseException(ParseFailReason.InvalidUnit, $"Not a valid time."); } date = new DateTime(date.Year, date.Month, date.Day, hours, minutes, seconds); }