Skip to content

Commit

Permalink
8317742: ISO Standard Date Format implementation consistency on DateT…
Browse files Browse the repository at this point in the history
…imeFormatter and String.format

Reviewed-by: rriggs, naoto
  • Loading branch information
wenshao authored and naotoj committed Nov 21, 2023
1 parent c4aba87 commit 61d81d6
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 2 deletions.
21 changes: 20 additions & 1 deletion src/java.base/share/classes/java/util/Formatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.chrono.IsoChronology;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQueries;
Expand Down Expand Up @@ -2050,6 +2051,11 @@ private static char getGroupingSeparator(Locale locale) {
return locale == null ? ',' : getDecimalFormatSymbols(locale).getGroupingSeparator();
}

// Use minus sign from cached DecimalFormatSymbols.
private static char getMinusSign(Locale locale) {
return locale == null ? '-' : getDecimalFormatSymbols(locale).getMinusSign();
}

private Appendable a;
private final Locale l;
private IOException lastException;
Expand Down Expand Up @@ -4490,7 +4496,20 @@ private Appendable print(Formatter fmt, StringBuilder sb, TemporalAccessor t, ch
}
case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d)
char sep = '-';
print(fmt, sb, t, DateTime.YEAR_4, l).append(sep);
ChronoField yearField;
if (t.query(TemporalQueries.chronology()) instanceof IsoChronology) {
yearField = ChronoField.YEAR;
} else {
yearField = ChronoField.YEAR_OF_ERA;
}
int year = t.get(yearField);
if (year < 0) {
sb.append(getMinusSign(l));
year = -year;
} else if (year > 9999) {
sb.append('+');
}
sb.append(localizedMagnitude(fmt, null, year, Flags.ZERO_PAD, 4, l)).append(sep);
print(fmt, sb, t, DateTime.MONTH, l).append(sep);
print(fmt, sb, t, DateTime.DAY_OF_MONTH_0, l);
break;
Expand Down
64 changes: 63 additions & 1 deletion test/jdk/java/util/Formatter/BasicDateTime.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2023, 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
Expand Down Expand Up @@ -34,6 +34,14 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormatSymbols;
import java.text.DecimalFormatSymbols;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.time.ZoneOffset;
import java.time.chrono.*;
import java.time.temporal.ChronoField;
import java.util.*;

import static java.util.Calendar.*;
Expand Down Expand Up @@ -450,5 +458,59 @@ public static void test() {
tryCatch("%%%", UnknownFormatConversionException.class);
// perhaps an IllegalFormatArgumentIndexException should be defined?
tryCatch("%<%", IllegalFormatFlagsException.class);

// %tF LocalDate
test("%tF", "2023-01-13", LocalDate.of(2023, 1, 13));
test("%tF", "2023-10-03", LocalDate.of(2023, 10, 3));
test("%tF", "0001-10-03", LocalDate.of(1, 10, 3));
test("%tF", "0012-10-03", LocalDate.of(12, 10, 3));
test("%tF", "0123-10-03", LocalDate.of(123, 10, 3));
test("%tF", "+12345-10-03", LocalDate.of(12345, 10, 3));
test("%tF", "+12345-10-03", LocalDateTime.of(12345, 10, 3, 0, 0, 0));
test("%tF", "+12345-10-03", OffsetDateTime.of(LocalDateTime.of(12345, 10, 3, 0, 0, 0), ZoneOffset.UTC));
test("%tF", "+12345-10-03", ZonedDateTime.of(LocalDateTime.of(12345, 10, 3, 0, 0, 0), ZoneOffset.UTC));
test("%tF", "-0001-10-03", LocalDate.of(-1, 10, 3));
test("%tF", "-0012-10-03", LocalDate.of(-12, 10, 3));
test("%tF", "-0123-10-03", LocalDate.of(-123, 10, 3));
test("%tF", "-1234-10-03", LocalDate.of(-1234, 10, 3));
test("%tF", "-12345-10-03", LocalDate.of(-12345, 10, 3));
test("%tF", "-12345-10-03", LocalDate.of(-12345, 10, 3));
test("%tF", "-12345-10-03", LocalDateTime.of(-12345, 10, 3, 0, 0, 0));
test("%tF", "-12345-10-03", OffsetDateTime.of(LocalDateTime.of(-12345, 10, 3, 0, 0, 0), ZoneOffset.UTC));
test("%tF", "-12345-10-03", ZonedDateTime.of(LocalDateTime.of(-12345, 10, 3, 0, 0, 0), ZoneOffset.UTC));

// check minusSign
int year = 2023, month = 1, dayOfMonth = 13;
String specifier = "%tF";
for (Locale locale : Locale.getAvailableLocales()) {
char minusSign = DecimalFormatSymbols.getInstance(locale).getMinusSign();
String str = new Formatter(new StringBuilder(), locale)
.format(specifier, LocalDate.of(year, month, dayOfMonth))
.toString();
test(locale, specifier, minusSign + str, LocalDate.of(-year, month, dayOfMonth));
}

// ja-JP-u-ca-japanese
ChronoLocalDate jpDate = Chronology
.ofLocale(Locale.forLanguageTag("ja-JP-u-ca-japanese"))
.dateNow();
test(Locale.JAPANESE,
"%tF",
String.format(
"%04d-%02d-%02d",
jpDate.get(ChronoField.YEAR_OF_ERA),
jpDate.get(ChronoField.MONTH_OF_YEAR),
jpDate.get(ChronoField.DAY_OF_MONTH)),
jpDate);

ChronoLocalDate jpDate1 = JapaneseChronology.INSTANCE.dateNow();
test(Locale.JAPANESE,
"%tF",
String.format(
"%04d-%02d-%02d",
jpDate1.get(ChronoField.YEAR_OF_ERA),
jpDate1.get(ChronoField.MONTH_OF_YEAR),
jpDate1.get(ChronoField.DAY_OF_MONTH)),
jpDate1);
}
}

1 comment on commit 61d81d6

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.