8166138: DateTimeFormatter.ISO_INSTANT should handle offsets

Reviewed-by: rriggs, scolebourne, naoto
This commit is contained in:
Pallavi Sonal 2018-10-04 17:25:51 +05:30 committed by Nishit Jain
parent ea3fb3979c
commit f5d19b9109
3 changed files with 79 additions and 24 deletions

View file

@ -1138,9 +1138,12 @@ public final class DateTimeFormatter {
* <p>
* This returns an immutable formatter capable of formatting and parsing
* the ISO-8601 instant format.
* When formatting, the second-of-minute is always output.
* When formatting, the instant will always be suffixed by 'Z' to indicate UTC.
* The second-of-minute is always output.
* The nano-of-second outputs zero, three, six or nine digits as necessary.
* When parsing, time to at least the seconds field is required.
* When parsing, the behaviour of {@link DateTimeFormatterBuilder#appendOffsetId()}
* will be used to parse the offset, converting the instant to UTC as necessary.
* The time to at least the seconds field is required.
* Fractional seconds from zero to nine are parsed.
* The localized decimal style is not used.
* <p>

View file

@ -837,6 +837,10 @@ public final class DateTimeFormatterBuilder {
* The leap-second time of '23:59:59' is handled to some degree, see
* {@link DateTimeFormatter#parsedLeapSecond()} for full details.
* <p>
* When formatting, the instant will always be suffixed by 'Z' to indicate UTC.
* When parsing, the behaviour of {@link DateTimeFormatterBuilder#appendOffsetId()}
* will be used to parse the offset, converting the instant to UTC as necessary.
* <p>
* An alternative to this method is to format/parse the instant as a single
* epoch-seconds value. That is achieved using {@code appendValue(INSTANT_SECONDS)}.
*
@ -3468,7 +3472,7 @@ public final class DateTimeFormatterBuilder {
.appendValue(MINUTE_OF_HOUR, 2).appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.appendFraction(NANO_OF_SECOND, minDigits, maxDigits, true)
.appendLiteral('Z')
.appendOffsetId()
.toFormatter().toPrinterParser(false);
DateTimeParseContext newContext = context.copy();
int pos = parser.parse(newContext, text, position);
@ -3486,6 +3490,7 @@ public final class DateTimeFormatterBuilder {
Long nanoVal = newContext.getParsed(NANO_OF_SECOND);
int sec = (secVal != null ? secVal.intValue() : 0);
int nano = (nanoVal != null ? nanoVal.intValue() : 0);
int offset = newContext.getParsed(OFFSET_SECONDS).intValue();
int days = 0;
if (hour == 24 && min == 0 && sec == 0 && nano == 0) {
hour = 0;
@ -3498,7 +3503,7 @@ public final class DateTimeFormatterBuilder {
long instantSecs;
try {
LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, min, sec, 0).plusDays(days);
instantSecs = ldt.toEpochSecond(ZoneOffset.UTC);
instantSecs = ldt.toEpochSecond(ZoneOffset.ofTotalSeconds(offset));
instantSecs += Math.multiplyExact(yearParsed / 10_000L, SECONDS_PER_10000_YEARS);
} catch (RuntimeException ex) {
return ~position;