8337279: Share StringBuilder to format instant

Reviewed-by: naoto, liach
This commit is contained in:
Shaojin Wen 2025-03-22 01:35:09 +00:00
parent 22182f71ed
commit 74420391fa
10 changed files with 342 additions and 123 deletions

View File

@ -103,6 +103,8 @@ import java.util.Objects;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import jdk.internal.util.DateTimeHelper;
/**
* A date without a time-zone in the ISO-8601 calendar system,
* such as {@code 2007-12-03}.
@ -2148,37 +2150,10 @@ public final class LocalDate
@Override
public String toString() {
var buf = new StringBuilder(10);
formatTo(buf);
DateTimeHelper.formatTo(buf, this);
return buf.toString();
}
/**
* Prints the toString result to the given buf, avoiding extra string allocations.
* Requires extra capacity of 10 to avoid StringBuilder reallocation.
*/
void formatTo(StringBuilder buf) {
int yearValue = year;
int monthValue = month;
int dayValue = day;
int absYear = Math.abs(yearValue);
if (absYear < 1000) {
if (yearValue < 0) {
buf.append('-');
}
buf.repeat('0', absYear < 10 ? 3 : absYear < 100 ? 2 : 1);
buf.append(absYear);
} else {
if (yearValue > 9999) {
buf.append('+');
}
buf.append(yearValue);
}
buf.append(monthValue < 10 ? "-0" : "-")
.append(monthValue)
.append(dayValue < 10 ? "-0" : "-")
.append(dayValue);
}
//-----------------------------------------------------------------------
/**
* Writes the object using a

View File

@ -96,6 +96,8 @@ import java.time.temporal.ValueRange;
import java.time.zone.ZoneRules;
import java.util.Objects;
import jdk.internal.util.DateTimeHelper;
/**
* A date-time without a time-zone in the ISO-8601 calendar system,
* such as {@code 2007-12-03T10:15:30}.
@ -1966,18 +1968,10 @@ public final class LocalDateTime
@Override
public String toString() {
var buf = new StringBuilder(29);
formatTo(buf);
DateTimeHelper.formatTo(buf, this);
return buf.toString();
}
/**
* Prints the toString result to the given buf, avoiding extra string allocations.
*/
void formatTo(StringBuilder buf) {
date.formatTo(buf);
buf.append('T');
time.formatTo(buf);
}
//-----------------------------------------------------------------------
/**
@ -2018,5 +2012,4 @@ public final class LocalDateTime
LocalTime time = LocalTime.readExternal(in);
return LocalDateTime.of(date, time);
}
}

View File

@ -92,7 +92,7 @@ import java.time.temporal.UnsupportedTemporalTypeException;
import java.time.temporal.ValueRange;
import java.util.Objects;
import jdk.internal.util.DecimalDigits;
import jdk.internal.util.DateTimeHelper;
/**
* A time without a time-zone in the ISO-8601 calendar system,
@ -1632,42 +1632,10 @@ public final class LocalTime
@Override
public String toString() {
var buf = new StringBuilder(18);
formatTo(buf);
DateTimeHelper.formatTo(buf, this);
return buf.toString();
}
/**
* Prints the toString result to the given buf, avoiding extra string allocations.
* Requires extra capacity of 18 to avoid StringBuilder reallocation.
*/
void formatTo(StringBuilder buf) {
int hourValue = hour;
int minuteValue = minute;
int secondValue = second;
int nanoValue = nano;
buf.append(hourValue < 10 ? "0" : "").append(hourValue)
.append(minuteValue < 10 ? ":0" : ":").append(minuteValue);
if (secondValue > 0 || nanoValue > 0) {
buf.append(secondValue < 10 ? ":0" : ":").append(secondValue);
if (nanoValue > 0) {
buf.append('.');
int zeros = 9 - DecimalDigits.stringSize(nanoValue);
if (zeros > 0) {
buf.repeat('0', zeros);
}
int digits;
if (nanoValue % 1_000_000 == 0) {
digits = nanoValue / 1_000_000;
} else if (nanoValue % 1000 == 0) {
digits = nanoValue / 1000;
} else {
digits = nanoValue;
}
buf.append(digits);
}
}
}
//-----------------------------------------------------------------------
/**
* Writes the object using a

View File

@ -93,6 +93,8 @@ import java.time.zone.ZoneRules;
import java.util.Comparator;
import java.util.Objects;
import jdk.internal.util.DateTimeHelper;
/**
* A date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system,
* such as {@code 2007-12-03T10:15:30+01:00}.
@ -1925,7 +1927,7 @@ public final class OffsetDateTime
public String toString() {
var offsetStr = offset.toString();
var buf = new StringBuilder(29 + offsetStr.length());
dateTime.formatTo(buf);
DateTimeHelper.formatTo(buf, dateTime);
return buf.append(offsetStr).toString();
}

View File

@ -92,6 +92,8 @@ import java.time.temporal.ValueRange;
import java.time.zone.ZoneRules;
import java.util.Objects;
import jdk.internal.util.DateTimeHelper;
/**
* A time with an offset from UTC/Greenwich in the ISO-8601 calendar system,
* such as {@code 10:15:30+01:00}.
@ -1400,7 +1402,7 @@ public final class OffsetTime
public String toString() {
var offsetStr = offset.toString();
var buf = new StringBuilder(18 + offsetStr.length());
time.formatTo(buf);
DateTimeHelper.formatTo(buf, time);
return buf.append(offsetStr).toString();
}

View File

@ -91,6 +91,8 @@ import java.time.zone.ZoneRules;
import java.util.List;
import java.util.Objects;
import jdk.internal.util.DateTimeHelper;
/**
* A date-time with a time-zone in the ISO-8601 calendar system,
* such as {@code 2007-12-03T10:15:30+01:00 Europe/Paris}.
@ -2222,7 +2224,7 @@ public final class ZonedDateTime
length += zoneStr.length() + 2;
}
var buf = new StringBuilder(length);
dateTime.formatTo(buf);
DateTimeHelper.formatTo(buf, dateTime);
buf.append(offsetStr);
if (zoneStr != null) {
buf.append('[').append(zoneStr).append(']');

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2025, 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
@ -121,6 +121,7 @@ import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.internal.util.DateTimeHelper;
import jdk.internal.util.DecimalDigits;
import sun.text.spi.JavaTimeDateTimePatternProvider;
@ -161,7 +162,6 @@ import sun.util.locale.provider.TimeZoneNameUtility;
* @since 1.8
*/
public final class DateTimeFormatterBuilder {
/**
* Query for a time-zone that is region-only.
*/
@ -3809,58 +3809,73 @@ public final class DateTimeFormatterBuilder {
}
long inSec = inSecs;
int inNano = NANO_OF_SECOND.checkValidIntValue(inNanos != null ? inNanos : 0);
// format mostly using LocalDateTime.toString
if (fractionalDigits == 0) {
inNano = 0;
}
boolean printNanoInLocalDateTime = fractionalDigits == -2
|| (inNano == 0 && (fractionalDigits == 0 || fractionalDigits == -1));
if (inSec >= -SECONDS_0000_TO_1970) {
// current era
long zeroSecs = inSec - SECONDS_PER_10000_YEARS + SECONDS_0000_TO_1970;
long hi = Math.floorDiv(zeroSecs, SECONDS_PER_10000_YEARS) + 1;
long lo = Math.floorMod(zeroSecs, SECONDS_PER_10000_YEARS);
LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, 0, ZoneOffset.UTC);
if (hi > 0) {
buf.append('+').append(hi);
}
buf.append(ldt);
if (ldt.getSecond() == 0) {
buf.append(":00");
}
currentEra(buf, inSec, printNanoInLocalDateTime ? inNano : 0);
} else {
// before current era
long zeroSecs = inSec + SECONDS_0000_TO_1970;
long hi = zeroSecs / SECONDS_PER_10000_YEARS;
long lo = zeroSecs % SECONDS_PER_10000_YEARS;
LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, 0, ZoneOffset.UTC);
int pos = buf.length();
buf.append(ldt);
if (ldt.getSecond() == 0) {
buf.append(":00");
}
if (hi < 0) {
if (ldt.getYear() == -10_000) {
buf.replace(pos, pos + 2, Long.toString(hi - 1));
} else if (lo == 0) {
buf.insert(pos, hi);
} else {
buf.insert(pos + 1, Math.abs(hi));
}
}
beforeCurrentEra(buf, inSec, printNanoInLocalDateTime ? inNano : 0);
}
// add fraction
if ((fractionalDigits < 0 && inNano > 0) || fractionalDigits > 0) {
buf.append('.');
int div = 100_000_000;
for (int i = 0; ((fractionalDigits == -1 && inNano > 0) ||
(fractionalDigits == -2 && (inNano > 0 || (i % 3) != 0)) ||
i < fractionalDigits); i++) {
int digit = inNano / div;
buf.append((char) (digit + '0'));
inNano = inNano - (digit * div);
div = div / 10;
}
if (!printNanoInLocalDateTime) {
printNano(buf, inSec, inNano);
}
buf.append('Z');
return true;
}
private void printNano(StringBuilder buf, long inSec, int inNano) {
buf.append('.');
int div = 100_000_000;
int fractionalDigits = this.fractionalDigits;
for (int i = 0; ((fractionalDigits == -1 && inNano > 0) ||
(fractionalDigits == -2 && (inNano > 0 || (i % 3) != 0)) ||
i < fractionalDigits); i++) {
int digit = inNano / div;
buf.append((char) (digit + '0'));
inNano = inNano - (digit * div);
div = div / 10;
}
}
private static void currentEra(StringBuilder buf, long inSec, int inNano) {
long zeroSecs = inSec - SECONDS_PER_10000_YEARS + SECONDS_0000_TO_1970;
long hi = Math.floorDiv(zeroSecs, SECONDS_PER_10000_YEARS) + 1;
long lo = Math.floorMod(zeroSecs, SECONDS_PER_10000_YEARS);
LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, inNano, ZoneOffset.UTC);
if (hi > 0) {
buf.append('+').append(hi);
}
DateTimeHelper.formatTo(buf, ldt);
if (ldt.getSecond() == 0 && inNano == 0) {
buf.append(":00");
}
}
private static void beforeCurrentEra(StringBuilder buf, long inSec, int inNano) {
long zeroSecs = inSec + SECONDS_0000_TO_1970;
long hi = zeroSecs / SECONDS_PER_10000_YEARS;
long lo = zeroSecs % SECONDS_PER_10000_YEARS;
LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, inNano, ZoneOffset.UTC);
int pos = buf.length();
DateTimeHelper.formatTo(buf, ldt);
if (ldt.getSecond() == 0 && inNano == 0) {
buf.append(":00");
}
if (hi < 0) {
if (ldt.getYear() == -10_000) {
buf.replace(pos, pos + 2, Long.toString(hi - 1));
} else if (lo == 0) {
buf.insert(pos, hi);
} else {
buf.insert(pos + 1, Math.abs(hi));
}
}
}
@Override
public int parse(DateTimeParseContext context, CharSequence text, int position) {
// new context to avoid overwriting fields like year/month/day

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, Alibaba Group Holding Limited. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* Helper for java.time
*/
public final class DateTimeHelper {
private DateTimeHelper() {
}
/**
* Prints the toString result to the given buf, avoiding extra string allocations.
*/
public static void formatTo(StringBuilder buf, LocalDateTime dateTime) {
DateTimeHelper.formatTo(buf, dateTime.toLocalDate());
buf.append('T');
DateTimeHelper.formatTo(buf, dateTime.toLocalTime());
}
/**
* Prints the toString result to the given buf, avoiding extra string allocations.
* Requires extra capacity of 10 to avoid StringBuilder reallocation.
*/
public static void formatTo(StringBuilder buf, LocalDate date) {
int year = date.getYear(),
month = date.getMonthValue(),
day = date.getDayOfMonth();
int absYear = Math.abs(year);
if (absYear < 1000) {
if (year < 0) {
buf.append('-');
}
buf.repeat('0', absYear < 10 ? 3 : absYear < 100 ? 2 : 1);
buf.append(absYear);
} else {
if (year > 9999) {
buf.append('+');
}
buf.append(year);
}
buf.append(month < 10 ? "-0" : "-").append(month)
.append(day < 10 ? "-0" : "-").append(day);
}
/**
* Prints the toString result to the given buf, avoiding extra string allocations.
* Requires extra capacity of 18 to avoid StringBuilder reallocation.
*/
public static void formatTo(StringBuilder buf, LocalTime time) {
int hour = time.getHour(),
minute = time.getMinute(),
second = time.getSecond(),
nano = time.getNano();
buf.append(hour < 10 ? "0" : "").append(hour)
.append(minute < 10 ? ":0" : ":").append(minute);
if ((second | nano) > 0) {
buf.append(second < 10 ? ":0" : ":").append(second);
if (nano > 0) {
buf.append('.');
int zeros = 9 - DecimalDigits.stringSize(nano);
if (zeros > 0) {
buf.repeat('0', zeros);
}
int digits;
if (nano % 1_000_000 == 0) {
digits = nano / 1_000_000;
} else if (nano % 1000 == 0) {
digits = nano / 1000;
} else {
digits = nano;
}
buf.append(digits);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2025, 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
@ -311,6 +311,158 @@ public class TCKInstantPrinterParser {
}
}
@Test
public void test_print_instant() {
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendInstant().toFormatter();
DateTimeFormatter formatter0 = new DateTimeFormatterBuilder().appendInstant(0).toFormatter();
DateTimeFormatter formatter1 = new DateTimeFormatterBuilder().appendInstant(1).toFormatter();
DateTimeFormatter formatter2 = new DateTimeFormatterBuilder().appendInstant(2).toFormatter();
DateTimeFormatter formatter3 = new DateTimeFormatterBuilder().appendInstant(3).toFormatter();
DateTimeFormatter formatter4 = new DateTimeFormatterBuilder().appendInstant(4).toFormatter();
DateTimeFormatter formatter5 = new DateTimeFormatterBuilder().appendInstant(5).toFormatter();
DateTimeFormatter formatter6 = new DateTimeFormatterBuilder().appendInstant(6).toFormatter();
DateTimeFormatter formatter7 = new DateTimeFormatterBuilder().appendInstant(7).toFormatter();
DateTimeFormatter formatter8 = new DateTimeFormatterBuilder().appendInstant(8).toFormatter();
DateTimeFormatter formatter9 = new DateTimeFormatterBuilder().appendInstant(9).toFormatter();
DateTimeFormatter formatterN1 = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter();
{
Instant instant = Instant.ofEpochSecond(1111721337984L, 1);
assertEquals("+37199-01-18T02:46:24.000000001Z", formatter.format(instant));
assertEquals("+37199-01-18T02:46:24Z", formatter0.format(instant));
assertEquals("+37199-01-18T02:46:24.0Z", formatter1.format(instant));
assertEquals("+37199-01-18T02:46:24.00Z", formatter2.format(instant));
assertEquals("+37199-01-18T02:46:24.000Z", formatter3.format(instant));
assertEquals("+37199-01-18T02:46:24.0000Z", formatter4.format(instant));
assertEquals("+37199-01-18T02:46:24.00000Z", formatter5.format(instant));
assertEquals("+37199-01-18T02:46:24.000000Z", formatter6.format(instant));
assertEquals("+37199-01-18T02:46:24.0000000Z", formatter7.format(instant));
assertEquals("+37199-01-18T02:46:24.00000000Z", formatter8.format(instant));
assertEquals("+37199-01-18T02:46:24.000000001Z", formatter9.format(instant));
assertEquals("+37199-01-18T02:46:24.000000001Z", formatterN1.format(instant));
}
{
Instant instant = Instant.ofEpochSecond(1111721337984L, 10);
assertEquals("+37199-01-18T02:46:24.000000010Z", formatter.format(instant));
assertEquals("+37199-01-18T02:46:24Z", formatter0.format(instant));
assertEquals("+37199-01-18T02:46:24.0Z", formatter1.format(instant));
assertEquals("+37199-01-18T02:46:24.00Z", formatter2.format(instant));
assertEquals("+37199-01-18T02:46:24.000Z", formatter3.format(instant));
assertEquals("+37199-01-18T02:46:24.0000Z", formatter4.format(instant));
assertEquals("+37199-01-18T02:46:24.00000Z", formatter5.format(instant));
assertEquals("+37199-01-18T02:46:24.000000Z", formatter6.format(instant));
assertEquals("+37199-01-18T02:46:24.0000000Z", formatter7.format(instant));
assertEquals("+37199-01-18T02:46:24.00000001Z", formatter8.format(instant));
assertEquals("+37199-01-18T02:46:24.000000010Z", formatter9.format(instant));
assertEquals("+37199-01-18T02:46:24.00000001Z", formatterN1.format(instant));
}
{
Instant instant = Instant.ofEpochSecond(1111721337984L, 100);
assertEquals("+37199-01-18T02:46:24.000000100Z", formatter.format(instant));
assertEquals("+37199-01-18T02:46:24Z", formatter0.format(instant));
assertEquals("+37199-01-18T02:46:24.0Z", formatter1.format(instant));
assertEquals("+37199-01-18T02:46:24.00Z", formatter2.format(instant));
assertEquals("+37199-01-18T02:46:24.000Z", formatter3.format(instant));
assertEquals("+37199-01-18T02:46:24.0000Z", formatter4.format(instant));
assertEquals("+37199-01-18T02:46:24.00000Z", formatter5.format(instant));
assertEquals("+37199-01-18T02:46:24.000000Z", formatter6.format(instant));
assertEquals("+37199-01-18T02:46:24.0000001Z", formatter7.format(instant));
assertEquals("+37199-01-18T02:46:24.00000010Z", formatter8.format(instant));
assertEquals("+37199-01-18T02:46:24.000000100Z", formatter9.format(instant));
assertEquals("+37199-01-18T02:46:24.0000001Z", formatterN1.format(instant));
}
{
Instant instant = Instant.ofEpochSecond(1111721337984L, 1_000);
assertEquals("+37199-01-18T02:46:24.000001Z", formatter.format(instant));
assertEquals("+37199-01-18T02:46:24Z", formatter0.format(instant));
assertEquals("+37199-01-18T02:46:24.0Z", formatter1.format(instant));
assertEquals("+37199-01-18T02:46:24.00Z", formatter2.format(instant));
assertEquals("+37199-01-18T02:46:24.000Z", formatter3.format(instant));
assertEquals("+37199-01-18T02:46:24.0000Z", formatter4.format(instant));
assertEquals("+37199-01-18T02:46:24.00000Z", formatter5.format(instant));
assertEquals("+37199-01-18T02:46:24.000001Z", formatter6.format(instant));
assertEquals("+37199-01-18T02:46:24.0000010Z", formatter7.format(instant));
assertEquals("+37199-01-18T02:46:24.00000100Z", formatter8.format(instant));
assertEquals("+37199-01-18T02:46:24.000001000Z", formatter9.format(instant));
assertEquals("+37199-01-18T02:46:24.000001Z", formatterN1.format(instant));
}
{
Instant instant = Instant.ofEpochSecond(1721337984L, 10_000);
assertEquals("2024-07-18T21:26:24.000010Z", formatter.format(instant));
assertEquals("2024-07-18T21:26:24Z", formatter0.format(instant));
assertEquals("2024-07-18T21:26:24.0Z", formatter1.format(instant));
assertEquals("2024-07-18T21:26:24.00Z", formatter2.format(instant));
assertEquals("2024-07-18T21:26:24.000Z", formatter3.format(instant));
assertEquals("2024-07-18T21:26:24.0000Z", formatter4.format(instant));
assertEquals("2024-07-18T21:26:24.00001Z", formatter5.format(instant));
assertEquals("2024-07-18T21:26:24.000010Z", formatter6.format(instant));
assertEquals("2024-07-18T21:26:24.0000100Z", formatter7.format(instant));
assertEquals("2024-07-18T21:26:24.00001000Z", formatter8.format(instant));
assertEquals("2024-07-18T21:26:24.000010000Z", formatter9.format(instant));
assertEquals("2024-07-18T21:26:24.00001Z", formatterN1.format(instant));
}
{
Instant instant = Instant.ofEpochSecond(-1721337984L, 100_000);
assertEquals("1915-06-16T02:33:36.000100Z", formatter.format(instant));
assertEquals("1915-06-16T02:33:36Z", formatter0.format(instant));
assertEquals("1915-06-16T02:33:36.0Z", formatter1.format(instant));
assertEquals("1915-06-16T02:33:36.00Z", formatter2.format(instant));
assertEquals("1915-06-16T02:33:36.000Z", formatter3.format(instant));
assertEquals("1915-06-16T02:33:36.0001Z", formatter4.format(instant));
assertEquals("1915-06-16T02:33:36.00010Z", formatter5.format(instant));
assertEquals("1915-06-16T02:33:36.000100Z", formatter6.format(instant));
assertEquals("1915-06-16T02:33:36.0001000Z", formatter7.format(instant));
assertEquals("1915-06-16T02:33:36.00010000Z", formatter8.format(instant));
assertEquals("1915-06-16T02:33:36.000100000Z", formatter9.format(instant));
assertEquals("1915-06-16T02:33:36.0001Z", formatterN1.format(instant));
}
{
Instant instant = Instant.ofEpochSecond(-51721337984L, 1_000_000);
assertEquals("0331-01-07T09:40:16.001Z", formatter.format(instant));
assertEquals("0331-01-07T09:40:16Z", formatter0.format(instant));
assertEquals("0331-01-07T09:40:16.0Z", formatter1.format(instant));
assertEquals("0331-01-07T09:40:16.00Z", formatter2.format(instant));
assertEquals("0331-01-07T09:40:16.001Z", formatter3.format(instant));
assertEquals("0331-01-07T09:40:16.0010Z", formatter4.format(instant));
assertEquals("0331-01-07T09:40:16.00100Z", formatter5.format(instant));
assertEquals("0331-01-07T09:40:16.001000Z", formatter6.format(instant));
assertEquals("0331-01-07T09:40:16.0010000Z", formatter7.format(instant));
assertEquals("0331-01-07T09:40:16.00100000Z", formatter8.format(instant));
assertEquals("0331-01-07T09:40:16.001000000Z", formatter9.format(instant));
assertEquals("0331-01-07T09:40:16.001Z", formatterN1.format(instant));
}
{
Instant instant = Instant.ofEpochSecond(11337984L, 100_000_000);
assertEquals("1970-05-12T05:26:24.100Z", formatter.format(instant));
assertEquals("1970-05-12T05:26:24Z", formatter0.format(instant));
assertEquals("1970-05-12T05:26:24.1Z", formatter1.format(instant));
assertEquals("1970-05-12T05:26:24.10Z", formatter2.format(instant));
assertEquals("1970-05-12T05:26:24.100Z", formatter3.format(instant));
assertEquals("1970-05-12T05:26:24.1000Z", formatter4.format(instant));
assertEquals("1970-05-12T05:26:24.10000Z", formatter5.format(instant));
assertEquals("1970-05-12T05:26:24.100000Z", formatter6.format(instant));
assertEquals("1970-05-12T05:26:24.1000000Z", formatter7.format(instant));
assertEquals("1970-05-12T05:26:24.10000000Z", formatter8.format(instant));
assertEquals("1970-05-12T05:26:24.100000000Z", formatter9.format(instant));
assertEquals("1970-05-12T05:26:24.1Z", formatterN1.format(instant));
}
{
Instant instant = Instant.MAX;
assertEquals("+1000000000-12-31T23:59:59.999999999Z", formatter.format(instant));
assertEquals("+1000000000-12-31T23:59:59Z", formatter0.format(instant));
assertEquals("+1000000000-12-31T23:59:59.9Z", formatter1.format(instant));
assertEquals("+1000000000-12-31T23:59:59.99Z", formatter2.format(instant));
assertEquals("+1000000000-12-31T23:59:59.999Z", formatter3.format(instant));
assertEquals("+1000000000-12-31T23:59:59.9999Z", formatter4.format(instant));
assertEquals("+1000000000-12-31T23:59:59.99999Z", formatter5.format(instant));
assertEquals("+1000000000-12-31T23:59:59.999999Z", formatter6.format(instant));
assertEquals("+1000000000-12-31T23:59:59.9999999Z", formatter7.format(instant));
assertEquals("+1000000000-12-31T23:59:59.99999999Z", formatter8.format(instant));
assertEquals("+1000000000-12-31T23:59:59.999999999Z", formatter9.format(instant));
assertEquals("+1000000000-12-31T23:59:59.999999999Z", formatterN1.format(instant));
}
}
//-----------------------------------------------------------------------
@Test(expectedExceptions=IllegalArgumentException.class)
public void test_appendInstant_tooSmall() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* Copyright (c) 2025, Alibaba Group Holding Limited. 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
@ -121,4 +121,11 @@ public class ToStringBench {
bh.consume(localTime.toString());
}
}
}
@Benchmark
public void instantToString(Blackhole bh) {
for (Instant instant : INSTANTS) {
bh.consume(instant.toString());
}
}
}