Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/util/calendar/CalendarSystem.java
38918 views
/*1* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.util.calendar;2627import java.io.File;28import java.io.FileInputStream;29import java.io.IOException;30import java.security.AccessController;31import java.security.PrivilegedActionException;32import java.security.PrivilegedExceptionAction;33import java.util.Properties;34import java.util.TimeZone;35import java.util.concurrent.ConcurrentHashMap;36import java.util.concurrent.ConcurrentMap;3738/**39* <code>CalendarSystem</code> is an abstract class that defines the40* programming interface to deal with calendar date and time.41*42* <p><code>CalendarSystem</code> instances are singletons. For43* example, there exists only one Gregorian calendar instance in the44* Java runtime environment. A singleton instance can be obtained45* calling one of the static factory methods.46*47* <h4>CalendarDate</h4>48*49* <p>For the methods in a <code>CalendarSystem</code> that manipulate50* a <code>CalendarDate</code>, <code>CalendarDate</code>s that have51* been created by the <code>CalendarSystem</code> must be52* specified. Otherwise, the methods throw an exception. This is53* because, for example, a Chinese calendar date can't be understood54* by the Hebrew calendar system.55*56* <h4>Calendar names</h4>57*58* Each calendar system has a unique name to be identified. The Java59* runtime in this release supports the following calendar systems.60*61* <pre>62* Name Calendar System63* ---------------------------------------64* gregorian Gregorian Calendar65* julian Julian Calendar66* japanese Japanese Imperial Calendar67* </pre>68*69* @see CalendarDate70* @author Masayoshi Okutsu71* @since 1.572*/7374public abstract class CalendarSystem {7576/////////////////////// Calendar Factory Methods /////////////////////////7778private volatile static boolean initialized = false;7980// Map of calendar names and calendar class names81private static ConcurrentMap<String, String> names;8283// Map of calendar names and CalendarSystem instances84private static ConcurrentMap<String,CalendarSystem> calendars;8586private static final String PACKAGE_NAME = "sun.util.calendar.";8788private static final String[] namePairs = {89"gregorian", "Gregorian",90"japanese", "LocalGregorianCalendar",91"julian", "JulianCalendar",92/*93"hebrew", "HebrewCalendar",94"iso8601", "ISOCalendar",95"taiwanese", "LocalGregorianCalendar",96"thaibuddhist", "LocalGregorianCalendar",97*/98};99100private static void initNames() {101ConcurrentMap<String,String> nameMap = new ConcurrentHashMap<>();102103// Associate a calendar name with its class name and the104// calendar class name with its date class name.105StringBuilder clName = new StringBuilder();106for (int i = 0; i < namePairs.length; i += 2) {107clName.setLength(0);108String cl = clName.append(PACKAGE_NAME).append(namePairs[i+1]).toString();109nameMap.put(namePairs[i], cl);110}111synchronized (CalendarSystem.class) {112if (!initialized) {113names = nameMap;114calendars = new ConcurrentHashMap<>();115initialized = true;116}117}118}119120private final static Gregorian GREGORIAN_INSTANCE = new Gregorian();121122/**123* Returns the singleton instance of the <code>Gregorian</code>124* calendar system.125*126* @return the <code>Gregorian</code> instance127*/128public static Gregorian getGregorianCalendar() {129return GREGORIAN_INSTANCE;130}131132/**133* Returns a <code>CalendarSystem</code> specified by the calendar134* name. The calendar name has to be one of the supported calendar135* names.136*137* @param calendarName the calendar name138* @return the <code>CalendarSystem</code> specified by139* <code>calendarName</code>, or null if there is no140* <code>CalendarSystem</code> associated with the given calendar name.141*/142public static CalendarSystem forName(String calendarName) {143if ("gregorian".equals(calendarName)) {144return GREGORIAN_INSTANCE;145}146147if (!initialized) {148initNames();149}150151CalendarSystem cal = calendars.get(calendarName);152if (cal != null) {153return cal;154}155156String className = names.get(calendarName);157if (className == null) {158return null; // Unknown calendar name159}160161if (className.endsWith("LocalGregorianCalendar")) {162// Create the specific kind of local Gregorian calendar system163cal = LocalGregorianCalendar.getLocalGregorianCalendar(calendarName);164} else {165try {166Class<?> cl = Class.forName(className);167cal = (CalendarSystem) cl.newInstance();168} catch (Exception e) {169throw new InternalError(e);170}171}172if (cal == null) {173return null;174}175CalendarSystem cs = calendars.putIfAbsent(calendarName, cal);176return (cs == null) ? cal : cs;177}178179/**180* Returns a {@link Properties} loaded from lib/calendars.properties.181*182* @return a {@link Properties} loaded from lib/calendars.properties183* @throws IOException if an error occurred when reading from the input stream184* @throws IllegalArgumentException if the input stream contains any malformed185* Unicode escape sequences186*/187public static Properties getCalendarProperties() throws IOException {188Properties calendarProps = null;189try {190String homeDir = AccessController.doPrivileged(191new sun.security.action.GetPropertyAction("java.home"));192final String fname = homeDir + File.separator + "lib" + File.separator193+ "calendars.properties";194calendarProps = AccessController.doPrivileged(new PrivilegedExceptionAction<Properties>() {195@Override196public Properties run() throws IOException {197Properties props = new Properties();198try (FileInputStream fis = new FileInputStream(fname)) {199props.load(fis);200}201return props;202}203});204} catch (PrivilegedActionException e) {205Throwable cause = e.getCause();206if (cause instanceof IOException) {207throw (IOException) cause;208} else if (cause instanceof IllegalArgumentException) {209throw (IllegalArgumentException) cause;210}211// Should not happen212throw new InternalError(cause);213}214return calendarProps;215}216217//////////////////////////////// Calendar API //////////////////////////////////218219/**220* Returns the name of this calendar system.221*/222public abstract String getName();223224public abstract CalendarDate getCalendarDate();225226/**227* Calculates calendar fields from the specified number of228* milliseconds since the Epoch, January 1, 1970 00:00:00 UTC229* (Gregorian). This method doesn't check overflow or underflow230* when adjusting the millisecond value (representing UTC) with231* the time zone offsets (i.e., the GMT offset and amount of232* daylight saving).233*234* @param millis the offset value in milliseconds from January 1,235* 1970 00:00:00 UTC (Gregorian).236* @return a <code>CalendarDate</code> instance that contains the237* calculated calendar field values.238*/239public abstract CalendarDate getCalendarDate(long millis);240241public abstract CalendarDate getCalendarDate(long millis, CalendarDate date);242243public abstract CalendarDate getCalendarDate(long millis, TimeZone zone);244245/**246* Constructs a <code>CalendarDate</code> that is specific to this247* calendar system. All calendar fields have their initial248* values. The {@link TimeZone#getDefault() default time zone} is249* set to the instance.250*251* @return a <code>CalendarDate</code> instance that contains the initial252* calendar field values.253*/254public abstract CalendarDate newCalendarDate();255256public abstract CalendarDate newCalendarDate(TimeZone zone);257258/**259* Returns the number of milliseconds since the Epoch, January 1,260* 1970 00:00:00 UTC (Gregorian), represented by the specified261* <code>CalendarDate</code>.262*263* @param date the <code>CalendarDate</code> from which the time264* value is calculated265* @return the number of milliseconds since the Epoch.266*/267public abstract long getTime(CalendarDate date);268269/**270* Returns the length in days of the specified year by271* <code>date</code>. This method does not perform the272* normalization with the specified <code>CalendarDate</code>. The273* <code>CalendarDate</code> must be normalized to get a correct274* value.275*/276public abstract int getYearLength(CalendarDate date);277278/**279* Returns the number of months of the specified year. This method280* does not perform the normalization with the specified281* <code>CalendarDate</code>. The <code>CalendarDate</code> must282* be normalized to get a correct value.283*/284public abstract int getYearLengthInMonths(CalendarDate date);285286/**287* Returns the length in days of the month specified by the calendar288* date. This method does not perform the normalization with the289* specified calendar date. The <code>CalendarDate</code> must290* be normalized to get a correct value.291*292* @param date the date from which the month value is obtained293* @return the number of days in the month294* @exception IllegalArgumentException if the specified calendar date295* doesn't have a valid month value in this calendar system.296*/297public abstract int getMonthLength(CalendarDate date); // no setter298299/**300* Returns the length in days of a week in this calendar301* system. If this calendar system has multiple radix weeks, this302* method returns only one of them.303*/304public abstract int getWeekLength();305306/**307* Returns the <code>Era</code> designated by the era name that308* has to be known to this calendar system. If no Era is309* applicable to this calendar system, null is returned.310*311* @param eraName the name of the era312* @return the <code>Era</code> designated by313* <code>eraName</code>, or <code>null</code> if no Era is314* applicable to this calendar system or the specified era name is315* not known to this calendar system.316*/317public abstract Era getEra(String eraName);318319/**320* Returns valid <code>Era</code>s of this calendar system. The321* return value is sorted in the descendant order. (i.e., the first322* element of the returned array is the oldest era.) If no era is323* applicable to this calendar system, <code>null</code> is returned.324*325* @return an array of valid <code>Era</code>s, or326* <code>null</code> if no era is applicable to this calendar327* system.328*/329public abstract Era[] getEras();330331/**332* @throws IllegalArgumentException if the specified era name is333* unknown to this calendar system.334* @see Era335*/336public abstract void setEra(CalendarDate date, String eraName);337338/**339* Returns a <code>CalendarDate</code> of the n-th day of week340* which is on, after or before the specified date. For example, the341* first Sunday in April 2002 (Gregorian) can be obtained as342* below:343*344* <pre><code>345* Gregorian cal = CalendarSystem.getGregorianCalendar();346* CalendarDate date = cal.newCalendarDate();347* date.setDate(2004, cal.APRIL, 1);348* CalendarDate firstSun = cal.getNthDayOfWeek(1, cal.SUNDAY, date);349* // firstSun represents April 4, 2004.350* </code></pre>351*352* This method returns a new <code>CalendarDate</code> instance353* and doesn't modify the original date.354*355* @param nth specifies the n-th one. A positive number specifies356* <em>on or after</em> the <code>date</code>. A non-positive number357* specifies <em>on or before</em> the <code>date</code>.358* @param dayOfWeek the day of week359* @param date the date360* @return the date of the nth <code>dayOfWeek</code> after361* or before the specified <code>CalendarDate</code>362*/363public abstract CalendarDate getNthDayOfWeek(int nth, int dayOfWeek,364CalendarDate date);365366public abstract CalendarDate setTimeOfDay(CalendarDate date, int timeOfDay);367368/**369* Checks whether the calendar fields specified by <code>date</code>370* represents a valid date and time in this calendar system. If the371* given date is valid, <code>date</code> is marked as <em>normalized</em>.372*373* @param date the <code>CalendarDate</code> to be validated374* @return <code>true</code> if all the calendar fields are consistent,375* otherwise, <code>false</code> is returned.376* @exception NullPointerException if the specified377* <code>date</code> is <code>null</code>378*/379public abstract boolean validate(CalendarDate date);380381/**382* Normalizes calendar fields in the specified383* <code>date</code>. Also all {@link CalendarDate#FIELD_UNDEFINED384* undefined} fields are set to correct values. The actual385* normalization process is calendar system dependent.386*387* @param date the calendar date to be validated388* @return <code>true</code> if all fields have been normalized;389* <code>false</code> otherwise.390* @exception NullPointerException if the specified391* <code>date</code> is <code>null</code>392*/393public abstract boolean normalize(CalendarDate date);394}395396397