Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it possible to build a parser by tokens #30

Merged
merged 8 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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 @@
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);

Check warning on line 80 in src/main/java/com/ethlo/time/internal/fixed/ITUParser.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/ethlo/time/internal/fixed/ITUParser.java#L80

Added line #L80 was not covered by tests
}
}

Expand Down Expand Up @@ -109,7 +110,7 @@
final char sign = chars.charAt(idx);
if (sign != PLUS && sign != MINUS)
{
raiseUnexpectedCharacter(chars, idx);
raiseUnexpectedCharacter(chars, idx, ZULU_UPPER, ZULU_LOWER, PLUS, MINUS);

Check warning on line 113 in src/main/java/com/ethlo/time/internal/fixed/ITUParser.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/ethlo/time/internal/fixed/ITUParser.java#L113

Added line #L113 was not covered by tests
}

if (left < 6)
Expand Down Expand Up @@ -258,7 +259,7 @@
}
else
{
throw raiseUnexpectedCharacter(chars, offset + 19);
throw raiseUnexpectedCharacter(chars, offset + 19, ArrayUtils.merge(parseConfig.getFractionSeparators(), new char[]{ZULU_UPPER, ZULU_LOWER, PLUS, MINUS}));

Check warning on line 262 in src/main/java/com/ethlo/time/internal/fixed/ITUParser.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/ethlo/time/internal/fixed/ITUParser.java#L262

Added line #L262 was not covered by tests
}
}
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
Loading