initial commit

This commit is contained in:
Naoto Sato 2026-01-22 15:45:27 -08:00
parent 96a2649e29
commit 14c4beb193
3 changed files with 52 additions and 4 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -817,6 +817,7 @@ public final class DateTimeFormatter {
* <li>The {@link #ISO_LOCAL_DATE}
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* Parsing is case insensitive.
* </ul>
* <p>
@ -829,7 +830,9 @@ public final class DateTimeFormatter {
ISO_OFFSET_DATE = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.parseLenient()
.appendOffsetId()
.parseStrict()
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
}
@ -846,6 +849,7 @@ public final class DateTimeFormatter {
* <li>If the offset is not available then the format is complete.
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* Parsing is case insensitive.
* </ul>
* <p>
@ -862,7 +866,9 @@ public final class DateTimeFormatter {
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.optionalStart()
.parseLenient()
.appendOffsetId()
.parseStrict()
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
}
@ -919,6 +925,7 @@ public final class DateTimeFormatter {
* <li>The {@link #ISO_LOCAL_TIME}
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* Parsing is case insensitive.
* </ul>
* <p>
@ -930,7 +937,9 @@ public final class DateTimeFormatter {
ISO_OFFSET_TIME = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_TIME)
.parseLenient()
.appendOffsetId()
.parseStrict()
.toFormatter(ResolverStyle.STRICT, null);
}
@ -947,6 +956,7 @@ public final class DateTimeFormatter {
* <li>If the offset is not available then the format is complete.
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* Parsing is case insensitive.
* </ul>
* <p>
@ -962,7 +972,9 @@ public final class DateTimeFormatter {
.parseCaseInsensitive()
.append(ISO_LOCAL_TIME)
.optionalStart()
.parseLenient()
.appendOffsetId()
.parseStrict()
.toFormatter(ResolverStyle.STRICT, null);
}
@ -1075,6 +1087,7 @@ public final class DateTimeFormatter {
* <li>If the offset is not available to format or parse then the format is complete.
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* <li>If the zone ID is not available or is a {@code ZoneOffset} then the format is complete.
* <li>An open square bracket '['.
* <li>The {@link ZoneId#getId() zone ID}. This is not part of the ISO-8601 standard.
@ -1094,7 +1107,9 @@ public final class DateTimeFormatter {
ISO_DATE_TIME = new DateTimeFormatterBuilder()
.append(ISO_LOCAL_DATE_TIME)
.optionalStart()
.parseLenient()
.appendOffsetId()
.parseStrict()
.optionalStart()
.appendLiteral('[')
.parseCaseSensitive()
@ -1121,6 +1136,7 @@ public final class DateTimeFormatter {
* <li>If the offset is not available to format or parse then the format is complete.
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* Parsing is case insensitive.
* </ul>
* <p>
@ -1139,7 +1155,9 @@ public final class DateTimeFormatter {
.appendLiteral('-')
.appendValue(DAY_OF_YEAR, 3)
.optionalStart()
.parseLenient()
.appendOffsetId()
.parseStrict()
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
}
@ -1165,6 +1183,7 @@ public final class DateTimeFormatter {
* <li>If the offset is not available to format or parse then the format is complete.
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard.
* The offset parsing is lenient, which allows the minutes and seconds to be optional.
* Parsing is case insensitive.
* </ul>
* <p>
@ -1185,7 +1204,9 @@ public final class DateTimeFormatter {
.appendLiteral('-')
.appendValue(DAY_OF_WEEK, 1)
.optionalStart()
.parseLenient()
.appendOffsetId()
.parseStrict()
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
}

View File

@ -421,7 +421,6 @@ public class TCKOffsetTime extends AbstractDateTimeTest {
{"00;00"},
{"12-00"},
{"-01:00"},
{"00:00:00-09"},
{"00:00:00,09"},
{"00:00:abs"},
{"11"},

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -59,6 +59,7 @@
*/
package test.java.time.format;
import static java.time.format.DateTimeFormatter.*;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -93,15 +94,19 @@ import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.util.Locale;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Test DateTimeFormatter.
* @bug 8085887 8293146
* @bug 8085887 8293146 8210336
*/
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class TestDateTimeFormatter {
@ -333,4 +338,27 @@ public class TestDateTimeFormatter {
assertThrows(DateTimeException.class, () -> LocalDate.parse(weekDate, f));
}
}
private static Stream<Arguments> data_iso_short_offset_parse() {
return Stream.of(
Arguments.of("20260123-01", BASIC_ISO_DATE),
Arguments.of("2026-01-23-01", ISO_DATE),
Arguments.of("2026-01-23T11:30:59-01", ISO_DATE_TIME),
Arguments.of("11:30:59-01", ISO_TIME),
Arguments.of("2026-01-23-01", ISO_OFFSET_DATE),
Arguments.of("2026-01-23T11:30:59-01", ISO_OFFSET_DATE_TIME),
Arguments.of("11:30:59-01", ISO_OFFSET_TIME),
Arguments.of("2026-023-01", ISO_ORDINAL_DATE),
Arguments.of("2026-W04-5-01", ISO_WEEK_DATE)
);
}
// Checks if predefined ISO formatters can parse hour-only offsets
@ParameterizedTest
@MethodSource("data_iso_short_offset_parse")
public void test_iso_short_offset_parse(String text, DateTimeFormatter formatter) {
var formatted = formatter.format(formatter.parse(text));
var expected = text + (formatter == BASIC_ISO_DATE ? "00" : ":00");
assertEquals(expected, formatted);
}
}