Skip to content

Commit

Permalink
fixing date defaulting when input format is day of year
Browse files Browse the repository at this point in the history
  • Loading branch information
Vishalks committed Sep 21, 2022
1 parent f73a870 commit 37fc8aa
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,15 @@ public long getFrom(TemporalAccessor temporal) {
static final DateFormatter SECONDS_FORMATTER = new JavaDateFormatter(
"epoch_second",
SECONDS_FORMATTER1,
builder -> builder.parseDefaulting(ChronoField.NANO_OF_SECOND, 999_999_999L),
(builder, parser) -> builder.parseDefaulting(ChronoField.NANO_OF_SECOND, 999_999_999L),
SECONDS_FORMATTER1,
SECONDS_FORMATTER2
);

static final DateFormatter MILLIS_FORMATTER = new JavaDateFormatter(
"epoch_millis",
MILLISECONDS_FORMATTER1,
builder -> builder.parseDefaulting(EpochTime.NANOS_OF_MILLI, 999_999L),
(builder, parser) -> builder.parseDefaulting(EpochTime.NANOS_OF_MILLI, 999_999L),
MILLISECONDS_FORMATTER1,
MILLISECONDS_FORMATTER2
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,20 @@
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

class JavaDateFormatter implements DateFormatter {

// base fields which should be used for default parsing, when we round up for date math
private static final Map<TemporalField, Long> ROUND_UP_BASE_FIELDS = new HashMap<>(6);
private static final Map<TemporalField, Long> ROUND_UP_GENERIC_BASE_FIELDS = new HashMap<>(4);

{
ROUND_UP_BASE_FIELDS.put(ChronoField.MONTH_OF_YEAR, 1L);
ROUND_UP_BASE_FIELDS.put(ChronoField.DAY_OF_MONTH, 1L);
ROUND_UP_BASE_FIELDS.put(ChronoField.HOUR_OF_DAY, 23L);
ROUND_UP_BASE_FIELDS.put(ChronoField.MINUTE_OF_HOUR, 59L);
ROUND_UP_BASE_FIELDS.put(ChronoField.SECOND_OF_MINUTE, 59L);
ROUND_UP_BASE_FIELDS.put(ChronoField.NANO_OF_SECOND, 999_999_999L);
ROUND_UP_GENERIC_BASE_FIELDS.put(ChronoField.HOUR_OF_DAY, 23L);
ROUND_UP_GENERIC_BASE_FIELDS.put(ChronoField.MINUTE_OF_HOUR, 59L);
ROUND_UP_GENERIC_BASE_FIELDS.put(ChronoField.SECOND_OF_MINUTE, 59L);
ROUND_UP_GENERIC_BASE_FIELDS.put(ChronoField.NANO_OF_SECOND, 999_999_999L);
}

private final String format;
private final DateTimeFormatter printer;
private final List<DateTimeFormatter> parsers;
Expand Down Expand Up @@ -96,14 +93,25 @@ JavaDateFormatter getRoundupParser() {

// named formatters use default roundUpParser
JavaDateFormatter(String format, DateTimeFormatter printer, DateTimeFormatter... parsers) {
this(format, printer, builder -> ROUND_UP_BASE_FIELDS.forEach(builder::parseDefaulting), parsers);
this(format, printer, ROUND_UP_BASE_FIELDS, parsers);
}

private static final BiConsumer<DateTimeFormatterBuilder, DateTimeFormatter> ROUND_UP_BASE_FIELDS = (builder, parser) -> {
String parserString = parser.toString();
if (parserString.contains(ChronoField.DAY_OF_YEAR.toString())) {
builder.parseDefaulting(ChronoField.DAY_OF_YEAR, 1L);
} else {
builder.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1L);
builder.parseDefaulting(ChronoField.DAY_OF_MONTH, 1L);
}
ROUND_UP_GENERIC_BASE_FIELDS.forEach(builder::parseDefaulting);
};

// subclasses override roundUpParser
JavaDateFormatter(
String format,
DateTimeFormatter printer,
Consumer<DateTimeFormatterBuilder> roundupParserConsumer,
BiConsumer<DateTimeFormatterBuilder, DateTimeFormatter> roundupParserConsumer,
DateTimeFormatter... parsers
) {
if (printer == null) {
Expand Down Expand Up @@ -138,13 +146,13 @@ JavaDateFormatter getRoundupParser() {
* <code>DateFormatters</code>.
* This means that we need to also have multiple RoundUp parsers.
*/
private List<DateTimeFormatter> createRoundUpParser(String format, Consumer<DateTimeFormatterBuilder> roundupParserConsumer) {
private List<DateTimeFormatter> createRoundUpParser(String format, BiConsumer<DateTimeFormatterBuilder, DateTimeFormatter> roundupParserConsumer) {
if (format.contains("||") == false) {
List<DateTimeFormatter> roundUpParsers = new ArrayList<>();
for (DateTimeFormatter parser : this.parsers) {
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.append(parser);
roundupParserConsumer.accept(builder);
roundupParserConsumer.accept(builder, parser);
roundUpParsers.add(builder.toFormatter(locale()));
}
return roundUpParsers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ public void testWeekDates() {
assertDateMathEquals(formatter.toDateMathParser(), "2015", "2014-12-29T23:59:59.999Z", 0, true, ZoneOffset.UTC);
}

public void testDayOfYear() {
DateFormatter formatter = DateFormatter.forPattern("yyyy-DDD'T'HH:mm:ss.SSS");
assertDateMathEquals(formatter.toDateMathParser(), "2022-104T14:08:31.355", "2022-104T14:08:31.355", 0, true, ZoneOffset.UTC);
}

public void testDayOfYearWithMissingFields() {
DateFormatter formatter = DateFormatter.forPattern("yyyy[-DDD'T'HH:mm:ss.SSS]");
assertDateMathEquals(formatter.toDateMathParser(), "2022", "2022-01-01T23:59:59.999Z", 0, true, ZoneOffset.UTC);
}

public void testBasicDates() {
assertDateMathEquals("2014-05-30", "2014-05-30T00:00:00.000");
assertDateMathEquals("2014-05-30T20", "2014-05-30T20:00:00.000");
Expand Down

0 comments on commit 37fc8aa

Please sign in to comment.