This class parses human-readable time specifications in the format described in detail on the rrdfetch man page. It is primarily a Java port of Tobi Oetiker's parsetime.c code, adapted for Java conventions.
Supported time specification formats include:
- Absolute times: "Jan 1 2023", "12:30", "2023/01/01 12:30:45"
- Relative times: "now-2hours", "tomorrow", "noon yesterday"
- Natural language: "midnight", "teatime", "start of week"
- Time ranges: "start+1week", "end-2days"
Special parsing rules:
- Two-digit years before 38 are interpreted as post-2000
- Ambiguous "m" token resolved based on context (months vs minutes)
- Supports both 12-hour (AM/PM) and 24-hour time formats
- Multiple date separators accepted: "/", ".", "-"
The parser uses a two-phase approach:
1. Lexical scanning (TimeScanner) breaks input into tokens
2. Grammar parsing interprets tokens according to at-style syntax rules
Example usage:
TimeParser parser = new TimeParser("now-1day+2hours");
TimeSpec spec = parser.parse();
long timestamp = spec.getTimestamp();
Field Summary
FieldsModifier and TypeFieldDescription(package private) intCurrent operation (PLUS/MINUS)(package private) intPrevious multiplier for months-minutes disambiguationprivate static final intOperator for "previous", used in place of + or -.(package private) final TimeScannerInput scanner(package private) final TimeSpecParsed time spec(package private) TimeTokenCurrent tokenConstructor Summary
ConstructorsConstructorDescriptionTimeParser(String dateString) Constructs TimeParser instance from the given input string.Method Summary
Modifier and TypeMethodDescriptionprivate voidassignDate(long mday, long mon, long year) Sets the day, month and year of the result.private voidday()Parses a day: a name, a month-day, or a full date.private voidexpectToken(int desired, String errorMessage) Expects a specific token type and throws exception if not found.parse()Parses the input string specified in the constructor.private voidplusMinus(int doop) Handles plus/minus operations for relative time adjustments.private voidAttempts to parse time-of-day specification from current token.
Field Details
PREVIOUS_OP
private static final int PREVIOUS_OPOperator for "previous", used in place of + or -.- See Also:
token
TimeToken tokenCurrent tokenscanner
Input scannerspec
Parsed time specop
int opCurrent operation (PLUS/MINUS)prev_multiplier
int prev_multiplierPrevious multiplier for months-minutes disambiguation
Constructor Details
TimeParser
Constructs TimeParser instance from the given input string.- Parameters:
dateString- at-style time specification (read rrdfetch man page for the complete explanation)
Method Details
expectToken
Expects a specific token type and throws exception if not found.This helper method advances the scanner and validates that the next token matches the expected type. If the token type doesn't match, it throws an IllegalArgumentException with the provided error message.
- Parameters:
desired- the expected token type identifiererrorMessage- error message to throw if token doesn't match- Throws:
IllegalArgumentException- if the next token is not of the desired type
plusMinus
private void plusMinus(int doop) Handles plus/minus operations for relative time adjustments.This method processes time adjustments like "+2 hours" or "-5 days". It handles the ambiguous "m" token (months vs minutes) by using context from the previous multiplier to make an educated guess.
Ambiguity resolution logic:
- After days/weeks/months/years: "m" means months
- After seconds/minutes/hours: "m" means minutes
- Otherwise: numbers < 6 mean months, >= 6 mean minutes- Parameters:
doop- the operation type (PLUS or MINUS), or -1 to skip processing
timeOfDay
private void timeOfDay()Attempts to parse time-of-day specification from current token.This method is called when a plain number is encountered at the start of a time specification, which could represent either a time (HH:MM) or a date. The method tries to parse it as a time first, and if that fails, it restores scanner state and returns without modifying the time spec.
Supported time formats:
- HH (hour only)
- HH:MM or HH.MM (hour and minute)
- Optional AM/PM suffix for 12-hour formatThe method uses backtracking to restore scanner state if parsing fails, allowing the parser to try alternative interpretations (like treating the number as a date instead).
assignDate
private void assignDate(long mday, long mon, long year) Sets the day, month and year of the result.- Parameters:
mday- day of the monthmon- the month number, 1 to 12year- the year, with the century
day
private void day()Parses a day: a name, a month-day, or a full date.parse
Parses the input string specified in the constructor.- Returns:
- Object representing parsed date/time.