mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8202088: Japanese new era implementation
Reviewed-by: scolebourne, rriggs, nishjain, weijun
This commit is contained in:
parent
307f2c4550
commit
ec4b6a477f
21 changed files with 277 additions and 96 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018, 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
|
||||
|
@ -123,14 +123,19 @@ public final class JapaneseEra
|
|||
*/
|
||||
public static final JapaneseEra SHOWA = new JapaneseEra(1, LocalDate.of(1926, 12, 25));
|
||||
/**
|
||||
* The singleton instance for the 'Heisei' era (1989-01-08 - current)
|
||||
* The singleton instance for the 'Heisei' era (1989-01-08 - 2019-04-30)
|
||||
* which has the value 2.
|
||||
*/
|
||||
public static final JapaneseEra HEISEI = new JapaneseEra(2, LocalDate.of(1989, 1, 8));
|
||||
/**
|
||||
* The singleton instance for the 'NewEra' era (2019-05-01 - current)
|
||||
* which has the value 3.
|
||||
*/
|
||||
private static final JapaneseEra NEWERA = new JapaneseEra(3, LocalDate.of(2019, 5, 1));
|
||||
|
||||
// The number of predefined JapaneseEra constants.
|
||||
// There may be a supplemental era defined by the property.
|
||||
private static final int N_ERA_CONSTANTS = HEISEI.getValue() + ERA_OFFSET;
|
||||
private static final int N_ERA_CONSTANTS = NEWERA.getValue() + ERA_OFFSET;
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
|
@ -148,6 +153,7 @@ public final class JapaneseEra
|
|||
KNOWN_ERAS[1] = TAISHO;
|
||||
KNOWN_ERAS[2] = SHOWA;
|
||||
KNOWN_ERAS[3] = HEISEI;
|
||||
KNOWN_ERAS[4] = NEWERA;
|
||||
for (int i = N_ERA_CONSTANTS; i < ERA_CONFIG.length; i++) {
|
||||
CalendarDate date = ERA_CONFIG[i].getSinceDate();
|
||||
LocalDate isoDate = LocalDate.of(date.getYear(), date.getMonth(), date.getDayOfMonth());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2018, 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
|
||||
|
@ -50,6 +50,7 @@ import sun.util.calendar.ZoneInfo;
|
|||
* 2 Taisho 1912-07-30T00:00:00 local time
|
||||
* 3 Showa 1926-12-25T00:00:00 local time
|
||||
* 4 Heisei 1989-01-08T00:00:00 local time
|
||||
* 5 NewEra 2019-05-01T00:00:00 local time
|
||||
* ------------------------------------------------------
|
||||
* }</pre>
|
||||
*
|
||||
|
@ -71,8 +72,10 @@ import sun.util.calendar.ZoneInfo;
|
|||
* </pre>
|
||||
* where
|
||||
* <dl>
|
||||
* <dt>{@code <name>:}<dd>the full name of the new era (non-ASCII characters allowed)
|
||||
* <dt>{@code <abbr>:}<dd>the abbreviation of the new era (non-ASCII characters allowed)
|
||||
* <dt>{@code <name>:}<dd>the full name of the new era (non-ASCII characters allowed,
|
||||
* either in platform's native encoding or in Unicode escape notation, {@code \\uXXXX})
|
||||
* <dt>{@code <abbr>:}<dd>the abbreviation of the new era (non-ASCII characters allowed,
|
||||
* either in platform's native encoding or in Unicode escape notation, {@code \\uXXXX})
|
||||
* <dt>{@code <time['u']>:}<dd>the start time of the new era represented by
|
||||
* milliseconds from 1970-01-01T00:00:00 local time or UTC if {@code 'u'} is
|
||||
* appended to the milliseconds value. (ASCII digits only)
|
||||
|
@ -125,6 +128,11 @@ class JapaneseImperialCalendar extends Calendar {
|
|||
*/
|
||||
public static final int HEISEI = 4;
|
||||
|
||||
/**
|
||||
* The ERA constant designating the NewEra era.
|
||||
*/
|
||||
private static final int NEWERA = 5;
|
||||
|
||||
private static final int EPOCH_OFFSET = 719163; // Fixed date of January 1, 1970 (Gregorian)
|
||||
|
||||
// Useful millisecond constants. Although ONE_DAY and ONE_WEEK can fit
|
||||
|
@ -155,6 +163,9 @@ class JapaneseImperialCalendar extends Calendar {
|
|||
// Fixed date of the first date of each era.
|
||||
private static final long[] sinceFixedDates;
|
||||
|
||||
// The current era
|
||||
private static final int currentEra;
|
||||
|
||||
/*
|
||||
* <pre>
|
||||
* Greatest Least
|
||||
|
@ -251,13 +262,18 @@ class JapaneseImperialCalendar extends Calendar {
|
|||
// eras[BEFORE_MEIJI] and sinceFixedDate[BEFORE_MEIJI] are the
|
||||
// same as Gregorian.
|
||||
int index = BEFORE_MEIJI;
|
||||
int current = index;
|
||||
sinceFixedDates[index] = gcal.getFixedDate(BEFORE_MEIJI_ERA.getSinceDate());
|
||||
eras[index++] = BEFORE_MEIJI_ERA;
|
||||
for (Era e : es) {
|
||||
if(e.getSince(TimeZone.NO_TIMEZONE) < System.currentTimeMillis()) {
|
||||
current = index;
|
||||
}
|
||||
CalendarDate d = e.getSinceDate();
|
||||
sinceFixedDates[index] = gcal.getFixedDate(d);
|
||||
eras[index++] = e;
|
||||
}
|
||||
currentEra = current;
|
||||
|
||||
LEAST_MAX_VALUES[ERA] = MAX_VALUES[ERA] = eras.length - 1;
|
||||
|
||||
|
@ -1743,12 +1759,12 @@ class JapaneseImperialCalendar extends Calendar {
|
|||
}
|
||||
} else if (transitionYear) {
|
||||
if (jdate.getYear() == 1) {
|
||||
// As of Heisei (since Meiji) there's no case
|
||||
// As of NewEra (since Meiji) there's no case
|
||||
// that there are multiple transitions in a
|
||||
// year. Historically there was such
|
||||
// case. There might be such case again in the
|
||||
// future.
|
||||
if (era > HEISEI) {
|
||||
if (era > NEWERA) {
|
||||
CalendarDate pd = eras[era - 1].getSinceDate();
|
||||
if (normalizedYear == pd.getYear()) {
|
||||
d.setMonth(pd.getMonth()).setDayOfMonth(pd.getDayOfMonth());
|
||||
|
@ -1883,7 +1899,7 @@ class JapaneseImperialCalendar extends Calendar {
|
|||
year = isSet(YEAR) ? internalGet(YEAR) : 1;
|
||||
} else {
|
||||
if (isSet(YEAR)) {
|
||||
era = eras.length - 1;
|
||||
era = currentEra;
|
||||
year = internalGet(YEAR);
|
||||
} else {
|
||||
// Equivalent to 1970 (Gregorian)
|
||||
|
@ -2367,7 +2383,7 @@ class JapaneseImperialCalendar extends Calendar {
|
|||
* default ERA is the current era, but a zero (unset) ERA means before Meiji.
|
||||
*/
|
||||
private int internalGetEra() {
|
||||
return isSet(ERA) ? internalGet(ERA) : eras.length - 1;
|
||||
return isSet(ERA) ? internalGet(ERA) : currentEra;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2018, 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
|
||||
|
@ -106,6 +106,7 @@ public class FormatData extends ParallelListResourceBundle {
|
|||
"T",
|
||||
"S",
|
||||
"H",
|
||||
"N", // NewEra
|
||||
};
|
||||
|
||||
// Japanese imperial calendar era strings
|
||||
|
@ -115,6 +116,7 @@ public class FormatData extends ParallelListResourceBundle {
|
|||
"Taisho",
|
||||
"Showa",
|
||||
"Heisei",
|
||||
"NewEra", // NewEra
|
||||
};
|
||||
|
||||
return new Object[][] {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2018, 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
|
||||
|
@ -159,6 +159,7 @@ public class JavaTimeSupplementary extends OpenListResourceBundle {
|
|||
"Taisho",
|
||||
"Showa",
|
||||
"Heisei",
|
||||
"NewEra", // New Era
|
||||
};
|
||||
|
||||
final String[] sharedShortEras = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2018, 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
|
||||
|
@ -48,6 +48,7 @@ import java.util.TimeZone;
|
|||
* Taisho 1912-07-30T00:00:00 local time
|
||||
* Showa 1926-12-25T00:00:00 local time
|
||||
* Heisei 1989-01-08T00:00:00 local time
|
||||
* NewEra 2019-05-01T00:00:00 local time
|
||||
* -----------------------------------------------------------------------
|
||||
* }</pre>
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2018, 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
|
||||
|
@ -27,6 +27,8 @@ package sun.util.calendar;
|
|||
|
||||
import java.security.AccessController;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
|
@ -41,11 +43,12 @@ public class LocalGregorianCalendar extends BaseCalendar {
|
|||
new Era("Taisho", "T", -1812153600000L, true),
|
||||
new Era("Showa", "S", -1357603200000L, true),
|
||||
new Era("Heisei", "H", 600220800000L, true),
|
||||
new Era("NewEra", "N", 1556668800000L, true),
|
||||
};
|
||||
|
||||
private static boolean isValidEra(Era newEra, Era[] eras) {
|
||||
Era last = eras[eras.length - 1];
|
||||
if (last.getSinceDate().getYear() >= newEra.getSinceDate().getYear()) {
|
||||
if (last.getSince(null) >= newEra.getSince(null)) {
|
||||
return false;
|
||||
}
|
||||
// The new era name should be unique. Its abbr may not.
|
||||
|
@ -173,7 +176,7 @@ public class LocalGregorianCalendar extends BaseCalendar {
|
|||
return null;
|
||||
}
|
||||
String key = keyvalue[0].trim();
|
||||
String value = keyvalue[1].trim();
|
||||
String value = convertUnicodeEscape(keyvalue[1].trim());
|
||||
switch (key) {
|
||||
case "name":
|
||||
eraName = value;
|
||||
|
@ -203,6 +206,17 @@ public class LocalGregorianCalendar extends BaseCalendar {
|
|||
return new Era(eraName, abbr, since, localTime);
|
||||
}
|
||||
|
||||
private static String convertUnicodeEscape(String src) {
|
||||
Matcher m = Pattern.compile("\\\\u([0-9a-fA-F]{4})").matcher(src);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (m.find()) {
|
||||
m.appendReplacement(sb,
|
||||
Character.toString((char)Integer.parseUnsignedInt(m.group(1), 16)));
|
||||
}
|
||||
m.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private LocalGregorianCalendar(String name, Era[] eras) {
|
||||
this.name = name;
|
||||
this.eras = eras;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018, 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
|
||||
|
@ -35,8 +35,8 @@ import sun.util.calendar.CalendarSystem;
|
|||
import sun.util.calendar.Era;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.util.spi.CalendarDataProvider
|
||||
* CalendarDataProvider} class for the JRE LocaleProviderAdapter.
|
||||
* Concrete implementation of the {@link java.util.spi.CalendarNameProvider
|
||||
* CalendarNameProvider} class for the JRE LocaleProviderAdapter.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @author Naoto Sato
|
||||
|
@ -77,28 +77,43 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av
|
|||
if (field == DAY_OF_WEEK || field == YEAR) {
|
||||
--value;
|
||||
}
|
||||
if (value < 0 || value > strings.length) {
|
||||
if (value < 0) {
|
||||
return null;
|
||||
} else if (value == strings.length) {
|
||||
} else if (value >= strings.length) {
|
||||
if (field == ERA && "japanese".equals(calendarType)) {
|
||||
// get the supplemental era, if any, specified through
|
||||
// the property "jdk.calendar.japanese.supplemental.era"
|
||||
// which is always the last element.
|
||||
Era[] jeras = CalendarSystem.forName("japanese").getEras();
|
||||
if (jeras.length == value) {
|
||||
Era supEra = jeras[value - 1]; // 0-based index
|
||||
if (javatime) {
|
||||
return getBaseStyle(style) == NARROW_FORMAT ?
|
||||
supEra.getAbbreviation() :
|
||||
supEra.getName();
|
||||
} else {
|
||||
return (style & LONG) != 0 ?
|
||||
supEra.getName() :
|
||||
supEra.getAbbreviation();
|
||||
if (value <= jeras.length) {
|
||||
// Localized era name could not be retrieved from this provider.
|
||||
// This can occur either for NewEra or SupEra.
|
||||
//
|
||||
// If it's CLDR provider, try COMPAT first, which is guaranteed to have
|
||||
// the name for NewEra.
|
||||
if (type == LocaleProviderAdapter.Type.CLDR) {
|
||||
lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
|
||||
key = getResourceKeyFor(LocaleProviderAdapter.Type.JRE,
|
||||
calendarType, field, style, javatime);
|
||||
strings =
|
||||
javatime ? lr.getJavaTimeNames(key) : lr.getCalendarNames(key);
|
||||
}
|
||||
if (strings == null || value >= strings.length) {
|
||||
// Get the default name for SupEra
|
||||
Era supEra = jeras[value - 1]; // 0-based index
|
||||
if (javatime) {
|
||||
return getBaseStyle(style) == NARROW_FORMAT ?
|
||||
supEra.getAbbreviation() :
|
||||
supEra.getName();
|
||||
} else {
|
||||
return (style & LONG) != 0 ?
|
||||
supEra.getName() :
|
||||
supEra.getAbbreviation();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
name = strings[value];
|
||||
// If name is empty in standalone, try its `format' style.
|
||||
|
@ -180,7 +195,7 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av
|
|||
return map;
|
||||
}
|
||||
|
||||
private int getBaseStyle(int style) {
|
||||
private static int getBaseStyle(int style) {
|
||||
return style & ~(SHORT_STANDALONE - SHORT_FORMAT);
|
||||
}
|
||||
|
||||
|
@ -261,6 +276,11 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av
|
|||
}
|
||||
|
||||
private String getResourceKey(String type, int field, int style, boolean javatime) {
|
||||
return getResourceKeyFor(this.type, type, field, style, javatime);
|
||||
}
|
||||
|
||||
private static String getResourceKeyFor(LocaleProviderAdapter.Type adapterType,
|
||||
String type, int field, int style, boolean javatime) {
|
||||
int baseStyle = getBaseStyle(style);
|
||||
boolean isStandalone = (style != baseStyle);
|
||||
|
||||
|
@ -284,7 +304,7 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av
|
|||
// JRE and CLDR use different resource key conventions
|
||||
// due to historical reasons. (JRE DateFormatSymbols.getEras returns
|
||||
// abbreviations while other getShort*() return abbreviations.)
|
||||
if (this.type == LocaleProviderAdapter.Type.JRE) {
|
||||
if (adapterType == LocaleProviderAdapter.Type.JRE) {
|
||||
if (javatime) {
|
||||
if (baseStyle == LONG) {
|
||||
key.append("long.");
|
||||
|
@ -336,7 +356,7 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av
|
|||
return key.length() > 0 ? key.toString() : null;
|
||||
}
|
||||
|
||||
private String toStyleName(int baseStyle) {
|
||||
private static String toStyleName(int baseStyle) {
|
||||
switch (baseStyle) {
|
||||
case SHORT:
|
||||
return "Abbreviations";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue