/*
* Copyright (C) 2014 The Android Open Source Project
* Copyright (c) 2000, 2021, 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
* 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 sun.util.calendar;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* CalendarSystem
is an abstract class that defines the
* programming interface to deal with calendar date and time.
*
*
CalendarSystem
instances are singletons. For
* example, there exists only one Gregorian calendar instance in the
* Java runtime environment. A singleton instance can be obtained
* calling one of the static factory methods.
*
*
For the methods in a CalendarSystem
that manipulate
* a CalendarDate
, CalendarDate
s that have
* been created by the CalendarSystem
must be
* specified. Otherwise, the methods throw an exception. This is
* because, for example, a Chinese calendar date can't be understood
* by the Hebrew calendar system.
*
*
* Name Calendar System * --------------------------------------- * gregorian Gregorian Calendar * julian Julian Calendar * japanese Japanese Imperial Calendar ** * @see CalendarDate * @author Masayoshi Okutsu * @since 1.5 */ public abstract class CalendarSystem { /////////////////////// Calendar Factory Methods ///////////////////////// // BEGIN Android-changed: avoid reflection and lazy initialization for loading calendar classes. /* private static volatile boolean initialized; // Map of calendar names and calendar class names private static ConcurrentMap
Gregorian
* calendar system.
*
* @return the Gregorian
instance
*/
public static Gregorian getGregorianCalendar() {
return GregorianHolder.GREGORIAN_INSTANCE;
}
/**
* Returns a CalendarSystem
specified by the calendar
* name. The calendar name has to be one of the supported calendar
* names.
*
* @param calendarName the calendar name
* @return the CalendarSystem
specified by
* calendarName
, or null if there is no
* CalendarSystem
associated with the given calendar name.
*/
public static CalendarSystem forName(String calendarName) {
if ("gregorian".equals(calendarName)) {
return GregorianHolder.GREGORIAN_INSTANCE;
}
// BEGIN Android-removed: lazy initialization, use classes instead of class names.
/*
if (!initialized) {
initNames();
}
*/
// END Android-removed: lazy initialization, use classes instead of class names.
CalendarSystem cal = calendars.get(calendarName);
if (cal != null) {
return cal;
}
// BEGIN Android-changed: avoid reflection for loading calendar classes.
/*
String className = names.get(calendarName);
if (className == null) {
*/
Class> calendarClass = names.get(calendarName);
if (calendarClass == null) {
// END Android-changed: avoid reflection for loading calendar classes.
return null; // Unknown calendar name
}
// BEGIN Android-changed: avoid reflection for loading calendar classes.
/*
if (className.endsWith("LocalGregorianCalendar")) {
*/
if (calendarClass.isAssignableFrom(LocalGregorianCalendar.class)) {
// END Android-changed: avoid reflection for loading calendar classes.
// Create the specific kind of local Gregorian calendar system
cal = LocalGregorianCalendar.getLocalGregorianCalendar(calendarName);
} else {
try {
// BEGIN Android-changed: avoid reflection for loading calendar classes.
/*
@SuppressWarnings("deprecation")
Object tmp = Class.forName(className).newInstance();
cal = (CalendarSystem) tmp;
*/
cal = (CalendarSystem) calendarClass.newInstance();
// END Android-changed: avoid reflection for loading calendar classes.
} catch (Exception e) {
throw new InternalError(e);
}
}
if (cal == null) {
return null;
}
CalendarSystem cs = calendars.putIfAbsent(calendarName, cal);
return (cs == null) ? cal : cs;
}
// BEGIN Android-added: load calendar Properties from resources.
/**
* Returns a {@link Properties} loaded from lib/calendars.properties.
*
* @return a {@link Properties} loaded from lib/calendars.properties
* @throws IOException if an error occurred when reading from the input stream
* @throws IllegalArgumentException if the input stream contains any malformed
* Unicode escape sequences
*/
public static Properties getCalendarProperties() throws IOException {
Properties calendarProps = new Properties();
try (InputStream is = ClassLoader.getSystemResourceAsStream("calendars.properties")) {
calendarProps.load(is);
}
return calendarProps;
}
// END Android-added: load calendar Properties from resources.
//////////////////////////////// Calendar API //////////////////////////////////
/**
* Returns the name of this calendar system.
*/
public abstract String getName();
public abstract CalendarDate getCalendarDate();
/**
* Calculates calendar fields from the specified number of
* milliseconds since the Epoch, January 1, 1970 00:00:00 UTC
* (Gregorian). This method doesn't check overflow or underflow
* when adjusting the millisecond value (representing UTC) with
* the time zone offsets (i.e., the GMT offset and amount of
* daylight saving).
*
* @param millis the offset value in milliseconds from January 1,
* 1970 00:00:00 UTC (Gregorian).
* @return a CalendarDate
instance that contains the
* calculated calendar field values.
*/
public abstract CalendarDate getCalendarDate(long millis);
public abstract CalendarDate getCalendarDate(long millis, CalendarDate date);
public abstract CalendarDate getCalendarDate(long millis, TimeZone zone);
/**
* Constructs a CalendarDate
that is specific to this
* calendar system. All calendar fields have their initial
* values. The {@link TimeZone#getDefault() default time zone} is
* set to the instance.
*
* @return a CalendarDate
instance that contains the initial
* calendar field values.
*/
public abstract CalendarDate newCalendarDate();
public abstract CalendarDate newCalendarDate(TimeZone zone);
/**
* Returns the number of milliseconds since the Epoch, January 1,
* 1970 00:00:00 UTC (Gregorian), represented by the specified
* CalendarDate
.
*
* @param date the CalendarDate
from which the time
* value is calculated
* @return the number of milliseconds since the Epoch.
*/
public abstract long getTime(CalendarDate date);
/**
* Returns the length in days of the specified year by
* date
. This method does not perform the
* normalization with the specified CalendarDate
. The
* CalendarDate
must be normalized to get a correct
* value.
*/
public abstract int getYearLength(CalendarDate date);
/**
* Returns the number of months of the specified year. This method
* does not perform the normalization with the specified
* CalendarDate
. The CalendarDate
must
* be normalized to get a correct value.
*/
public abstract int getYearLengthInMonths(CalendarDate date);
/**
* Returns the length in days of the month specified by the calendar
* date. This method does not perform the normalization with the
* specified calendar date. The CalendarDate
must
* be normalized to get a correct value.
*
* @param date the date from which the month value is obtained
* @return the number of days in the month
* @exception IllegalArgumentException if the specified calendar date
* doesn't have a valid month value in this calendar system.
*/
public abstract int getMonthLength(CalendarDate date); // no setter
/**
* Returns the length in days of a week in this calendar
* system. If this calendar system has multiple radix weeks, this
* method returns only one of them.
*/
public abstract int getWeekLength();
/**
* Returns the Era
designated by the era name that
* has to be known to this calendar system. If no Era is
* applicable to this calendar system, null is returned.
*
* @param eraName the name of the era
* @return the Era
designated by
* eraName
, or null
if no Era is
* applicable to this calendar system or the specified era name is
* not known to this calendar system.
*/
public abstract Era getEra(String eraName);
/**
* Returns valid Era
s of this calendar system. The
* return value is sorted in the descendant order. (i.e., the first
* element of the returned array is the oldest era.) If no era is
* applicable to this calendar system, null
is returned.
*
* @return an array of valid Era
s, or
* null
if no era is applicable to this calendar
* system.
*/
public abstract Era[] getEras();
/**
* @throws IllegalArgumentException if the specified era name is
* unknown to this calendar system.
* @see Era
*/
public abstract void setEra(CalendarDate date, String eraName);
/**
* Returns a CalendarDate
of the n-th day of week
* which is on, after or before the specified date. For example, the
* first Sunday in April 2002 (Gregorian) can be obtained as
* below:
*
*
* Gregorian cal = CalendarSystem.getGregorianCalendar();
* CalendarDate date = cal.newCalendarDate();
* date.setDate(2004, cal.APRIL, 1);
* CalendarDate firstSun = cal.getNthDayOfWeek(1, cal.SUNDAY, date);
* // firstSun represents April 4, 2004.
*
*
* This method returns a new CalendarDate
instance
* and doesn't modify the original date.
*
* @param nth specifies the n-th one. A positive number specifies
* on or after the date
. A non-positive number
* specifies on or before the date
.
* @param dayOfWeek the day of week
* @param date the date
* @return the date of the nth dayOfWeek
after
* or before the specified CalendarDate
*/
public abstract CalendarDate getNthDayOfWeek(int nth, int dayOfWeek,
CalendarDate date);
public abstract CalendarDate setTimeOfDay(CalendarDate date, int timeOfDay);
/**
* Checks whether the calendar fields specified by date
* represents a valid date and time in this calendar system. If the
* given date is valid, date
is marked as normalized.
*
* @param date the CalendarDate
to be validated
* @return true
if all the calendar fields are consistent,
* otherwise, false
is returned.
* @exception NullPointerException if the specified
* date
is null
*/
public abstract boolean validate(CalendarDate date);
/**
* Normalizes calendar fields in the specified
* date
. Also all {@link CalendarDate#FIELD_UNDEFINED
* undefined} fields are set to correct values. The actual
* normalization process is calendar system dependent.
*
* @param date the calendar date to be validated
* @return true
if all fields have been normalized;
* false
otherwise.
* @exception NullPointerException if the specified
* date
is null
*/
public abstract boolean normalize(CalendarDate date);
}