Path: blob/master/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java
41159 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.util.TimeZone;28import java.util.concurrent.ConcurrentHashMap;29import java.util.concurrent.ConcurrentMap;3031/**32* <code>CalendarSystem</code> is an abstract class that defines the33* programming interface to deal with calendar date and time.34*35* <p><code>CalendarSystem</code> instances are singletons. For36* example, there exists only one Gregorian calendar instance in the37* Java runtime environment. A singleton instance can be obtained38* calling one of the static factory methods.39*40* <h4>CalendarDate</h4>41*42* <p>For the methods in a <code>CalendarSystem</code> that manipulate43* a <code>CalendarDate</code>, <code>CalendarDate</code>s that have44* been created by the <code>CalendarSystem</code> must be45* specified. Otherwise, the methods throw an exception. This is46* because, for example, a Chinese calendar date can't be understood47* by the Hebrew calendar system.48*49* <h4>Calendar names</h4>50*51* Each calendar system has a unique name to be identified. The Java52* runtime in this release supports the following calendar systems.53*54* <pre>55* Name Calendar System56* ---------------------------------------57* gregorian Gregorian Calendar58* julian Julian Calendar59* japanese Japanese Imperial Calendar60* </pre>61*62* @see CalendarDate63* @author Masayoshi Okutsu64* @since 1.565*/6667public abstract class CalendarSystem {6869/////////////////////// Calendar Factory Methods /////////////////////////7071private static volatile boolean initialized;7273// Map of calendar names and calendar class names74private static ConcurrentMap<String, String> names;7576// Map of calendar names and CalendarSystem instances77private static ConcurrentMap<String,CalendarSystem> calendars;7879private static final String PACKAGE_NAME = "sun.util.calendar.";8081private static final String[] namePairs = {82"gregorian", "Gregorian",83"japanese", "LocalGregorianCalendar",84"julian", "JulianCalendar",85/*86"hebrew", "HebrewCalendar",87"iso8601", "ISOCalendar",88"taiwanese", "LocalGregorianCalendar",89"thaibuddhist", "LocalGregorianCalendar",90*/91};9293private static void initNames() {94ConcurrentMap<String,String> nameMap = new ConcurrentHashMap<>();9596// Associate a calendar name with its class name and the97// calendar class name with its date class name.98StringBuilder clName = new StringBuilder();99for (int i = 0; i < namePairs.length; i += 2) {100clName.setLength(0);101String cl = clName.append(PACKAGE_NAME).append(namePairs[i+1]).toString();102nameMap.put(namePairs[i], cl);103}104synchronized (CalendarSystem.class) {105if (!initialized) {106names = nameMap;107calendars = new ConcurrentHashMap<>();108initialized = true;109}110}111}112113private static final Gregorian GREGORIAN_INSTANCE = new Gregorian();114115/**116* Returns the singleton instance of the <code>Gregorian</code>117* calendar system.118*119* @return the <code>Gregorian</code> instance120*/121public static Gregorian getGregorianCalendar() {122return GREGORIAN_INSTANCE;123}124125/**126* Returns a <code>CalendarSystem</code> specified by the calendar127* name. The calendar name has to be one of the supported calendar128* names.129*130* @param calendarName the calendar name131* @return the <code>CalendarSystem</code> specified by132* <code>calendarName</code>, or null if there is no133* <code>CalendarSystem</code> associated with the given calendar name.134*/135public static CalendarSystem forName(String calendarName) {136if ("gregorian".equals(calendarName)) {137return GREGORIAN_INSTANCE;138}139140if (!initialized) {141initNames();142}143144CalendarSystem cal = calendars.get(calendarName);145if (cal != null) {146return cal;147}148149String className = names.get(calendarName);150if (className == null) {151return null; // Unknown calendar name152}153154if (className.endsWith("LocalGregorianCalendar")) {155// Create the specific kind of local Gregorian calendar system156cal = LocalGregorianCalendar.getLocalGregorianCalendar(calendarName);157} else {158try {159@SuppressWarnings("deprecation")160Object tmp = Class.forName(className).newInstance();161cal = (CalendarSystem) tmp;162} catch (Exception e) {163throw new InternalError(e);164}165}166if (cal == null) {167return null;168}169CalendarSystem cs = calendars.putIfAbsent(calendarName, cal);170return (cs == null) ? cal : cs;171}172173//////////////////////////////// Calendar API //////////////////////////////////174175/**176* Returns the name of this calendar system.177*/178public abstract String getName();179180public abstract CalendarDate getCalendarDate();181182/**183* Calculates calendar fields from the specified number of184* milliseconds since the Epoch, January 1, 1970 00:00:00 UTC185* (Gregorian). This method doesn't check overflow or underflow186* when adjusting the millisecond value (representing UTC) with187* the time zone offsets (i.e., the GMT offset and amount of188* daylight saving).189*190* @param millis the offset value in milliseconds from January 1,191* 1970 00:00:00 UTC (Gregorian).192* @return a <code>CalendarDate</code> instance that contains the193* calculated calendar field values.194*/195public abstract CalendarDate getCalendarDate(long millis);196197public abstract CalendarDate getCalendarDate(long millis, CalendarDate date);198199public abstract CalendarDate getCalendarDate(long millis, TimeZone zone);200201/**202* Constructs a <code>CalendarDate</code> that is specific to this203* calendar system. All calendar fields have their initial204* values. The {@link TimeZone#getDefault() default time zone} is205* set to the instance.206*207* @return a <code>CalendarDate</code> instance that contains the initial208* calendar field values.209*/210public abstract CalendarDate newCalendarDate();211212public abstract CalendarDate newCalendarDate(TimeZone zone);213214/**215* Returns the number of milliseconds since the Epoch, January 1,216* 1970 00:00:00 UTC (Gregorian), represented by the specified217* <code>CalendarDate</code>.218*219* @param date the <code>CalendarDate</code> from which the time220* value is calculated221* @return the number of milliseconds since the Epoch.222*/223public abstract long getTime(CalendarDate date);224225/**226* Returns the length in days of the specified year by227* <code>date</code>. This method does not perform the228* normalization with the specified <code>CalendarDate</code>. The229* <code>CalendarDate</code> must be normalized to get a correct230* value.231*/232public abstract int getYearLength(CalendarDate date);233234/**235* Returns the number of months of the specified year. This method236* does not perform the normalization with the specified237* <code>CalendarDate</code>. The <code>CalendarDate</code> must238* be normalized to get a correct value.239*/240public abstract int getYearLengthInMonths(CalendarDate date);241242/**243* Returns the length in days of the month specified by the calendar244* date. This method does not perform the normalization with the245* specified calendar date. The <code>CalendarDate</code> must246* be normalized to get a correct value.247*248* @param date the date from which the month value is obtained249* @return the number of days in the month250* @exception IllegalArgumentException if the specified calendar date251* doesn't have a valid month value in this calendar system.252*/253public abstract int getMonthLength(CalendarDate date); // no setter254255/**256* Returns the length in days of a week in this calendar257* system. If this calendar system has multiple radix weeks, this258* method returns only one of them.259*/260public abstract int getWeekLength();261262/**263* Returns the <code>Era</code> designated by the era name that264* has to be known to this calendar system. If no Era is265* applicable to this calendar system, null is returned.266*267* @param eraName the name of the era268* @return the <code>Era</code> designated by269* <code>eraName</code>, or <code>null</code> if no Era is270* applicable to this calendar system or the specified era name is271* not known to this calendar system.272*/273public abstract Era getEra(String eraName);274275/**276* Returns valid <code>Era</code>s of this calendar system. The277* return value is sorted in the descendant order. (i.e., the first278* element of the returned array is the oldest era.) If no era is279* applicable to this calendar system, <code>null</code> is returned.280*281* @return an array of valid <code>Era</code>s, or282* <code>null</code> if no era is applicable to this calendar283* system.284*/285public abstract Era[] getEras();286287/**288* @throws IllegalArgumentException if the specified era name is289* unknown to this calendar system.290* @see Era291*/292public abstract void setEra(CalendarDate date, String eraName);293294/**295* Returns a <code>CalendarDate</code> of the n-th day of week296* which is on, after or before the specified date. For example, the297* first Sunday in April 2002 (Gregorian) can be obtained as298* below:299*300* <pre><code>301* Gregorian cal = CalendarSystem.getGregorianCalendar();302* CalendarDate date = cal.newCalendarDate();303* date.setDate(2004, cal.APRIL, 1);304* CalendarDate firstSun = cal.getNthDayOfWeek(1, cal.SUNDAY, date);305* // firstSun represents April 4, 2004.306* </code></pre>307*308* This method returns a new <code>CalendarDate</code> instance309* and doesn't modify the original date.310*311* @param nth specifies the n-th one. A positive number specifies312* <em>on or after</em> the <code>date</code>. A non-positive number313* specifies <em>on or before</em> the <code>date</code>.314* @param dayOfWeek the day of week315* @param date the date316* @return the date of the nth <code>dayOfWeek</code> after317* or before the specified <code>CalendarDate</code>318*/319public abstract CalendarDate getNthDayOfWeek(int nth, int dayOfWeek,320CalendarDate date);321322public abstract CalendarDate setTimeOfDay(CalendarDate date, int timeOfDay);323324/**325* Checks whether the calendar fields specified by <code>date</code>326* represents a valid date and time in this calendar system. If the327* given date is valid, <code>date</code> is marked as <em>normalized</em>.328*329* @param date the <code>CalendarDate</code> to be validated330* @return <code>true</code> if all the calendar fields are consistent,331* otherwise, <code>false</code> is returned.332* @exception NullPointerException if the specified333* <code>date</code> is <code>null</code>334*/335public abstract boolean validate(CalendarDate date);336337/**338* Normalizes calendar fields in the specified339* <code>date</code>. Also all {@link CalendarDate#FIELD_UNDEFINED340* undefined} fields are set to correct values. The actual341* normalization process is calendar system dependent.342*343* @param date the calendar date to be validated344* @return <code>true</code> if all fields have been normalized;345* <code>false</code> otherwise.346* @exception NullPointerException if the specified347* <code>date</code> is <code>null</code>348*/349public abstract boolean normalize(CalendarDate date);350}351352353