Skip to content

Commit

Permalink
Make it possible to build a parser by tokens (#30)
Browse files Browse the repository at this point in the history
Make it possible to build custom parser by tokens
  • Loading branch information
ethlo authored Feb 4, 2024
1 parent 6861929 commit ababe65
Show file tree
Hide file tree
Showing 27 changed files with 986 additions and 64 deletions.
18 changes: 9 additions & 9 deletions src/main/java/com/ethlo/time/DateTime.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
* #L%
*/

import static com.ethlo.time.internal.ITUParser.DATE_SEPARATOR;
import static com.ethlo.time.internal.ITUParser.SEPARATOR_UPPER;
import static com.ethlo.time.internal.ITUParser.TIME_SEPARATOR;
import static com.ethlo.time.internal.ITUFormatter.finish;
import static com.ethlo.time.internal.LeapSecondHandler.LEAP_SECOND_SECONDS;
import static com.ethlo.time.internal.fixed.ITUFormatter.finish;
import static com.ethlo.time.internal.fixed.ITUParser.DATE_SEPARATOR;
import static com.ethlo.time.internal.fixed.ITUParser.SEPARATOR_UPPER;
import static com.ethlo.time.internal.fixed.ITUParser.TIME_SEPARATOR;
import static com.ethlo.time.internal.util.LeapSecondHandler.LEAP_SECOND_SECONDS;

import java.time.DateTimeException;
import java.time.Instant;
Expand All @@ -43,10 +43,10 @@
import java.util.Optional;

import com.ethlo.time.internal.DateTimeFormatException;
import com.ethlo.time.internal.DateTimeMath;
import com.ethlo.time.internal.DefaultLeapSecondHandler;
import com.ethlo.time.internal.LeapSecondHandler;
import com.ethlo.time.internal.LimitedCharArrayIntegerUtil;
import com.ethlo.time.internal.util.DateTimeMath;
import com.ethlo.time.internal.util.DefaultLeapSecondHandler;
import com.ethlo.time.internal.util.LeapSecondHandler;
import com.ethlo.time.internal.util.LimitedCharArrayIntegerUtil;

/**
* Container class for parsed date/date-time data. The {@link #getMostGranularField()} contains the highest granularity field found, like MONTH, MINUTE, SECOND.
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/ethlo/time/Field.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public enum Field
HOUR(13),
MINUTE(16),
SECOND(19),
NANO(20);
NANO(20),
ZONE_OFFSET(17);

private final int requiredLength;

Expand Down
12 changes: 6 additions & 6 deletions src/main/java/com/ethlo/time/ITU.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import java.time.YearMonth;
import java.time.format.DateTimeParseException;

import com.ethlo.time.internal.ITUFormatter;
import com.ethlo.time.internal.ITUParser;
import com.ethlo.time.internal.fixed.ITUFormatter;
import com.ethlo.time.internal.fixed.ITUParser;

/**
* The main access to the parse and formatting functions in this library.
Expand Down Expand Up @@ -71,7 +71,8 @@ public static DateTime parseLenient(String text)

/**
* Allows parsing leniently with {@link ParseConfig to control some aspects of the parsing}
* @param text The text to parse
*
* @param text The text to parse
* @param parseConfig The configuration to use for parsing
* @return The date-time parsed
*/
Expand All @@ -81,10 +82,9 @@ public static DateTime parseLenient(String text, ParseConfig parseConfig)
}

/**
*
* @param text The text to parse
* @param text The text to parse
* @param parseConfig The configuration to use for parsing
* @param position The position to start parsing from. The index (and the errorIndex, if an error occurs) is updated after the parsing process has completed
* @param position The position to start parsing from. The index (and the errorIndex, if an error occurs) is updated after the parsing process has completed
* @return The date-time parsed
*/
public static DateTime parseLenient(String text, ParseConfig parseConfig, ParsePosition position)
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/com/ethlo/time/ParseConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,11 @@
* #L%
*/

import static com.ethlo.time.internal.ITUParser.SEPARATOR_LOWER;
import static com.ethlo.time.internal.ITUParser.SEPARATOR_SPACE;
import static com.ethlo.time.internal.ITUParser.SEPARATOR_UPPER;

import java.util.Arrays;
import java.util.Optional;

import static com.ethlo.time.internal.fixed.ITUParser.*;

public class ParseConfig
{
private static final char[] DEFAULT_DATE_TIME_SEPARATORS = new char[]{SEPARATOR_UPPER, SEPARATOR_LOWER, SEPARATOR_SPACE};
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/ethlo/time/TimezoneOffset.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
public class TimezoneOffset
{
public static final TimezoneOffset UTC = new TimezoneOffset(0, 0);
private static final int SECONDS_PER_HOUR = 3600;
private static final int SECONDS_PER_MINUTE = 60;
private static final int MINUTES_PER_HOUR = 60;
private final int hours;
private final int minutes;

Expand All @@ -43,6 +46,13 @@ public static TimezoneOffset ofHoursMinutes(int hours, int minutes)
return new TimezoneOffset(hours, minutes);
}

public static TimezoneOffset ofTotalSeconds(int seconds)
{
final int absHours = seconds / SECONDS_PER_HOUR;
int absMinutes = (seconds / SECONDS_PER_MINUTE) % MINUTES_PER_HOUR;
return ofHoursMinutes(absHours, absMinutes);
}

public static TimezoneOffset of(ZoneOffset offset)
{
final int seconds = offset.getTotalSeconds();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ethlo.time.internal;
package com.ethlo.time.internal.fixed;

/*-
* #%L
Expand All @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -20,20 +20,22 @@
* #L%
*/

import static com.ethlo.time.internal.ITUParser.DATE_SEPARATOR;
import static com.ethlo.time.internal.ITUParser.FRACTION_SEPARATOR;
import static com.ethlo.time.internal.ITUParser.MAX_FRACTION_DIGITS;
import static com.ethlo.time.internal.ITUParser.MINUS;
import static com.ethlo.time.internal.ITUParser.PLUS;
import static com.ethlo.time.internal.ITUParser.SEPARATOR_UPPER;
import static com.ethlo.time.internal.ITUParser.TIME_SEPARATOR;
import static com.ethlo.time.internal.ITUParser.ZULU_UPPER;
import static com.ethlo.time.internal.fixed.ITUParser.DATE_SEPARATOR;
import static com.ethlo.time.internal.fixed.ITUParser.FRACTION_SEPARATOR;
import static com.ethlo.time.internal.fixed.ITUParser.MAX_FRACTION_DIGITS;
import static com.ethlo.time.internal.fixed.ITUParser.MINUS;
import static com.ethlo.time.internal.fixed.ITUParser.PLUS;
import static com.ethlo.time.internal.fixed.ITUParser.SEPARATOR_UPPER;
import static com.ethlo.time.internal.fixed.ITUParser.TIME_SEPARATOR;
import static com.ethlo.time.internal.fixed.ITUParser.ZULU_UPPER;

import java.time.OffsetDateTime;
import java.time.ZoneOffset;

import com.ethlo.time.Field;
import com.ethlo.time.TimezoneOffset;
import com.ethlo.time.internal.DateTimeFormatException;
import com.ethlo.time.internal.util.LimitedCharArrayIntegerUtil;

public class ITUFormatter
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ethlo.time.internal;
package com.ethlo.time.internal.fixed;

/*-
* #%L
Expand All @@ -20,13 +20,13 @@
* #L%
*/

import static com.ethlo.time.internal.ErrorUtil.assertFractionDigits;
import static com.ethlo.time.internal.ErrorUtil.assertPositionContains;
import static com.ethlo.time.internal.ErrorUtil.raiseUnexpectedCharacter;
import static com.ethlo.time.internal.ErrorUtil.raiseUnexpectedEndOfText;
import static com.ethlo.time.internal.LimitedCharArrayIntegerUtil.DIGIT_9;
import static com.ethlo.time.internal.LimitedCharArrayIntegerUtil.ZERO;
import static com.ethlo.time.internal.LimitedCharArrayIntegerUtil.parsePositiveInt;
import static com.ethlo.time.internal.util.ErrorUtil.assertFractionDigits;
import static com.ethlo.time.internal.util.ErrorUtil.assertPositionContains;
import static com.ethlo.time.internal.util.ErrorUtil.raiseUnexpectedCharacter;
import static com.ethlo.time.internal.util.ErrorUtil.raiseUnexpectedEndOfText;
import static com.ethlo.time.internal.util.LimitedCharArrayIntegerUtil.DIGIT_9;
import static com.ethlo.time.internal.util.LimitedCharArrayIntegerUtil.ZERO;
import static com.ethlo.time.internal.util.LimitedCharArrayIntegerUtil.parsePositiveInt;

import java.time.OffsetDateTime;
import java.time.format.DateTimeParseException;
Expand All @@ -36,6 +36,7 @@
import com.ethlo.time.Field;
import com.ethlo.time.ParseConfig;
import com.ethlo.time.TimezoneOffset;
import com.ethlo.time.internal.util.ArrayUtils;

public class ITUParser
{
Expand All @@ -44,11 +45,11 @@ public class ITUParser
public static final char SEPARATOR_UPPER = 'T';
public static final char SEPARATOR_LOWER = 't';
public static final char SEPARATOR_SPACE = ' ';
static final char PLUS = '+';
static final char MINUS = '-';
public static final char PLUS = '+';
public static final char MINUS = '-';
public static final char FRACTION_SEPARATOR = '.';
static final char ZULU_UPPER = 'Z';
private static final char ZULU_LOWER = 'z';
public static final char ZULU_UPPER = 'Z';
public static final char ZULU_LOWER = 'z';
public static final int MAX_FRACTION_DIGITS = 9;
public static final int RADIX = 10;
public static final int DIGITS_IN_NANO = 9;
Expand Down Expand Up @@ -76,7 +77,7 @@ private static DateTime handleTime(final int offset, final ParseConfig parseConf
return new DateTime(Field.MINUTE, year, month, day, hour, minute, 0, 0, zoneOffset, 0, charLength);

default:
throw raiseUnexpectedCharacter(chars, offset + 16);
throw raiseUnexpectedCharacter(chars, offset + 16, TIME_SEPARATOR, ZULU_UPPER, ZULU_LOWER, PLUS, MINUS);
}
}

Expand Down Expand Up @@ -109,7 +110,7 @@ private static TimezoneOffset parseTimezone(int offset, final ParseConfig parseC
final char sign = chars.charAt(idx);
if (sign != PLUS && sign != MINUS)
{
raiseUnexpectedCharacter(chars, idx);
raiseUnexpectedCharacter(chars, idx, ZULU_UPPER, ZULU_LOWER, PLUS, MINUS);
}

if (left < 6)
Expand Down Expand Up @@ -258,7 +259,7 @@ else if (c == PLUS || c == MINUS)
}
else
{
throw raiseUnexpectedCharacter(chars, offset + 19);
throw raiseUnexpectedCharacter(chars, offset + 19, ArrayUtils.merge(parseConfig.getFractionSeparators(), new char[]{ZULU_UPPER, ZULU_LOWER, PLUS, MINUS}));
}
}
else if (length == 19)
Expand Down
60 changes: 60 additions & 0 deletions src/main/java/com/ethlo/time/internal/token/DigitsToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.ethlo.time.internal.token;

/*-
* #%L
* Internet Time Utility
* %%
* Copyright (C) 2017 - 2024 Morten Haraldsen (ethlo)
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import java.text.ParsePosition;

import com.ethlo.time.Field;
import com.ethlo.time.internal.util.LimitedCharArrayIntegerUtil;
import com.ethlo.time.token.DateTimeToken;

public class DigitsToken implements DateTimeToken
{
private final Field field;
private final int length;

public DigitsToken(Field field, int length)
{
this.field = field;
this.length = length;
}

@Override
public int read(String text, ParsePosition parsePosition)
{
final int offset = parsePosition.getIndex();
final int end = offset + length;
final int value = LimitedCharArrayIntegerUtil.parsePositiveInt(text, offset, end);
parsePosition.setIndex(end);
return value;
}

public Field getField()
{
return field;
}

@Override
public String toString()
{
return "digits: " + field + "(" + length + ")";
}
}
61 changes: 61 additions & 0 deletions src/main/java/com/ethlo/time/internal/token/FractionsToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.ethlo.time.internal.token;

/*-
* #%L
* Internet Time Utility
* %%
* Copyright (C) 2017 - 2024 Morten Haraldsen (ethlo)
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import static com.ethlo.time.internal.util.LimitedCharArrayIntegerUtil.DIGIT_9;
import static com.ethlo.time.internal.util.LimitedCharArrayIntegerUtil.ZERO;

import java.text.ParsePosition;

import com.ethlo.time.Field;
import com.ethlo.time.token.DateTimeToken;

public class FractionsToken implements DateTimeToken
{
@Override
public int read(final String text, final ParsePosition parsePosition)
{
int idx = parsePosition.getIndex();
final int length = text.length();
int value = 0;
while (idx < length)
{
final char c = text.charAt(idx);
if (c < ZERO || c > DIGIT_9)
{
break;
}
else
{
value = value * 10 + (c - ZERO);
idx++;
}
}
parsePosition.setIndex(idx);
return value;
}

@Override
public Field getField()
{
return Field.NANO;
}
}
Loading

0 comments on commit ababe65

Please sign in to comment.