feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
398
jdkSrc/jdk8/sun/util/calendar/AbstractCalendar.java
Normal file
398
jdkSrc/jdk8/sun/util/calendar/AbstractCalendar.java
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2004, 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.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* The <code>AbstractCalendar</code> class provides a framework for
|
||||
* implementing a concrete calendar system.
|
||||
*
|
||||
* <p><a name="fixed_date"></a><B>Fixed Date</B><br>
|
||||
*
|
||||
* For implementing a concrete calendar system, each calendar must
|
||||
* have the common date numbering, starting from midnight the onset of
|
||||
* Monday, January 1, 1 (Gregorian). It is called a <I>fixed date</I>
|
||||
* in this class. January 1, 1 (Gregorian) is fixed date 1. (See
|
||||
* Nachum Dershowitz and Edward M. Reingold, <I>CALENDRICAL
|
||||
* CALCULATION The Millennium Edition</I>, Section 1.2 for details.)
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public abstract class AbstractCalendar extends CalendarSystem {
|
||||
|
||||
// The constants assume no leap seconds support.
|
||||
static final int SECOND_IN_MILLIS = 1000;
|
||||
static final int MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
|
||||
static final int HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
|
||||
static final int DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
|
||||
|
||||
// The number of days between January 1, 1 and January 1, 1970 (Gregorian)
|
||||
static final int EPOCH_OFFSET = 719163;
|
||||
|
||||
private Era[] eras;
|
||||
|
||||
protected AbstractCalendar() {
|
||||
}
|
||||
|
||||
public Era getEra(String eraName) {
|
||||
if (eras != null) {
|
||||
for (int i = 0; i < eras.length; i++) {
|
||||
if (eras[i].equals(eraName)) {
|
||||
return eras[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Era[] getEras() {
|
||||
Era[] e = null;
|
||||
if (eras != null) {
|
||||
e = new Era[eras.length];
|
||||
System.arraycopy(eras, 0, e, 0, eras.length);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
public void setEra(CalendarDate date, String eraName) {
|
||||
if (eras == null) {
|
||||
return; // should report an error???
|
||||
}
|
||||
for (int i = 0; i < eras.length; i++) {
|
||||
Era e = eras[i];
|
||||
if (e != null && e.getName().equals(eraName)) {
|
||||
date.setEra(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unknown era name: " + eraName);
|
||||
}
|
||||
|
||||
protected void setEras(Era[] eras) {
|
||||
this.eras = eras;
|
||||
}
|
||||
|
||||
public CalendarDate getCalendarDate() {
|
||||
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
|
||||
}
|
||||
|
||||
public CalendarDate getCalendarDate(long millis) {
|
||||
return getCalendarDate(millis, newCalendarDate());
|
||||
}
|
||||
|
||||
public CalendarDate getCalendarDate(long millis, TimeZone zone) {
|
||||
CalendarDate date = newCalendarDate(zone);
|
||||
return getCalendarDate(millis, date);
|
||||
}
|
||||
|
||||
public CalendarDate getCalendarDate(long millis, CalendarDate date) {
|
||||
int ms = 0; // time of day
|
||||
int zoneOffset = 0;
|
||||
int saving = 0;
|
||||
long days = 0; // fixed date
|
||||
|
||||
// adjust to local time if `date' has time zone.
|
||||
TimeZone zi = date.getZone();
|
||||
if (zi != null) {
|
||||
int[] offsets = new int[2];
|
||||
if (zi instanceof ZoneInfo) {
|
||||
zoneOffset = ((ZoneInfo)zi).getOffsets(millis, offsets);
|
||||
} else {
|
||||
zoneOffset = zi.getOffset(millis);
|
||||
offsets[0] = zi.getRawOffset();
|
||||
offsets[1] = zoneOffset - offsets[0];
|
||||
}
|
||||
|
||||
// We need to calculate the given millis and time zone
|
||||
// offset separately for java.util.GregorianCalendar
|
||||
// compatibility. (i.e., millis + zoneOffset could cause
|
||||
// overflow or underflow, which must be avoided.) Usually
|
||||
// days should be 0 and ms is in the range of -13:00 to
|
||||
// +14:00. However, we need to deal with extreme cases.
|
||||
days = zoneOffset / DAY_IN_MILLIS;
|
||||
ms = zoneOffset % DAY_IN_MILLIS;
|
||||
saving = offsets[1];
|
||||
}
|
||||
date.setZoneOffset(zoneOffset);
|
||||
date.setDaylightSaving(saving);
|
||||
|
||||
days += millis / DAY_IN_MILLIS;
|
||||
ms += (int) (millis % DAY_IN_MILLIS);
|
||||
if (ms >= DAY_IN_MILLIS) {
|
||||
// at most ms is (DAY_IN_MILLIS - 1) * 2.
|
||||
ms -= DAY_IN_MILLIS;
|
||||
++days;
|
||||
} else {
|
||||
// at most ms is (1 - DAY_IN_MILLIS) * 2. Adding one
|
||||
// DAY_IN_MILLIS results in still negative.
|
||||
while (ms < 0) {
|
||||
ms += DAY_IN_MILLIS;
|
||||
--days;
|
||||
}
|
||||
}
|
||||
|
||||
// convert to fixed date (offset from Jan. 1, 1 (Gregorian))
|
||||
days += EPOCH_OFFSET;
|
||||
|
||||
// calculate date fields from the fixed date
|
||||
getCalendarDateFromFixedDate(date, days);
|
||||
|
||||
// calculate time fields from the time of day
|
||||
setTimeOfDay(date, ms);
|
||||
date.setLeapYear(isLeapYear(date));
|
||||
date.setNormalized(true);
|
||||
return date;
|
||||
}
|
||||
|
||||
public long getTime(CalendarDate date) {
|
||||
long gd = getFixedDate(date);
|
||||
long ms = (gd - EPOCH_OFFSET) * DAY_IN_MILLIS + getTimeOfDay(date);
|
||||
int zoneOffset = 0;
|
||||
TimeZone zi = date.getZone();
|
||||
if (zi != null) {
|
||||
if (date.isNormalized()) {
|
||||
return ms - date.getZoneOffset();
|
||||
}
|
||||
// adjust time zone and daylight saving
|
||||
int[] offsets = new int[2];
|
||||
if (date.isStandardTime()) {
|
||||
// 1) 2:30am during starting-DST transition is
|
||||
// intrepreted as 2:30am ST
|
||||
// 2) 5:00pm during DST is still interpreted as 5:00pm ST
|
||||
// 3) 1:30am during ending-DST transition is interpreted
|
||||
// as 1:30am ST (after transition)
|
||||
if (zi instanceof ZoneInfo) {
|
||||
((ZoneInfo)zi).getOffsetsByStandard(ms, offsets);
|
||||
zoneOffset = offsets[0];
|
||||
} else {
|
||||
zoneOffset = zi.getOffset(ms - zi.getRawOffset());
|
||||
}
|
||||
} else {
|
||||
// 1) 2:30am during starting-DST transition is
|
||||
// intrepreted as 3:30am DT
|
||||
// 2) 5:00pm during DST is intrepreted as 5:00pm DT
|
||||
// 3) 1:30am during ending-DST transition is interpreted
|
||||
// as 1:30am DT/0:30am ST (before transition)
|
||||
if (zi instanceof ZoneInfo) {
|
||||
zoneOffset = ((ZoneInfo)zi).getOffsetsByWall(ms, offsets);
|
||||
} else {
|
||||
zoneOffset = zi.getOffset(ms - zi.getRawOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
ms -= zoneOffset;
|
||||
getCalendarDate(ms, date);
|
||||
return ms;
|
||||
}
|
||||
|
||||
protected long getTimeOfDay(CalendarDate date) {
|
||||
long fraction = date.getTimeOfDay();
|
||||
if (fraction != CalendarDate.TIME_UNDEFINED) {
|
||||
return fraction;
|
||||
}
|
||||
fraction = getTimeOfDayValue(date);
|
||||
date.setTimeOfDay(fraction);
|
||||
return fraction;
|
||||
}
|
||||
|
||||
public long getTimeOfDayValue(CalendarDate date) {
|
||||
long fraction = date.getHours();
|
||||
fraction *= 60;
|
||||
fraction += date.getMinutes();
|
||||
fraction *= 60;
|
||||
fraction += date.getSeconds();
|
||||
fraction *= 1000;
|
||||
fraction += date.getMillis();
|
||||
return fraction;
|
||||
}
|
||||
|
||||
public CalendarDate setTimeOfDay(CalendarDate cdate, int fraction) {
|
||||
if (fraction < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
boolean normalizedState = cdate.isNormalized();
|
||||
int time = fraction;
|
||||
int hours = time / HOUR_IN_MILLIS;
|
||||
time %= HOUR_IN_MILLIS;
|
||||
int minutes = time / MINUTE_IN_MILLIS;
|
||||
time %= MINUTE_IN_MILLIS;
|
||||
int seconds = time / SECOND_IN_MILLIS;
|
||||
time %= SECOND_IN_MILLIS;
|
||||
cdate.setHours(hours);
|
||||
cdate.setMinutes(minutes);
|
||||
cdate.setSeconds(seconds);
|
||||
cdate.setMillis(time);
|
||||
cdate.setTimeOfDay(fraction);
|
||||
if (hours < 24 && normalizedState) {
|
||||
// If this time of day setting doesn't affect the date,
|
||||
// then restore the normalized state.
|
||||
cdate.setNormalized(normalizedState);
|
||||
}
|
||||
return cdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 7 in this default implementation.
|
||||
*
|
||||
* @return 7
|
||||
*/
|
||||
public int getWeekLength() {
|
||||
return 7;
|
||||
}
|
||||
|
||||
protected abstract boolean isLeapYear(CalendarDate date);
|
||||
|
||||
public CalendarDate getNthDayOfWeek(int nth, int dayOfWeek, CalendarDate date) {
|
||||
CalendarDate ndate = (CalendarDate) date.clone();
|
||||
normalize(ndate);
|
||||
long fd = getFixedDate(ndate);
|
||||
long nfd;
|
||||
if (nth > 0) {
|
||||
nfd = 7 * nth + getDayOfWeekDateBefore(fd, dayOfWeek);
|
||||
} else {
|
||||
nfd = 7 * nth + getDayOfWeekDateAfter(fd, dayOfWeek);
|
||||
}
|
||||
getCalendarDateFromFixedDate(ndate, nfd);
|
||||
return ndate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a date of the given day of week before the given fixed
|
||||
* date.
|
||||
*
|
||||
* @param fixedDate the fixed date
|
||||
* @param dayOfWeek the day of week
|
||||
* @return the calculated date
|
||||
*/
|
||||
static long getDayOfWeekDateBefore(long fixedDate, int dayOfWeek) {
|
||||
return getDayOfWeekDateOnOrBefore(fixedDate - 1, dayOfWeek);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a date of the given day of week that is closest to and
|
||||
* after the given fixed date.
|
||||
*
|
||||
* @param fixedDate the fixed date
|
||||
* @param dayOfWeek the day of week
|
||||
* @return the calculated date
|
||||
*/
|
||||
static long getDayOfWeekDateAfter(long fixedDate, int dayOfWeek) {
|
||||
return getDayOfWeekDateOnOrBefore(fixedDate + 7, dayOfWeek);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a date of the given day of week on or before the given fixed
|
||||
* date.
|
||||
*
|
||||
* @param fixedDate the fixed date
|
||||
* @param dayOfWeek the day of week
|
||||
* @return the calculated date
|
||||
*/
|
||||
// public for java.util.GregorianCalendar
|
||||
public static long getDayOfWeekDateOnOrBefore(long fixedDate, int dayOfWeek) {
|
||||
long fd = fixedDate - (dayOfWeek - 1);
|
||||
if (fd >= 0) {
|
||||
return fixedDate - (fd % 7);
|
||||
}
|
||||
return fixedDate - CalendarUtils.mod(fd, 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fixed date calculated with the specified calendar
|
||||
* date. If the specified date is not normalized, its date fields
|
||||
* are normalized.
|
||||
*
|
||||
* @param date a <code>CalendarDate</code> with which the fixed
|
||||
* date is calculated
|
||||
* @return the calculated fixed date
|
||||
* @see AbstractCalendar.html#fixed_date
|
||||
*/
|
||||
protected abstract long getFixedDate(CalendarDate date);
|
||||
|
||||
/**
|
||||
* Calculates calendar fields from the specified fixed date. This
|
||||
* method stores the calculated calendar field values in the specified
|
||||
* <code>CalendarDate</code>.
|
||||
*
|
||||
* @param date a <code>CalendarDate</code> to stored the
|
||||
* calculated calendar fields.
|
||||
* @param fixedDate a fixed date to calculate calendar fields
|
||||
* @see AbstractCalendar.html#fixed_date
|
||||
*/
|
||||
protected abstract void getCalendarDateFromFixedDate(CalendarDate date,
|
||||
long fixedDate);
|
||||
|
||||
public boolean validateTime(CalendarDate date) {
|
||||
int t = date.getHours();
|
||||
if (t < 0 || t >= 24) {
|
||||
return false;
|
||||
}
|
||||
t = date.getMinutes();
|
||||
if (t < 0 || t >= 60) {
|
||||
return false;
|
||||
}
|
||||
t = date.getSeconds();
|
||||
// TODO: Leap second support.
|
||||
if (t < 0 || t >= 60) {
|
||||
return false;
|
||||
}
|
||||
t = date.getMillis();
|
||||
if (t < 0 || t >= 1000) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int normalizeTime(CalendarDate date) {
|
||||
long fraction = getTimeOfDay(date);
|
||||
long days = 0;
|
||||
|
||||
if (fraction >= DAY_IN_MILLIS) {
|
||||
days = fraction / DAY_IN_MILLIS;
|
||||
fraction %= DAY_IN_MILLIS;
|
||||
} else if (fraction < 0) {
|
||||
days = CalendarUtils.floorDivide(fraction, DAY_IN_MILLIS);
|
||||
if (days != 0) {
|
||||
fraction -= DAY_IN_MILLIS * days; // mod(fraction, DAY_IN_MILLIS)
|
||||
}
|
||||
}
|
||||
if (days != 0) {
|
||||
date.setTimeOfDay(fraction);
|
||||
}
|
||||
date.setMillis((int)(fraction % 1000));
|
||||
fraction /= 1000;
|
||||
date.setSeconds((int)(fraction % 60));
|
||||
fraction /= 60;
|
||||
date.setMinutes((int)(fraction % 60));
|
||||
date.setHours((int)(fraction / 60));
|
||||
return (int)days;
|
||||
}
|
||||
}
|
||||
537
jdkSrc/jdk8/sun/util/calendar/BaseCalendar.java
Normal file
537
jdkSrc/jdk8/sun/util/calendar/BaseCalendar.java
Normal file
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, 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.util.TimeZone;
|
||||
|
||||
/**
|
||||
* The <code>BaseCalendar</code> provides basic calendar calculation
|
||||
* functions to support the Julian, Gregorian, and Gregorian-based
|
||||
* calendar systems.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public abstract class BaseCalendar extends AbstractCalendar {
|
||||
|
||||
public static final int JANUARY = 1;
|
||||
public static final int FEBRUARY = 2;
|
||||
public static final int MARCH = 3;
|
||||
public static final int APRIL = 4;
|
||||
public static final int MAY = 5;
|
||||
public static final int JUNE = 6;
|
||||
public static final int JULY = 7;
|
||||
public static final int AUGUST = 8;
|
||||
public static final int SEPTEMBER = 9;
|
||||
public static final int OCTOBER = 10;
|
||||
public static final int NOVEMBER = 11;
|
||||
public static final int DECEMBER = 12;
|
||||
|
||||
// day of week constants
|
||||
public static final int SUNDAY = 1;
|
||||
public static final int MONDAY = 2;
|
||||
public static final int TUESDAY = 3;
|
||||
public static final int WEDNESDAY = 4;
|
||||
public static final int THURSDAY = 5;
|
||||
public static final int FRIDAY = 6;
|
||||
public static final int SATURDAY = 7;
|
||||
|
||||
// The base Gregorian year of FIXED_DATES[]
|
||||
private static final int BASE_YEAR = 1970;
|
||||
|
||||
// Pre-calculated fixed dates of January 1 from BASE_YEAR
|
||||
// (Gregorian). This table covers all the years that can be
|
||||
// supported by the POSIX time_t (32-bit) after the Epoch. Note
|
||||
// that the data type is int[].
|
||||
private static final int[] FIXED_DATES = {
|
||||
719163, // 1970
|
||||
719528, // 1971
|
||||
719893, // 1972
|
||||
720259, // 1973
|
||||
720624, // 1974
|
||||
720989, // 1975
|
||||
721354, // 1976
|
||||
721720, // 1977
|
||||
722085, // 1978
|
||||
722450, // 1979
|
||||
722815, // 1980
|
||||
723181, // 1981
|
||||
723546, // 1982
|
||||
723911, // 1983
|
||||
724276, // 1984
|
||||
724642, // 1985
|
||||
725007, // 1986
|
||||
725372, // 1987
|
||||
725737, // 1988
|
||||
726103, // 1989
|
||||
726468, // 1990
|
||||
726833, // 1991
|
||||
727198, // 1992
|
||||
727564, // 1993
|
||||
727929, // 1994
|
||||
728294, // 1995
|
||||
728659, // 1996
|
||||
729025, // 1997
|
||||
729390, // 1998
|
||||
729755, // 1999
|
||||
730120, // 2000
|
||||
730486, // 2001
|
||||
730851, // 2002
|
||||
731216, // 2003
|
||||
731581, // 2004
|
||||
731947, // 2005
|
||||
732312, // 2006
|
||||
732677, // 2007
|
||||
733042, // 2008
|
||||
733408, // 2009
|
||||
733773, // 2010
|
||||
734138, // 2011
|
||||
734503, // 2012
|
||||
734869, // 2013
|
||||
735234, // 2014
|
||||
735599, // 2015
|
||||
735964, // 2016
|
||||
736330, // 2017
|
||||
736695, // 2018
|
||||
737060, // 2019
|
||||
737425, // 2020
|
||||
737791, // 2021
|
||||
738156, // 2022
|
||||
738521, // 2023
|
||||
738886, // 2024
|
||||
739252, // 2025
|
||||
739617, // 2026
|
||||
739982, // 2027
|
||||
740347, // 2028
|
||||
740713, // 2029
|
||||
741078, // 2030
|
||||
741443, // 2031
|
||||
741808, // 2032
|
||||
742174, // 2033
|
||||
742539, // 2034
|
||||
742904, // 2035
|
||||
743269, // 2036
|
||||
743635, // 2037
|
||||
744000, // 2038
|
||||
744365, // 2039
|
||||
};
|
||||
|
||||
public abstract static class Date extends CalendarDate {
|
||||
protected Date() {
|
||||
super();
|
||||
}
|
||||
protected Date(TimeZone zone) {
|
||||
super(zone);
|
||||
}
|
||||
|
||||
public Date setNormalizedDate(int normalizedYear, int month, int dayOfMonth) {
|
||||
setNormalizedYear(normalizedYear);
|
||||
setMonth(month).setDayOfMonth(dayOfMonth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract int getNormalizedYear();
|
||||
|
||||
public abstract void setNormalizedYear(int normalizedYear);
|
||||
|
||||
// Cache for the fixed date of January 1 and year length of the
|
||||
// cachedYear. A simple benchmark showed 7% performance
|
||||
// improvement with >90% cache hit. The initial values are for Gregorian.
|
||||
int cachedYear = 2004;
|
||||
long cachedFixedDateJan1 = 731581L;
|
||||
long cachedFixedDateNextJan1 = cachedFixedDateJan1 + 366;
|
||||
|
||||
protected final boolean hit(int year) {
|
||||
return year == cachedYear;
|
||||
}
|
||||
|
||||
protected final boolean hit(long fixedDate) {
|
||||
return (fixedDate >= cachedFixedDateJan1 &&
|
||||
fixedDate < cachedFixedDateNextJan1);
|
||||
}
|
||||
protected int getCachedYear() {
|
||||
return cachedYear;
|
||||
}
|
||||
|
||||
protected long getCachedJan1() {
|
||||
return cachedFixedDateJan1;
|
||||
}
|
||||
|
||||
protected void setCache(int year, long jan1, int len) {
|
||||
cachedYear = year;
|
||||
cachedFixedDateJan1 = jan1;
|
||||
cachedFixedDateNextJan1 = jan1 + len;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validate(CalendarDate date) {
|
||||
Date bdate = (Date) date;
|
||||
if (bdate.isNormalized()) {
|
||||
return true;
|
||||
}
|
||||
int month = bdate.getMonth();
|
||||
if (month < JANUARY || month > DECEMBER) {
|
||||
return false;
|
||||
}
|
||||
int d = bdate.getDayOfMonth();
|
||||
if (d <= 0 || d > getMonthLength(bdate.getNormalizedYear(), month)) {
|
||||
return false;
|
||||
}
|
||||
int dow = bdate.getDayOfWeek();
|
||||
if (dow != Date.FIELD_UNDEFINED && dow != getDayOfWeek(bdate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validateTime(date)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bdate.setNormalized(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean normalize(CalendarDate date) {
|
||||
if (date.isNormalized()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Date bdate = (Date) date;
|
||||
TimeZone zi = bdate.getZone();
|
||||
|
||||
// If the date has a time zone, then we need to recalculate
|
||||
// the calendar fields. Let getTime() do it.
|
||||
if (zi != null) {
|
||||
getTime(date);
|
||||
return true;
|
||||
}
|
||||
|
||||
int days = normalizeTime(bdate);
|
||||
normalizeMonth(bdate);
|
||||
long d = (long)bdate.getDayOfMonth() + days;
|
||||
int m = bdate.getMonth();
|
||||
int y = bdate.getNormalizedYear();
|
||||
int ml = getMonthLength(y, m);
|
||||
|
||||
if (!(d > 0 && d <= ml)) {
|
||||
if (d <= 0 && d > -28) {
|
||||
ml = getMonthLength(y, --m);
|
||||
d += ml;
|
||||
bdate.setDayOfMonth((int) d);
|
||||
if (m == 0) {
|
||||
m = DECEMBER;
|
||||
bdate.setNormalizedYear(y - 1);
|
||||
}
|
||||
bdate.setMonth(m);
|
||||
} else if (d > ml && d < (ml + 28)) {
|
||||
d -= ml;
|
||||
++m;
|
||||
bdate.setDayOfMonth((int)d);
|
||||
if (m > DECEMBER) {
|
||||
bdate.setNormalizedYear(y + 1);
|
||||
m = JANUARY;
|
||||
}
|
||||
bdate.setMonth(m);
|
||||
} else {
|
||||
long fixedDate = d + getFixedDate(y, m, 1, bdate) - 1L;
|
||||
getCalendarDateFromFixedDate(bdate, fixedDate);
|
||||
}
|
||||
} else {
|
||||
bdate.setDayOfWeek(getDayOfWeek(bdate));
|
||||
}
|
||||
date.setLeapYear(isLeapYear(bdate.getNormalizedYear()));
|
||||
date.setZoneOffset(0);
|
||||
date.setDaylightSaving(0);
|
||||
bdate.setNormalized(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void normalizeMonth(CalendarDate date) {
|
||||
Date bdate = (Date) date;
|
||||
int year = bdate.getNormalizedYear();
|
||||
long month = bdate.getMonth();
|
||||
if (month <= 0) {
|
||||
long xm = 1L - month;
|
||||
year -= (int)((xm / 12) + 1);
|
||||
month = 13 - (xm % 12);
|
||||
bdate.setNormalizedYear(year);
|
||||
bdate.setMonth((int) month);
|
||||
} else if (month > DECEMBER) {
|
||||
year += (int)((month - 1) / 12);
|
||||
month = ((month - 1)) % 12 + 1;
|
||||
bdate.setNormalizedYear(year);
|
||||
bdate.setMonth((int) month);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 366 if the specified date is in a leap year, or 365
|
||||
* otherwise This method does not perform the normalization with
|
||||
* the specified <code>CalendarDate</code>. The
|
||||
* <code>CalendarDate</code> must be normalized to get a correct
|
||||
* value.
|
||||
*
|
||||
* @param a <code>CalendarDate</code>
|
||||
* @return a year length in days
|
||||
* @throws ClassCastException if the specified date is not a
|
||||
* {@link BaseCalendar.Date}
|
||||
*/
|
||||
public int getYearLength(CalendarDate date) {
|
||||
return isLeapYear(((Date)date).getNormalizedYear()) ? 366 : 365;
|
||||
}
|
||||
|
||||
public int getYearLengthInMonths(CalendarDate date) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
static final int[] DAYS_IN_MONTH
|
||||
// 12 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
= { 31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
static final int[] ACCUMULATED_DAYS_IN_MONTH
|
||||
// 12/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 9/1 10/1 11/1 12/1
|
||||
= { -30, 0, 31, 59, 90,120,151,181,212,243, 273, 304, 334};
|
||||
|
||||
static final int[] ACCUMULATED_DAYS_IN_MONTH_LEAP
|
||||
// 12/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 9/1 10/1 11/1 12/1
|
||||
= { -30, 0, 31, 59+1, 90+1,120+1,151+1,181+1,212+1,243+1, 273+1, 304+1, 334+1};
|
||||
|
||||
public int getMonthLength(CalendarDate date) {
|
||||
Date gdate = (Date) date;
|
||||
int month = gdate.getMonth();
|
||||
if (month < JANUARY || month > DECEMBER) {
|
||||
throw new IllegalArgumentException("Illegal month value: " + month);
|
||||
}
|
||||
return getMonthLength(gdate.getNormalizedYear(), month);
|
||||
}
|
||||
|
||||
// accepts 0 (December in the previous year) to 12.
|
||||
private int getMonthLength(int year, int month) {
|
||||
int days = DAYS_IN_MONTH[month];
|
||||
if (month == FEBRUARY && isLeapYear(year)) {
|
||||
days++;
|
||||
}
|
||||
return days;
|
||||
}
|
||||
|
||||
public long getDayOfYear(CalendarDate date) {
|
||||
return getDayOfYear(((Date)date).getNormalizedYear(),
|
||||
date.getMonth(),
|
||||
date.getDayOfMonth());
|
||||
}
|
||||
|
||||
final long getDayOfYear(int year, int month, int dayOfMonth) {
|
||||
return (long) dayOfMonth
|
||||
+ (isLeapYear(year) ?
|
||||
ACCUMULATED_DAYS_IN_MONTH_LEAP[month] : ACCUMULATED_DAYS_IN_MONTH[month]);
|
||||
}
|
||||
|
||||
// protected
|
||||
public long getFixedDate(CalendarDate date) {
|
||||
if (!date.isNormalized()) {
|
||||
normalizeMonth(date);
|
||||
}
|
||||
return getFixedDate(((Date)date).getNormalizedYear(),
|
||||
date.getMonth(),
|
||||
date.getDayOfMonth(),
|
||||
(BaseCalendar.Date) date);
|
||||
}
|
||||
|
||||
// public for java.util.GregorianCalendar
|
||||
public long getFixedDate(int year, int month, int dayOfMonth, BaseCalendar.Date cache) {
|
||||
boolean isJan1 = month == JANUARY && dayOfMonth == 1;
|
||||
|
||||
// Look up the one year cache
|
||||
if (cache != null && cache.hit(year)) {
|
||||
if (isJan1) {
|
||||
return cache.getCachedJan1();
|
||||
}
|
||||
return cache.getCachedJan1() + getDayOfYear(year, month, dayOfMonth) - 1;
|
||||
}
|
||||
|
||||
// Look up the pre-calculated fixed date table
|
||||
int n = year - BASE_YEAR;
|
||||
if (n >= 0 && n < FIXED_DATES.length) {
|
||||
long jan1 = FIXED_DATES[n];
|
||||
if (cache != null) {
|
||||
cache.setCache(year, jan1, isLeapYear(year) ? 366 : 365);
|
||||
}
|
||||
return isJan1 ? jan1 : jan1 + getDayOfYear(year, month, dayOfMonth) - 1;
|
||||
}
|
||||
|
||||
long prevyear = (long)year - 1;
|
||||
long days = dayOfMonth;
|
||||
|
||||
if (prevyear >= 0) {
|
||||
days += (365 * prevyear)
|
||||
+ (prevyear / 4)
|
||||
- (prevyear / 100)
|
||||
+ (prevyear / 400)
|
||||
+ ((367 * month - 362) / 12);
|
||||
} else {
|
||||
days += (365 * prevyear)
|
||||
+ CalendarUtils.floorDivide(prevyear, 4)
|
||||
- CalendarUtils.floorDivide(prevyear, 100)
|
||||
+ CalendarUtils.floorDivide(prevyear, 400)
|
||||
+ CalendarUtils.floorDivide((367 * month - 362), 12);
|
||||
}
|
||||
|
||||
if (month > FEBRUARY) {
|
||||
days -= isLeapYear(year) ? 1 : 2;
|
||||
}
|
||||
|
||||
// If it's January 1, update the cache.
|
||||
if (cache != null && isJan1) {
|
||||
cache.setCache(year, days, isLeapYear(year) ? 366 : 365);
|
||||
}
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates calendar fields and store them in the specified
|
||||
* <code>CalendarDate</code>.
|
||||
*/
|
||||
// should be 'protected'
|
||||
public void getCalendarDateFromFixedDate(CalendarDate date,
|
||||
long fixedDate) {
|
||||
Date gdate = (Date) date;
|
||||
int year;
|
||||
long jan1;
|
||||
boolean isLeap;
|
||||
if (gdate.hit(fixedDate)) {
|
||||
year = gdate.getCachedYear();
|
||||
jan1 = gdate.getCachedJan1();
|
||||
isLeap = isLeapYear(year);
|
||||
} else {
|
||||
// Looking up FIXED_DATES[] here didn't improve performance
|
||||
// much. So we calculate year and jan1. getFixedDate()
|
||||
// will look up FIXED_DATES[] actually.
|
||||
year = getGregorianYearFromFixedDate(fixedDate);
|
||||
jan1 = getFixedDate(year, JANUARY, 1, null);
|
||||
isLeap = isLeapYear(year);
|
||||
// Update the cache data
|
||||
gdate.setCache (year, jan1, isLeap ? 366 : 365);
|
||||
}
|
||||
|
||||
int priorDays = (int)(fixedDate - jan1);
|
||||
long mar1 = jan1 + 31 + 28;
|
||||
if (isLeap) {
|
||||
++mar1;
|
||||
}
|
||||
if (fixedDate >= mar1) {
|
||||
priorDays += isLeap ? 1 : 2;
|
||||
}
|
||||
int month = 12 * priorDays + 373;
|
||||
if (month > 0) {
|
||||
month /= 367;
|
||||
} else {
|
||||
month = CalendarUtils.floorDivide(month, 367);
|
||||
}
|
||||
long month1 = jan1 + ACCUMULATED_DAYS_IN_MONTH[month];
|
||||
if (isLeap && month >= MARCH) {
|
||||
++month1;
|
||||
}
|
||||
int dayOfMonth = (int)(fixedDate - month1) + 1;
|
||||
int dayOfWeek = getDayOfWeekFromFixedDate(fixedDate);
|
||||
assert dayOfWeek > 0 : "negative day of week " + dayOfWeek;
|
||||
gdate.setNormalizedYear(year);
|
||||
gdate.setMonth(month);
|
||||
gdate.setDayOfMonth(dayOfMonth);
|
||||
gdate.setDayOfWeek(dayOfWeek);
|
||||
gdate.setLeapYear(isLeap);
|
||||
gdate.setNormalized(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the day of week of the given Gregorian date.
|
||||
*/
|
||||
public int getDayOfWeek(CalendarDate date) {
|
||||
long fixedDate = getFixedDate(date);
|
||||
return getDayOfWeekFromFixedDate(fixedDate);
|
||||
}
|
||||
|
||||
public static final int getDayOfWeekFromFixedDate(long fixedDate) {
|
||||
// The fixed day 1 (January 1, 1 Gregorian) is Monday.
|
||||
if (fixedDate >= 0) {
|
||||
return (int)(fixedDate % 7) + SUNDAY;
|
||||
}
|
||||
return (int)CalendarUtils.mod(fixedDate, 7) + SUNDAY;
|
||||
}
|
||||
|
||||
public int getYearFromFixedDate(long fixedDate) {
|
||||
return getGregorianYearFromFixedDate(fixedDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Gregorian year number of the given fixed date.
|
||||
*/
|
||||
final int getGregorianYearFromFixedDate(long fixedDate) {
|
||||
long d0;
|
||||
int d1, d2, d3, d4;
|
||||
int n400, n100, n4, n1;
|
||||
int year;
|
||||
|
||||
if (fixedDate > 0) {
|
||||
d0 = fixedDate - 1;
|
||||
n400 = (int)(d0 / 146097);
|
||||
d1 = (int)(d0 % 146097);
|
||||
n100 = d1 / 36524;
|
||||
d2 = d1 % 36524;
|
||||
n4 = d2 / 1461;
|
||||
d3 = d2 % 1461;
|
||||
n1 = d3 / 365;
|
||||
d4 = (d3 % 365) + 1;
|
||||
} else {
|
||||
d0 = fixedDate - 1;
|
||||
n400 = (int)CalendarUtils.floorDivide(d0, 146097L);
|
||||
d1 = (int)CalendarUtils.mod(d0, 146097L);
|
||||
n100 = CalendarUtils.floorDivide(d1, 36524);
|
||||
d2 = CalendarUtils.mod(d1, 36524);
|
||||
n4 = CalendarUtils.floorDivide(d2, 1461);
|
||||
d3 = CalendarUtils.mod(d2, 1461);
|
||||
n1 = CalendarUtils.floorDivide(d3, 365);
|
||||
d4 = CalendarUtils.mod(d3, 365) + 1;
|
||||
}
|
||||
year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
||||
if (!(n100 == 4 || n1 == 4)) {
|
||||
++year;
|
||||
}
|
||||
return year;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the specified year is a Gregorian leap year, or
|
||||
* false otherwise.
|
||||
* @see BaseCalendar#isGregorianLeapYear
|
||||
*/
|
||||
protected boolean isLeapYear(CalendarDate date) {
|
||||
return isLeapYear(((Date)date).getNormalizedYear());
|
||||
}
|
||||
|
||||
boolean isLeapYear(int normalizedYear) {
|
||||
return CalendarUtils.isGregorianLeapYear(normalizedYear);
|
||||
}
|
||||
}
|
||||
505
jdkSrc/jdk8/sun/util/calendar/CalendarDate.java
Normal file
505
jdkSrc/jdk8/sun/util/calendar/CalendarDate.java
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, 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.lang.Cloneable;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* The <code>CalendarDate</code> class represents a specific instant
|
||||
* in time by calendar date and time fields that are multiple cycles
|
||||
* in different time unites. The semantics of each calendar field is
|
||||
* given by a concrete calendar system rather than this
|
||||
* <code>CalendarDate</code> class that holds calendar field values
|
||||
* without interpreting them. Therefore, this class can be used to
|
||||
* represent an amount of time, such as 2 years and 3 months.
|
||||
*
|
||||
* <p>A <code>CalendarDate</code> instance can be created by calling
|
||||
* the <code>newCalendarDate</code> or <code>getCalendarDate</code>
|
||||
* methods in <code>CalendarSystem</code>. A
|
||||
* <code>CalendarSystem</code> instance is obtained by calling one of
|
||||
* the factory methods in <code>CalendarSystem</code>. Manipulations
|
||||
* of calendar dates must be handled by the calendar system by which
|
||||
* <code>CalendarDate</code> instances have been created.
|
||||
*
|
||||
* <p>Some calendar fields can be modified through method calls. Any
|
||||
* modification of a calendar field brings the state of a
|
||||
* <code>CalendarDate</code> to <I>not normalized</I>. The
|
||||
* normalization must be performed to make all the calendar fields
|
||||
* consistent with a calendar system.
|
||||
*
|
||||
* <p>The <code>protected</code> methods are intended to be used for
|
||||
* implementing a concrete calendar system, not for general use as an
|
||||
* API.
|
||||
*
|
||||
* @see CalendarSystem
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
public abstract class CalendarDate implements Cloneable {
|
||||
public static final int FIELD_UNDEFINED = Integer.MIN_VALUE;
|
||||
public static final long TIME_UNDEFINED = Long.MIN_VALUE;
|
||||
|
||||
private Era era;
|
||||
private int year;
|
||||
private int month;
|
||||
private int dayOfMonth;
|
||||
private int dayOfWeek = FIELD_UNDEFINED;
|
||||
private boolean leapYear;
|
||||
|
||||
private int hours;
|
||||
private int minutes;
|
||||
private int seconds;
|
||||
private int millis; // fractional part of the second
|
||||
private long fraction; // time of day value in millisecond
|
||||
|
||||
private boolean normalized;
|
||||
|
||||
private TimeZone zoneinfo;
|
||||
private int zoneOffset;
|
||||
private int daylightSaving;
|
||||
private boolean forceStandardTime;
|
||||
|
||||
private Locale locale;
|
||||
|
||||
protected CalendarDate() {
|
||||
this(TimeZone.getDefault());
|
||||
}
|
||||
|
||||
protected CalendarDate(TimeZone zone) {
|
||||
zoneinfo = zone;
|
||||
}
|
||||
|
||||
public Era getEra() {
|
||||
return era;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the era of the date to the specified era. The default
|
||||
* implementation of this method accepts any Era value, including
|
||||
* <code>null</code>.
|
||||
*
|
||||
* @exception NullPointerException if the calendar system for this
|
||||
* <code>CalendarDate</code> requires eras and the specified era
|
||||
* is null.
|
||||
* @exception IllegalArgumentException if the specified
|
||||
* <code>era</code> is unknown to the calendar
|
||||
* system for this <code>CalendarDate</code>.
|
||||
*/
|
||||
public CalendarDate setEra(Era era) {
|
||||
if (this.era == era) {
|
||||
return this;
|
||||
}
|
||||
this.era = era;
|
||||
normalized = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public CalendarDate setYear(int year) {
|
||||
if (this.year != year) {
|
||||
this.year = year;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addYear(int n) {
|
||||
if (n != 0) {
|
||||
year += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the year represented by this
|
||||
* <code>CalendarDate</code> is a leap year. If leap years are
|
||||
* not applicable to the calendar system, this method always
|
||||
* returns <code>false</code>.
|
||||
*
|
||||
* <p>If this <code>CalendarDate</code> hasn't been normalized,
|
||||
* <code>false</code> is returned. The normalization must be
|
||||
* performed to retrieve the correct leap year information.
|
||||
*
|
||||
* @return <code>true</code> if this <code>CalendarDate</code> is
|
||||
* normalized and the year of this <code>CalendarDate</code> is a
|
||||
* leap year, or <code>false</code> otherwise.
|
||||
* @see BaseCalendar#isGregorianLeapYear
|
||||
*/
|
||||
public boolean isLeapYear() {
|
||||
return leapYear;
|
||||
}
|
||||
|
||||
void setLeapYear(boolean leapYear) {
|
||||
this.leapYear = leapYear;
|
||||
}
|
||||
|
||||
public int getMonth() {
|
||||
return month;
|
||||
}
|
||||
|
||||
public CalendarDate setMonth(int month) {
|
||||
if (this.month != month) {
|
||||
this.month = month;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMonth(int n) {
|
||||
if (n != 0) {
|
||||
month += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getDayOfMonth() {
|
||||
return dayOfMonth;
|
||||
}
|
||||
|
||||
public CalendarDate setDayOfMonth(int date) {
|
||||
if (dayOfMonth != date) {
|
||||
dayOfMonth = date;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addDayOfMonth(int n) {
|
||||
if (n != 0) {
|
||||
dayOfMonth += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the day of week value. If this CalendarDate is not
|
||||
* normalized, {@link #FIELD_UNDEFINED} is returned.
|
||||
*
|
||||
* @return day of week or {@link #FIELD_UNDEFINED}
|
||||
*/
|
||||
public int getDayOfWeek() {
|
||||
if (!isNormalized()) {
|
||||
dayOfWeek = FIELD_UNDEFINED;
|
||||
}
|
||||
return dayOfWeek;
|
||||
}
|
||||
|
||||
public int getHours() {
|
||||
return hours;
|
||||
}
|
||||
|
||||
public CalendarDate setHours(int hours) {
|
||||
if (this.hours != hours) {
|
||||
this.hours = hours;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addHours(int n) {
|
||||
if (n != 0) {
|
||||
hours += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMinutes() {
|
||||
return minutes;
|
||||
}
|
||||
|
||||
public CalendarDate setMinutes(int minutes) {
|
||||
if (this.minutes != minutes) {
|
||||
this.minutes = minutes;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMinutes(int n) {
|
||||
if (n != 0) {
|
||||
minutes += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
public CalendarDate setSeconds(int seconds) {
|
||||
if (this.seconds != seconds) {
|
||||
this.seconds = seconds;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addSeconds(int n) {
|
||||
if (n != 0) {
|
||||
seconds += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMillis() {
|
||||
return millis;
|
||||
}
|
||||
|
||||
public CalendarDate setMillis(int millis) {
|
||||
if (this.millis != millis) {
|
||||
this.millis = millis;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMillis(int n) {
|
||||
if (n != 0) {
|
||||
millis += n;
|
||||
normalized = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getTimeOfDay() {
|
||||
if (!isNormalized()) {
|
||||
return fraction = TIME_UNDEFINED;
|
||||
}
|
||||
return fraction;
|
||||
}
|
||||
|
||||
public CalendarDate setDate(int year, int month, int dayOfMonth) {
|
||||
setYear(year);
|
||||
setMonth(month);
|
||||
setDayOfMonth(dayOfMonth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addDate(int year, int month, int dayOfMonth) {
|
||||
addYear(year);
|
||||
addMonth(month);
|
||||
addDayOfMonth(dayOfMonth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate setTimeOfDay(int hours, int minutes, int seconds, int millis) {
|
||||
setHours(hours);
|
||||
setMinutes(minutes);
|
||||
setSeconds(seconds);
|
||||
setMillis(millis);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CalendarDate addTimeOfDay(int hours, int minutes, int seconds, int millis) {
|
||||
addHours(hours);
|
||||
addMinutes(minutes);
|
||||
addSeconds(seconds);
|
||||
addMillis(millis);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void setTimeOfDay(long fraction) {
|
||||
this.fraction = fraction;
|
||||
}
|
||||
|
||||
public boolean isNormalized() {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
|
||||
public boolean isStandardTime() {
|
||||
return forceStandardTime;
|
||||
}
|
||||
|
||||
public void setStandardTime(boolean standardTime) {
|
||||
forceStandardTime = standardTime;
|
||||
}
|
||||
|
||||
public boolean isDaylightTime() {
|
||||
if (isStandardTime()) {
|
||||
return false;
|
||||
}
|
||||
return daylightSaving != 0;
|
||||
}
|
||||
|
||||
protected void setLocale(Locale loc) {
|
||||
locale = loc;
|
||||
}
|
||||
|
||||
public TimeZone getZone() {
|
||||
return zoneinfo;
|
||||
}
|
||||
|
||||
public CalendarDate setZone(TimeZone zoneinfo) {
|
||||
this.zoneinfo = zoneinfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified date is the same date of this
|
||||
* <code>CalendarDate</code>. The time of the day fields are
|
||||
* ignored for the comparison.
|
||||
*/
|
||||
public boolean isSameDate(CalendarDate date) {
|
||||
return getDayOfWeek() == date.getDayOfWeek()
|
||||
&& getMonth() == date.getMonth()
|
||||
&& getYear() == date.getYear()
|
||||
&& getEra() == date.getEra();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof CalendarDate)) {
|
||||
return false;
|
||||
}
|
||||
CalendarDate that = (CalendarDate) obj;
|
||||
if (isNormalized() != that.isNormalized()) {
|
||||
return false;
|
||||
}
|
||||
boolean hasZone = zoneinfo != null;
|
||||
boolean thatHasZone = that.zoneinfo != null;
|
||||
if (hasZone != thatHasZone) {
|
||||
return false;
|
||||
}
|
||||
if (hasZone && !zoneinfo.equals(that.zoneinfo)) {
|
||||
return false;
|
||||
}
|
||||
return (getEra() == that.getEra()
|
||||
&& year == that.year
|
||||
&& month == that.month
|
||||
&& dayOfMonth == that.dayOfMonth
|
||||
&& hours == that.hours
|
||||
&& minutes == that.minutes
|
||||
&& seconds == that.seconds
|
||||
&& millis == that.millis
|
||||
&& zoneOffset == that.zoneOffset);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
// a pseudo (local standard) time stamp value in milliseconds
|
||||
// from the Epoch, assuming Gregorian calendar fields.
|
||||
long hash = ((((((long)year - 1970) * 12) + (month - 1)) * 30) + dayOfMonth) * 24;
|
||||
hash = ((((((hash + hours) * 60) + minutes) * 60) + seconds) * 1000) + millis;
|
||||
hash -= zoneOffset;
|
||||
int normalized = isNormalized() ? 1 : 0;
|
||||
int era = 0;
|
||||
Era e = getEra();
|
||||
if (e != null) {
|
||||
era = e.hashCode();
|
||||
}
|
||||
int zone = zoneinfo != null ? zoneinfo.hashCode() : 0;
|
||||
return (int) hash * (int)(hash >> 32) ^ era ^ normalized ^ zone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this <code>CalendarDate</code>. The
|
||||
* <code>TimeZone</code> object, if any, is not cloned.
|
||||
*
|
||||
* @return a copy of this <code>CalendarDate</code>
|
||||
*/
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// this shouldn't happen
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts calendar date values to a <code>String</code> in the
|
||||
* following format.
|
||||
* <pre>
|
||||
* yyyy-MM-dd'T'HH:mm:ss.SSSz
|
||||
* </pre>
|
||||
*
|
||||
* @see java.text.SimpleDateFormat
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
CalendarUtils.sprintf0d(sb, year, 4).append('-');
|
||||
CalendarUtils.sprintf0d(sb, month, 2).append('-');
|
||||
CalendarUtils.sprintf0d(sb, dayOfMonth, 2).append('T');
|
||||
CalendarUtils.sprintf0d(sb, hours, 2).append(':');
|
||||
CalendarUtils.sprintf0d(sb, minutes, 2).append(':');
|
||||
CalendarUtils.sprintf0d(sb, seconds, 2).append('.');
|
||||
CalendarUtils.sprintf0d(sb, millis, 3);
|
||||
if (zoneOffset == 0) {
|
||||
sb.append('Z');
|
||||
} else if (zoneOffset != FIELD_UNDEFINED) {
|
||||
int offset;
|
||||
char sign;
|
||||
if (zoneOffset > 0) {
|
||||
offset = zoneOffset;
|
||||
sign = '+';
|
||||
} else {
|
||||
offset = -zoneOffset;
|
||||
sign = '-';
|
||||
}
|
||||
offset /= 60000;
|
||||
sb.append(sign);
|
||||
CalendarUtils.sprintf0d(sb, offset / 60, 2);
|
||||
CalendarUtils.sprintf0d(sb, offset % 60, 2);
|
||||
} else {
|
||||
sb.append(" local time");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected void setDayOfWeek(int dayOfWeek) {
|
||||
this.dayOfWeek = dayOfWeek;
|
||||
}
|
||||
|
||||
protected void setNormalized(boolean normalized) {
|
||||
this.normalized = normalized;
|
||||
}
|
||||
|
||||
public int getZoneOffset() {
|
||||
return zoneOffset;
|
||||
}
|
||||
|
||||
protected void setZoneOffset(int offset) {
|
||||
zoneOffset = offset;
|
||||
}
|
||||
|
||||
public int getDaylightSaving() {
|
||||
return daylightSaving;
|
||||
}
|
||||
|
||||
protected void setDaylightSaving(int daylightSaving) {
|
||||
this.daylightSaving = daylightSaving;
|
||||
}
|
||||
}
|
||||
395
jdkSrc/jdk8/sun/util/calendar/CalendarSystem.java
Normal file
395
jdkSrc/jdk8/sun/util/calendar/CalendarSystem.java
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, 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.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* <code>CalendarSystem</code> is an abstract class that defines the
|
||||
* programming interface to deal with calendar date and time.
|
||||
*
|
||||
* <p><code>CalendarSystem</code> 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.
|
||||
*
|
||||
* <h4>CalendarDate</h4>
|
||||
*
|
||||
* <p>For the methods in a <code>CalendarSystem</code> that manipulate
|
||||
* a <code>CalendarDate</code>, <code>CalendarDate</code>s that have
|
||||
* been created by the <code>CalendarSystem</code> 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.
|
||||
*
|
||||
* <h4>Calendar names</h4>
|
||||
*
|
||||
* Each calendar system has a unique name to be identified. The Java
|
||||
* runtime in this release supports the following calendar systems.
|
||||
*
|
||||
* <pre>
|
||||
* Name Calendar System
|
||||
* ---------------------------------------
|
||||
* gregorian Gregorian Calendar
|
||||
* julian Julian Calendar
|
||||
* japanese Japanese Imperial Calendar
|
||||
* </pre>
|
||||
*
|
||||
* @see CalendarDate
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public abstract class CalendarSystem {
|
||||
|
||||
/////////////////////// Calendar Factory Methods /////////////////////////
|
||||
|
||||
private volatile static boolean initialized = false;
|
||||
|
||||
// Map of calendar names and calendar class names
|
||||
private static ConcurrentMap<String, String> names;
|
||||
|
||||
// Map of calendar names and CalendarSystem instances
|
||||
private static ConcurrentMap<String,CalendarSystem> calendars;
|
||||
|
||||
private static final String PACKAGE_NAME = "sun.util.calendar.";
|
||||
|
||||
private static final String[] namePairs = {
|
||||
"gregorian", "Gregorian",
|
||||
"japanese", "LocalGregorianCalendar",
|
||||
"julian", "JulianCalendar",
|
||||
/*
|
||||
"hebrew", "HebrewCalendar",
|
||||
"iso8601", "ISOCalendar",
|
||||
"taiwanese", "LocalGregorianCalendar",
|
||||
"thaibuddhist", "LocalGregorianCalendar",
|
||||
*/
|
||||
};
|
||||
|
||||
private static void initNames() {
|
||||
ConcurrentMap<String,String> nameMap = new ConcurrentHashMap<>();
|
||||
|
||||
// Associate a calendar name with its class name and the
|
||||
// calendar class name with its date class name.
|
||||
StringBuilder clName = new StringBuilder();
|
||||
for (int i = 0; i < namePairs.length; i += 2) {
|
||||
clName.setLength(0);
|
||||
String cl = clName.append(PACKAGE_NAME).append(namePairs[i+1]).toString();
|
||||
nameMap.put(namePairs[i], cl);
|
||||
}
|
||||
synchronized (CalendarSystem.class) {
|
||||
if (!initialized) {
|
||||
names = nameMap;
|
||||
calendars = new ConcurrentHashMap<>();
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final static Gregorian GREGORIAN_INSTANCE = new Gregorian();
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of the <code>Gregorian</code>
|
||||
* calendar system.
|
||||
*
|
||||
* @return the <code>Gregorian</code> instance
|
||||
*/
|
||||
public static Gregorian getGregorianCalendar() {
|
||||
return GREGORIAN_INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>CalendarSystem</code> specified by the calendar
|
||||
* name. The calendar name has to be one of the supported calendar
|
||||
* names.
|
||||
*
|
||||
* @param calendarName the calendar name
|
||||
* @return the <code>CalendarSystem</code> specified by
|
||||
* <code>calendarName</code>, or null if there is no
|
||||
* <code>CalendarSystem</code> associated with the given calendar name.
|
||||
*/
|
||||
public static CalendarSystem forName(String calendarName) {
|
||||
if ("gregorian".equals(calendarName)) {
|
||||
return GREGORIAN_INSTANCE;
|
||||
}
|
||||
|
||||
if (!initialized) {
|
||||
initNames();
|
||||
}
|
||||
|
||||
CalendarSystem cal = calendars.get(calendarName);
|
||||
if (cal != null) {
|
||||
return cal;
|
||||
}
|
||||
|
||||
String className = names.get(calendarName);
|
||||
if (className == null) {
|
||||
return null; // Unknown calendar name
|
||||
}
|
||||
|
||||
if (className.endsWith("LocalGregorianCalendar")) {
|
||||
// Create the specific kind of local Gregorian calendar system
|
||||
cal = LocalGregorianCalendar.getLocalGregorianCalendar(calendarName);
|
||||
} else {
|
||||
try {
|
||||
Class<?> cl = Class.forName(className);
|
||||
cal = (CalendarSystem) cl.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
if (cal == null) {
|
||||
return null;
|
||||
}
|
||||
CalendarSystem cs = calendars.putIfAbsent(calendarName, cal);
|
||||
return (cs == null) ? cal : cs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = null;
|
||||
try {
|
||||
String homeDir = AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("java.home"));
|
||||
final String fname = homeDir + File.separator + "lib" + File.separator
|
||||
+ "calendars.properties";
|
||||
calendarProps = AccessController.doPrivileged(new PrivilegedExceptionAction<Properties>() {
|
||||
@Override
|
||||
public Properties run() throws IOException {
|
||||
Properties props = new Properties();
|
||||
try (FileInputStream fis = new FileInputStream(fname)) {
|
||||
props.load(fis);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof IOException) {
|
||||
throw (IOException) cause;
|
||||
} else if (cause instanceof IllegalArgumentException) {
|
||||
throw (IllegalArgumentException) cause;
|
||||
}
|
||||
// Should not happen
|
||||
throw new InternalError(cause);
|
||||
}
|
||||
return calendarProps;
|
||||
}
|
||||
|
||||
//////////////////////////////// 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 <code>CalendarDate</code> 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 <code>CalendarDate</code> 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 <code>CalendarDate</code> 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
|
||||
* <code>CalendarDate</code>.
|
||||
*
|
||||
* @param date the <code>CalendarDate</code> 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
|
||||
* <code>date</code>. This method does not perform the
|
||||
* normalization with the specified <code>CalendarDate</code>. The
|
||||
* <code>CalendarDate</code> 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
|
||||
* <code>CalendarDate</code>. The <code>CalendarDate</code> 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 <code>CalendarDate</code> 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 <code>Era</code> 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 <code>Era</code> designated by
|
||||
* <code>eraName</code>, or <code>null</code> 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 <code>Era</code>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, <code>null</code> is returned.
|
||||
*
|
||||
* @return an array of valid <code>Era</code>s, or
|
||||
* <code>null</code> 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 <code>CalendarDate</code> 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:
|
||||
*
|
||||
* <pre><code>
|
||||
* 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.
|
||||
* </code></pre>
|
||||
*
|
||||
* This method returns a new <code>CalendarDate</code> instance
|
||||
* and doesn't modify the original date.
|
||||
*
|
||||
* @param nth specifies the n-th one. A positive number specifies
|
||||
* <em>on or after</em> the <code>date</code>. A non-positive number
|
||||
* specifies <em>on or before</em> the <code>date</code>.
|
||||
* @param dayOfWeek the day of week
|
||||
* @param date the date
|
||||
* @return the date of the nth <code>dayOfWeek</code> after
|
||||
* or before the specified <code>CalendarDate</code>
|
||||
*/
|
||||
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 <code>date</code>
|
||||
* represents a valid date and time in this calendar system. If the
|
||||
* given date is valid, <code>date</code> is marked as <em>normalized</em>.
|
||||
*
|
||||
* @param date the <code>CalendarDate</code> to be validated
|
||||
* @return <code>true</code> if all the calendar fields are consistent,
|
||||
* otherwise, <code>false</code> is returned.
|
||||
* @exception NullPointerException if the specified
|
||||
* <code>date</code> is <code>null</code>
|
||||
*/
|
||||
public abstract boolean validate(CalendarDate date);
|
||||
|
||||
/**
|
||||
* Normalizes calendar fields in the specified
|
||||
* <code>date</code>. 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 <code>true</code> if all fields have been normalized;
|
||||
* <code>false</code> otherwise.
|
||||
* @exception NullPointerException if the specified
|
||||
* <code>date</code> is <code>null</code>
|
||||
*/
|
||||
public abstract boolean normalize(CalendarDate date);
|
||||
}
|
||||
193
jdkSrc/jdk8/sun/util/calendar/CalendarUtils.java
Normal file
193
jdkSrc/jdk8/sun/util/calendar/CalendarUtils.java
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CalendarUtils {
|
||||
|
||||
/**
|
||||
* Returns whether the specified year is a leap year in the Gregorian
|
||||
* calendar system.
|
||||
*
|
||||
* @param gregorianYear a Gregorian calendar year
|
||||
* @return true if the given year is a leap year in the Gregorian
|
||||
* calendar system.
|
||||
* @see CalendarDate#isLeapYear
|
||||
*/
|
||||
public static final boolean isGregorianLeapYear(int gregorianYear) {
|
||||
return (((gregorianYear % 4) == 0)
|
||||
&& (((gregorianYear % 100) != 0) || ((gregorianYear % 400) == 0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified year is a leap year in the Julian
|
||||
* calendar system. The year number must be a normalized one
|
||||
* (e.g., 45 B.C.E. is 1-45).
|
||||
*
|
||||
* @param normalizedJulianYear a normalized Julian calendar year
|
||||
* @return true if the given year is a leap year in the Julian
|
||||
* calendar system.
|
||||
* @see CalendarDate#isLeapYear
|
||||
*/
|
||||
public static final boolean isJulianLeapYear(int normalizedJulianYear) {
|
||||
return (normalizedJulianYear % 4) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two integers and returns the floor of the quotient.
|
||||
* For example, <code>floorDivide(-1, 4)</code> returns -1 while
|
||||
* -1/4 is 0.
|
||||
*
|
||||
* @param n the numerator
|
||||
* @param d a divisor that must be greater than 0
|
||||
* @return the floor of the quotient
|
||||
*/
|
||||
public static final long floorDivide(long n, long d) {
|
||||
return ((n >= 0) ?
|
||||
(n / d) : (((n + 1L) / d) - 1L));
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two integers and returns the floor of the quotient.
|
||||
* For example, <code>floorDivide(-1, 4)</code> returns -1 while
|
||||
* -1/4 is 0.
|
||||
*
|
||||
* @param n the numerator
|
||||
* @param d a divisor that must be greater than 0
|
||||
* @return the floor of the quotient
|
||||
*/
|
||||
public static final int floorDivide(int n, int d) {
|
||||
return ((n >= 0) ?
|
||||
(n / d) : (((n + 1) / d) - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two integers and returns the floor of the quotient and
|
||||
* the modulus remainder. For example,
|
||||
* <code>floorDivide(-1,4)</code> returns <code>-1</code> with
|
||||
* <code>3</code> as its remainder, while <code>-1/4</code> is
|
||||
* <code>0</code> and <code>-1%4</code> is <code>-1</code>.
|
||||
*
|
||||
* @param n the numerator
|
||||
* @param d a divisor which must be > 0
|
||||
* @param r an array of at least one element in which the value
|
||||
* <code>mod(n, d)</code> is returned.
|
||||
* @return the floor of the quotient.
|
||||
*/
|
||||
public static final int floorDivide(int n, int d, int[] r) {
|
||||
if (n >= 0) {
|
||||
r[0] = n % d;
|
||||
return n / d;
|
||||
}
|
||||
int q = ((n + 1) / d) - 1;
|
||||
r[0] = n - (q * d);
|
||||
return q;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two integers and returns the floor of the quotient and
|
||||
* the modulus remainder. For example,
|
||||
* <code>floorDivide(-1,4)</code> returns <code>-1</code> with
|
||||
* <code>3</code> as its remainder, while <code>-1/4</code> is
|
||||
* <code>0</code> and <code>-1%4</code> is <code>-1</code>.
|
||||
*
|
||||
* @param n the numerator
|
||||
* @param d a divisor which must be > 0
|
||||
* @param r an array of at least one element in which the value
|
||||
* <code>mod(n, d)</code> is returned.
|
||||
* @return the floor of the quotient.
|
||||
*/
|
||||
public static final int floorDivide(long n, int d, int[] r) {
|
||||
if (n >= 0) {
|
||||
r[0] = (int)(n % d);
|
||||
return (int)(n / d);
|
||||
}
|
||||
int q = (int)(((n + 1) / d) - 1);
|
||||
r[0] = (int)(n - (q * d));
|
||||
return q;
|
||||
}
|
||||
|
||||
public static final long mod(long x, long y) {
|
||||
return (x - y * floorDivide(x, y));
|
||||
}
|
||||
|
||||
public static final int mod(int x, int y) {
|
||||
return (x - y * floorDivide(x, y));
|
||||
}
|
||||
|
||||
public static final int amod(int x, int y) {
|
||||
int z = mod(x, y);
|
||||
return (z == 0) ? y : z;
|
||||
}
|
||||
|
||||
public static final long amod(long x, long y) {
|
||||
long z = mod(x, y);
|
||||
return (z == 0) ? y : z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mimics sprintf(buf, "%0*d", decaimal, width).
|
||||
*/
|
||||
public static final StringBuilder sprintf0d(StringBuilder sb, int value, int width) {
|
||||
long d = value;
|
||||
if (d < 0) {
|
||||
sb.append('-');
|
||||
d = -d;
|
||||
--width;
|
||||
}
|
||||
int n = 10;
|
||||
for (int i = 2; i < width; i++) {
|
||||
n *= 10;
|
||||
}
|
||||
for (int i = 1; i < width && d < n; i++) {
|
||||
sb.append('0');
|
||||
n /= 10;
|
||||
}
|
||||
sb.append(d);
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static final StringBuffer sprintf0d(StringBuffer sb, int value, int width) {
|
||||
long d = value;
|
||||
if (d < 0) {
|
||||
sb.append('-');
|
||||
d = -d;
|
||||
--width;
|
||||
}
|
||||
int n = 10;
|
||||
for (int i = 2; i < width; i++) {
|
||||
n *= 10;
|
||||
}
|
||||
for (int i = 1; i < width && d < n; i++) {
|
||||
sb.append('0');
|
||||
n /= 10;
|
||||
}
|
||||
sb.append(d);
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
154
jdkSrc/jdk8/sun/util/calendar/Era.java
Normal file
154
jdkSrc/jdk8/sun/util/calendar/Era.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2019, 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.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* The class <code>Era</code> represents a calendar era that defines a
|
||||
* period of time in which the same year numbering is used. For
|
||||
* example, Gregorian year 2004 is <I>Heisei</I> 16 in the Japanese
|
||||
* calendar system. An era starts at any point of time (Gregorian) that is
|
||||
* represented by <code>CalendarDate</code>.
|
||||
*
|
||||
* <p><code>Era</code>s that are applicable to a particular calendar
|
||||
* system can be obtained by calling {@link CalendarSystem#getEras}
|
||||
* one of which can be used to specify a date in
|
||||
* <code>CalendarDate</code>.
|
||||
*
|
||||
* <p>The following era names are defined in this release.
|
||||
* <pre>{@code
|
||||
* Calendar system Era name Since (in Gregorian)
|
||||
* -----------------------------------------------------------------------
|
||||
* Japanese calendar Meiji 1868-01-01T00:00:00 local time
|
||||
* Taisho 1912-07-30T00:00:00 local time
|
||||
* Showa 1926-12-25T00:00:00 local time
|
||||
* Heisei 1989-01-08T00:00:00 local time
|
||||
* Reiwa 2019-05-01T00:00:00 local time
|
||||
* -----------------------------------------------------------------------
|
||||
* }</pre>
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public final class Era {
|
||||
private final String name;
|
||||
private final String abbr;
|
||||
private final long since;
|
||||
private final CalendarDate sinceDate;
|
||||
private final boolean localTime;
|
||||
|
||||
/**
|
||||
* Constructs an <code>Era</code> instance.
|
||||
*
|
||||
* @param name the era name (e.g., "BeforeCommonEra" for the Julian calendar system)
|
||||
* @param abbr the abbreviation of the era name (e.g., "B.C.E." for "BeforeCommonEra")
|
||||
* @param since the time (millisecond offset from January 1, 1970
|
||||
* (Gregorian) UTC or local time) when the era starts, inclusive.
|
||||
* @param localTime <code>true</code> if <code>since</code>
|
||||
* specifies a local time; <code>false</code> if
|
||||
* <code>since</code> specifies UTC
|
||||
*/
|
||||
public Era(String name, String abbr, long since, boolean localTime) {
|
||||
this.name = name;
|
||||
this.abbr = abbr;
|
||||
this.since = since;
|
||||
this.localTime = localTime;
|
||||
Gregorian gcal = CalendarSystem.getGregorianCalendar();
|
||||
BaseCalendar.Date d = (BaseCalendar.Date) gcal.newCalendarDate(null);
|
||||
gcal.getCalendarDate(since, d);
|
||||
sinceDate = new ImmutableGregorianDate(d);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDisplayName(Locale locale) {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAbbreviation() {
|
||||
return abbr;
|
||||
}
|
||||
|
||||
public String getDiaplayAbbreviation(Locale locale) {
|
||||
return abbr;
|
||||
}
|
||||
|
||||
public long getSince(TimeZone zone) {
|
||||
if (zone == null || !localTime) {
|
||||
return since;
|
||||
}
|
||||
int offset = zone.getOffset(since);
|
||||
return since - offset;
|
||||
}
|
||||
|
||||
public CalendarDate getSinceDate() {
|
||||
return sinceDate;
|
||||
}
|
||||
|
||||
public boolean isLocalTime() {
|
||||
return localTime;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Era)) {
|
||||
return false;
|
||||
}
|
||||
Era that = (Era) o;
|
||||
return name.equals(that.name)
|
||||
&& abbr.equals(that.abbr)
|
||||
&& since == that.since
|
||||
&& localTime == that.localTime;
|
||||
}
|
||||
|
||||
private int hash = 0;
|
||||
|
||||
public int hashCode() {
|
||||
if (hash == 0) {
|
||||
hash = name.hashCode() ^ abbr.hashCode() ^ (int)since ^ (int)(since >> 32)
|
||||
^ (localTime ? 1 : 0);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('[');
|
||||
sb.append(getName()).append(" (");
|
||||
sb.append(getAbbreviation()).append(')');
|
||||
sb.append(" since ").append(getSinceDate());
|
||||
if (localTime) {
|
||||
sb.setLength(sb.length() - 1); // remove 'Z'
|
||||
sb.append(" local time");
|
||||
}
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
87
jdkSrc/jdk8/sun/util/calendar/Gregorian.java
Normal file
87
jdkSrc/jdk8/sun/util/calendar/Gregorian.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2005, 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.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Gregorian calendar implementation.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public class Gregorian extends BaseCalendar {
|
||||
|
||||
static class Date extends BaseCalendar.Date {
|
||||
protected Date() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected Date(TimeZone zone) {
|
||||
super(zone);
|
||||
}
|
||||
|
||||
public int getNormalizedYear() {
|
||||
return getYear();
|
||||
}
|
||||
|
||||
public void setNormalizedYear(int normalizedYear) {
|
||||
setYear(normalizedYear);
|
||||
}
|
||||
}
|
||||
|
||||
Gregorian() {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "gregorian";
|
||||
}
|
||||
|
||||
public Date getCalendarDate() {
|
||||
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis) {
|
||||
return getCalendarDate(millis, newCalendarDate());
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis, CalendarDate date) {
|
||||
return (Date) super.getCalendarDate(millis, date);
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis, TimeZone zone) {
|
||||
return getCalendarDate(millis, newCalendarDate(zone));
|
||||
}
|
||||
|
||||
public Date newCalendarDate() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
public Date newCalendarDate(TimeZone zone) {
|
||||
return new Date(zone);
|
||||
}
|
||||
}
|
||||
258
jdkSrc/jdk8/sun/util/calendar/ImmutableGregorianDate.java
Normal file
258
jdkSrc/jdk8/sun/util/calendar/ImmutableGregorianDate.java
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
class ImmutableGregorianDate extends BaseCalendar.Date {
|
||||
private final BaseCalendar.Date date;
|
||||
|
||||
ImmutableGregorianDate(BaseCalendar.Date date) {
|
||||
if (date == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public Era getEra() {
|
||||
return date.getEra();
|
||||
}
|
||||
|
||||
public CalendarDate setEra(Era era) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return date.getYear();
|
||||
}
|
||||
|
||||
public CalendarDate setYear(int year) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addYear(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public boolean isLeapYear() {
|
||||
return date.isLeapYear();
|
||||
}
|
||||
|
||||
void setLeapYear(boolean leapYear) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public int getMonth() {
|
||||
return date.getMonth();
|
||||
}
|
||||
|
||||
public CalendarDate setMonth(int month) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMonth(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getDayOfMonth() {
|
||||
return date.getDayOfMonth();
|
||||
}
|
||||
|
||||
public CalendarDate setDayOfMonth(int date) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addDayOfMonth(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getDayOfWeek() {
|
||||
return date.getDayOfWeek();
|
||||
}
|
||||
|
||||
public int getHours() {
|
||||
return date.getHours();
|
||||
}
|
||||
|
||||
public CalendarDate setHours(int hours) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addHours(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getMinutes() {
|
||||
return date.getMinutes();
|
||||
}
|
||||
|
||||
public CalendarDate setMinutes(int minutes) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMinutes(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getSeconds() {
|
||||
return date.getSeconds();
|
||||
}
|
||||
|
||||
public CalendarDate setSeconds(int seconds) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addSeconds(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public int getMillis() {
|
||||
return date.getMillis();
|
||||
}
|
||||
|
||||
public CalendarDate setMillis(int millis) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addMillis(int n) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public long getTimeOfDay() {
|
||||
return date.getTimeOfDay();
|
||||
}
|
||||
|
||||
public CalendarDate setDate(int year, int month, int dayOfMonth) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addDate(int year, int month, int dayOfMonth) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate setTimeOfDay(int hours, int minutes, int seconds, int millis) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public CalendarDate addTimeOfDay(int hours, int minutes, int seconds, int millis) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
protected void setTimeOfDay(long fraction) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public boolean isNormalized() {
|
||||
return date.isNormalized();
|
||||
}
|
||||
|
||||
public boolean isStandardTime() {
|
||||
return date.isStandardTime();
|
||||
}
|
||||
|
||||
public void setStandardTime(boolean standardTime) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public boolean isDaylightTime() {
|
||||
return date.isDaylightTime();
|
||||
}
|
||||
|
||||
protected void setLocale(Locale loc) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public TimeZone getZone() {
|
||||
return date.getZone();
|
||||
}
|
||||
|
||||
public CalendarDate setZone(TimeZone zoneinfo) {
|
||||
unsupported(); return this;
|
||||
}
|
||||
|
||||
public boolean isSameDate(CalendarDate date) {
|
||||
return date.isSameDate(date);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof ImmutableGregorianDate)) {
|
||||
return false;
|
||||
}
|
||||
return date.equals(((ImmutableGregorianDate) obj).date);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return date.hashCode();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return date.toString();
|
||||
}
|
||||
|
||||
protected void setDayOfWeek(int dayOfWeek) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
protected void setNormalized(boolean normalized) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public int getZoneOffset() {
|
||||
return date.getZoneOffset();
|
||||
}
|
||||
|
||||
protected void setZoneOffset(int offset) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public int getDaylightSaving() {
|
||||
return date.getDaylightSaving();
|
||||
}
|
||||
|
||||
protected void setDaylightSaving(int daylightSaving) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
public int getNormalizedYear() {
|
||||
return date.getNormalizedYear();
|
||||
}
|
||||
|
||||
public void setNormalizedYear(int normalizedYear) {
|
||||
unsupported();
|
||||
}
|
||||
|
||||
private void unsupported() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
234
jdkSrc/jdk8/sun/util/calendar/JulianCalendar.java
Normal file
234
jdkSrc/jdk8/sun/util/calendar/JulianCalendar.java
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2005, 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.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Julian calendar implementation.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.5
|
||||
*/
|
||||
public class JulianCalendar extends BaseCalendar {
|
||||
|
||||
private static final int BCE = 0;
|
||||
private static final int CE = 1;
|
||||
|
||||
private static final Era[] eras = {
|
||||
new Era("BeforeCommonEra", "B.C.E.", Long.MIN_VALUE, false),
|
||||
new Era("CommonEra", "C.E.", -62135709175808L, true)
|
||||
};
|
||||
private static final int JULIAN_EPOCH = -1;
|
||||
|
||||
private static class Date extends BaseCalendar.Date {
|
||||
protected Date() {
|
||||
super();
|
||||
setCache(1, -1L, 365); // January 1, 1 CE (Julian)
|
||||
}
|
||||
|
||||
protected Date(TimeZone zone) {
|
||||
super(zone);
|
||||
setCache(1, -1L, 365); // January 1, 1 CE (Julian)
|
||||
}
|
||||
|
||||
public Date setEra(Era era) {
|
||||
if (era == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (era != eras[0] || era != eras[1]) {
|
||||
throw new IllegalArgumentException("unknown era: " + era);
|
||||
}
|
||||
super.setEra(era);
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void setKnownEra(Era era) {
|
||||
super.setEra(era);
|
||||
}
|
||||
|
||||
public int getNormalizedYear() {
|
||||
if (getEra() == eras[BCE]) {
|
||||
return 1 - getYear();
|
||||
}
|
||||
return getYear();
|
||||
}
|
||||
|
||||
// Use the year numbering ..., -2, -1, 0, 1, 2, ... for
|
||||
// normalized years. This differs from "Calendrical
|
||||
// Calculations" in which the numbering is ..., -2, -1, 1, 2,
|
||||
// ...
|
||||
public void setNormalizedYear(int year) {
|
||||
if (year <= 0) {
|
||||
setYear(1 - year);
|
||||
setKnownEra(eras[BCE]);
|
||||
} else {
|
||||
setYear(year);
|
||||
setKnownEra(eras[CE]);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String time = super.toString();
|
||||
time = time.substring(time.indexOf('T'));
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Era era = getEra();
|
||||
if (era != null) {
|
||||
String n = era.getAbbreviation();
|
||||
if (n != null) {
|
||||
sb.append(n).append(' ');
|
||||
}
|
||||
}
|
||||
sb.append(getYear()).append('-');
|
||||
CalendarUtils.sprintf0d(sb, getMonth(), 2).append('-');
|
||||
CalendarUtils.sprintf0d(sb, getDayOfMonth(), 2);
|
||||
sb.append(time);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
JulianCalendar() {
|
||||
setEras(eras);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "julian";
|
||||
}
|
||||
|
||||
public Date getCalendarDate() {
|
||||
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis) {
|
||||
return getCalendarDate(millis, newCalendarDate());
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis, CalendarDate date) {
|
||||
return (Date) super.getCalendarDate(millis, date);
|
||||
}
|
||||
|
||||
public Date getCalendarDate(long millis, TimeZone zone) {
|
||||
return getCalendarDate(millis, newCalendarDate(zone));
|
||||
}
|
||||
|
||||
public Date newCalendarDate() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
public Date newCalendarDate(TimeZone zone) {
|
||||
return new Date(zone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jyear normalized Julian year
|
||||
*/
|
||||
public long getFixedDate(int jyear, int month, int dayOfMonth, BaseCalendar.Date cache) {
|
||||
boolean isJan1 = month == JANUARY && dayOfMonth == 1;
|
||||
|
||||
// Look up the one year cache
|
||||
if (cache != null && cache.hit(jyear)) {
|
||||
if (isJan1) {
|
||||
return cache.getCachedJan1();
|
||||
}
|
||||
return cache.getCachedJan1() + getDayOfYear(jyear, month, dayOfMonth) - 1;
|
||||
}
|
||||
|
||||
long y = jyear;
|
||||
long days = JULIAN_EPOCH - 1 + (365 * (y - 1)) + dayOfMonth;
|
||||
if (y > 0) {
|
||||
// CE years
|
||||
days += (y - 1) / 4;
|
||||
} else {
|
||||
// BCE years
|
||||
days += CalendarUtils.floorDivide(y - 1, 4);
|
||||
}
|
||||
if (month > 0) {
|
||||
days += ((367 * (long) month) - 362) / 12;
|
||||
} else {
|
||||
days += CalendarUtils.floorDivide((367 * (long) month) - 362, 12);
|
||||
}
|
||||
if (month > FEBRUARY) {
|
||||
days -= CalendarUtils.isJulianLeapYear(jyear) ? 1 : 2;
|
||||
}
|
||||
|
||||
// If it's January 1, update the cache.
|
||||
if (cache != null && isJan1) {
|
||||
cache.setCache(jyear, days, CalendarUtils.isJulianLeapYear(jyear) ? 366 : 365);
|
||||
}
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) {
|
||||
Date jdate = (Date) date;
|
||||
long fd = 4 * (fixedDate - JULIAN_EPOCH) + 1464;
|
||||
int year;
|
||||
if (fd >= 0) {
|
||||
year = (int)(fd / 1461);
|
||||
} else {
|
||||
year = (int) CalendarUtils.floorDivide(fd, 1461);
|
||||
}
|
||||
int priorDays = (int)(fixedDate - getFixedDate(year, JANUARY, 1, jdate));
|
||||
boolean isLeap = CalendarUtils.isJulianLeapYear(year);
|
||||
if (fixedDate >= getFixedDate(year, MARCH, 1, jdate)) {
|
||||
priorDays += isLeap ? 1 : 2;
|
||||
}
|
||||
int month = 12 * priorDays + 373;
|
||||
if (month > 0) {
|
||||
month /= 367;
|
||||
} else {
|
||||
month = CalendarUtils.floorDivide(month, 367);
|
||||
}
|
||||
int dayOfMonth = (int)(fixedDate - getFixedDate(year, month, 1, jdate)) + 1;
|
||||
int dayOfWeek = getDayOfWeekFromFixedDate(fixedDate);
|
||||
assert dayOfWeek > 0 : "negative day of week " + dayOfWeek;
|
||||
jdate.setNormalizedYear(year);
|
||||
jdate.setMonth(month);
|
||||
jdate.setDayOfMonth(dayOfMonth);
|
||||
jdate.setDayOfWeek(dayOfWeek);
|
||||
jdate.setLeapYear(isLeap);
|
||||
jdate.setNormalized(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normalized Julian year number of the given fixed date.
|
||||
*/
|
||||
public int getYearFromFixedDate(long fixedDate) {
|
||||
int year = (int) CalendarUtils.floorDivide(4 * (fixedDate - JULIAN_EPOCH) + 1464, 1461);
|
||||
return year;
|
||||
}
|
||||
|
||||
public int getDayOfWeek(CalendarDate date) {
|
||||
// TODO: should replace this with a faster calculation, such
|
||||
// as cache table lookup
|
||||
long fixedDate = getFixedDate(date);
|
||||
return getDayOfWeekFromFixedDate(fixedDate);
|
||||
}
|
||||
|
||||
boolean isLeapYear(int jyear) {
|
||||
return CalendarUtils.isJulianLeapYear(jyear);
|
||||
}
|
||||
}
|
||||
389
jdkSrc/jdk8/sun/util/calendar/LocalGregorianCalendar.java
Normal file
389
jdkSrc/jdk8/sun/util/calendar/LocalGregorianCalendar.java
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, 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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.6
|
||||
*/
|
||||
|
||||
public class LocalGregorianCalendar extends BaseCalendar {
|
||||
private String name;
|
||||
private Era[] eras;
|
||||
|
||||
public static class Date extends BaseCalendar.Date {
|
||||
|
||||
protected Date() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected Date(TimeZone zone) {
|
||||
super(zone);
|
||||
}
|
||||
|
||||
private int gregorianYear = FIELD_UNDEFINED;
|
||||
|
||||
@Override
|
||||
public Date setEra(Era era) {
|
||||
if (getEra() != era) {
|
||||
super.setEra(era);
|
||||
gregorianYear = FIELD_UNDEFINED;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date addYear(int localYear) {
|
||||
super.addYear(localYear);
|
||||
gregorianYear += localYear;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date setYear(int localYear) {
|
||||
if (getYear() != localYear) {
|
||||
super.setYear(localYear);
|
||||
gregorianYear = FIELD_UNDEFINED;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNormalizedYear() {
|
||||
return gregorianYear;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNormalizedYear(int normalizedYear) {
|
||||
this.gregorianYear = normalizedYear;
|
||||
}
|
||||
|
||||
void setLocalEra(Era era) {
|
||||
super.setEra(era);
|
||||
}
|
||||
|
||||
void setLocalYear(int year) {
|
||||
super.setYear(year);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String time = super.toString();
|
||||
time = time.substring(time.indexOf('T'));
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Era era = getEra();
|
||||
if (era != null) {
|
||||
String abbr = era.getAbbreviation();
|
||||
if (abbr != null) {
|
||||
sb.append(abbr);
|
||||
}
|
||||
}
|
||||
sb.append(getYear()).append('.');
|
||||
CalendarUtils.sprintf0d(sb, getMonth(), 2).append('.');
|
||||
CalendarUtils.sprintf0d(sb, getDayOfMonth(), 2);
|
||||
sb.append(time);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static LocalGregorianCalendar getLocalGregorianCalendar(String name) {
|
||||
Properties calendarProps;
|
||||
try {
|
||||
calendarProps = CalendarSystem.getCalendarProperties();
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
// Parse calendar.*.eras
|
||||
String props = calendarProps.getProperty("calendar." + name + ".eras");
|
||||
if (props == null) {
|
||||
return null;
|
||||
}
|
||||
List<Era> eras = new ArrayList<>();
|
||||
StringTokenizer eraTokens = new StringTokenizer(props, ";");
|
||||
while (eraTokens.hasMoreTokens()) {
|
||||
String items = eraTokens.nextToken().trim();
|
||||
StringTokenizer itemTokens = new StringTokenizer(items, ",");
|
||||
String eraName = null;
|
||||
boolean localTime = true;
|
||||
long since = 0;
|
||||
String abbr = null;
|
||||
|
||||
while (itemTokens.hasMoreTokens()) {
|
||||
String item = itemTokens.nextToken();
|
||||
int index = item.indexOf('=');
|
||||
// it must be in the key=value form.
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
String key = item.substring(0, index);
|
||||
String value = item.substring(index + 1);
|
||||
if ("name".equals(key)) {
|
||||
eraName = value;
|
||||
} else if ("since".equals(key)) {
|
||||
if (value.endsWith("u")) {
|
||||
localTime = false;
|
||||
since = Long.parseLong(value.substring(0, value.length() - 1));
|
||||
} else {
|
||||
since = Long.parseLong(value);
|
||||
}
|
||||
} else if ("abbr".equals(key)) {
|
||||
abbr = value;
|
||||
} else {
|
||||
throw new RuntimeException("Unknown key word: " + key);
|
||||
}
|
||||
}
|
||||
Era era = new Era(eraName, abbr, since, localTime);
|
||||
eras.add(era);
|
||||
}
|
||||
Era[] eraArray = new Era[eras.size()];
|
||||
eras.toArray(eraArray);
|
||||
|
||||
return new LocalGregorianCalendar(name, eraArray);
|
||||
}
|
||||
|
||||
private LocalGregorianCalendar(String name, Era[] eras) {
|
||||
this.name = name;
|
||||
this.eras = eras;
|
||||
setEras(eras);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCalendarDate() {
|
||||
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCalendarDate(long millis) {
|
||||
return getCalendarDate(millis, newCalendarDate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCalendarDate(long millis, TimeZone zone) {
|
||||
return getCalendarDate(millis, newCalendarDate(zone));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getCalendarDate(long millis, CalendarDate date) {
|
||||
Date ldate = (Date) super.getCalendarDate(millis, date);
|
||||
return adjustYear(ldate, millis, ldate.getZoneOffset());
|
||||
}
|
||||
|
||||
private Date adjustYear(Date ldate, long millis, int zoneOffset) {
|
||||
int i;
|
||||
for (i = eras.length - 1; i >= 0; --i) {
|
||||
Era era = eras[i];
|
||||
long since = era.getSince(null);
|
||||
if (era.isLocalTime()) {
|
||||
since -= zoneOffset;
|
||||
}
|
||||
if (millis >= since) {
|
||||
ldate.setLocalEra(era);
|
||||
int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1;
|
||||
ldate.setLocalYear(y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 0) {
|
||||
ldate.setLocalEra(null);
|
||||
ldate.setLocalYear(ldate.getNormalizedYear());
|
||||
}
|
||||
ldate.setNormalized(true);
|
||||
return ldate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date newCalendarDate() {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date newCalendarDate(TimeZone zone) {
|
||||
return new Date(zone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(CalendarDate date) {
|
||||
Date ldate = (Date) date;
|
||||
Era era = ldate.getEra();
|
||||
if (era != null) {
|
||||
if (!validateEra(era)) {
|
||||
return false;
|
||||
}
|
||||
ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear() - 1);
|
||||
Date tmp = newCalendarDate(date.getZone());
|
||||
tmp.setEra(era).setDate(date.getYear(), date.getMonth(), date.getDayOfMonth());
|
||||
normalize(tmp);
|
||||
if (tmp.getEra() != era) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (date.getYear() >= eras[0].getSinceDate().getYear()) {
|
||||
return false;
|
||||
}
|
||||
ldate.setNormalizedYear(ldate.getYear());
|
||||
}
|
||||
return super.validate(ldate);
|
||||
}
|
||||
|
||||
private boolean validateEra(Era era) {
|
||||
// Validate the era
|
||||
for (int i = 0; i < eras.length; i++) {
|
||||
if (era == eras[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean normalize(CalendarDate date) {
|
||||
if (date.isNormalized()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
normalizeYear(date);
|
||||
Date ldate = (Date) date;
|
||||
|
||||
// Normalize it as a Gregorian date and get its millisecond value
|
||||
super.normalize(ldate);
|
||||
|
||||
boolean hasMillis = false;
|
||||
long millis = 0;
|
||||
int year = ldate.getNormalizedYear();
|
||||
int i;
|
||||
Era era = null;
|
||||
for (i = eras.length - 1; i >= 0; --i) {
|
||||
era = eras[i];
|
||||
if (era.isLocalTime()) {
|
||||
CalendarDate sinceDate = era.getSinceDate();
|
||||
int sinceYear = sinceDate.getYear();
|
||||
if (year > sinceYear) {
|
||||
break;
|
||||
}
|
||||
if (year == sinceYear) {
|
||||
int month = ldate.getMonth();
|
||||
int sinceMonth = sinceDate.getMonth();
|
||||
if (month > sinceMonth) {
|
||||
break;
|
||||
}
|
||||
if (month == sinceMonth) {
|
||||
int day = ldate.getDayOfMonth();
|
||||
int sinceDay = sinceDate.getDayOfMonth();
|
||||
if (day > sinceDay) {
|
||||
break;
|
||||
}
|
||||
if (day == sinceDay) {
|
||||
long timeOfDay = ldate.getTimeOfDay();
|
||||
long sinceTimeOfDay = sinceDate.getTimeOfDay();
|
||||
if (timeOfDay >= sinceTimeOfDay) {
|
||||
break;
|
||||
}
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!hasMillis) {
|
||||
millis = super.getTime(date);
|
||||
hasMillis = true;
|
||||
}
|
||||
|
||||
long since = era.getSince(date.getZone());
|
||||
if (millis >= since) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i >= 0) {
|
||||
ldate.setLocalEra(era);
|
||||
int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1;
|
||||
ldate.setLocalYear(y);
|
||||
} else {
|
||||
// Set Gregorian year with no era
|
||||
ldate.setEra(null);
|
||||
ldate.setLocalYear(year);
|
||||
ldate.setNormalizedYear(year);
|
||||
}
|
||||
ldate.setNormalized(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void normalizeMonth(CalendarDate date) {
|
||||
normalizeYear(date);
|
||||
super.normalizeMonth(date);
|
||||
}
|
||||
|
||||
void normalizeYear(CalendarDate date) {
|
||||
Date ldate = (Date) date;
|
||||
// Set the supposed-to-be-correct Gregorian year first
|
||||
// e.g., Showa 90 becomes 2015 (1926 + 90 - 1).
|
||||
Era era = ldate.getEra();
|
||||
if (era == null || !validateEra(era)) {
|
||||
ldate.setNormalizedYear(ldate.getYear());
|
||||
} else {
|
||||
ldate.setNormalizedYear(era.getSinceDate().getYear() + ldate.getYear() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specified Gregorian year is a leap year.
|
||||
* @see #isLeapYear(Era, int)
|
||||
*/
|
||||
@Override
|
||||
public boolean isLeapYear(int gregorianYear) {
|
||||
return CalendarUtils.isGregorianLeapYear(gregorianYear);
|
||||
}
|
||||
|
||||
public boolean isLeapYear(Era era, int year) {
|
||||
if (era == null) {
|
||||
return isLeapYear(year);
|
||||
}
|
||||
int gyear = era.getSinceDate().getYear() + year - 1;
|
||||
return isLeapYear(gyear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) {
|
||||
Date ldate = (Date) date;
|
||||
super.getCalendarDateFromFixedDate(ldate, fixedDate);
|
||||
adjustYear(ldate, (fixedDate - EPOCH_OFFSET) * DAY_IN_MILLIS, 0);
|
||||
}
|
||||
}
|
||||
737
jdkSrc/jdk8/sun/util/calendar/ZoneInfo.java
Normal file
737
jdkSrc/jdk8/sun/util/calendar/ZoneInfo.java
Normal file
@@ -0,0 +1,737 @@
|
||||
/*
|
||||
* 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.ObjectInputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.security.AccessController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* <code>ZoneInfo</code> is an implementation subclass of {@link
|
||||
* java.util.TimeZone TimeZone} that represents GMT offsets and
|
||||
* daylight saving time transitions of a time zone.
|
||||
* <p>
|
||||
* The daylight saving time transitions are described in the {@link
|
||||
* #transitions transitions} table consisting of a chronological
|
||||
* sequence of transitions of GMT offset and/or daylight saving time
|
||||
* changes. Since all transitions are represented in UTC, in theory,
|
||||
* <code>ZoneInfo</code> can be used with any calendar systems except
|
||||
* for the {@link #getOffset(int,int,int,int,int,int) getOffset}
|
||||
* method that takes Gregorian calendar date fields.
|
||||
* <p>
|
||||
* This table covers transitions from 1900 until 2037 (as of version
|
||||
* 1.4), Before 1900, it assumes that there was no daylight saving
|
||||
* time and the <code>getOffset</code> methods always return the
|
||||
* {@link #getRawOffset} value. No Local Mean Time is supported. If a
|
||||
* specified date is beyond the transition table and this time zone is
|
||||
* supposed to observe daylight saving time in 2037, it delegates
|
||||
* operations to a {@link java.util.SimpleTimeZone SimpleTimeZone}
|
||||
* object created using the daylight saving time schedule as of 2037.
|
||||
* <p>
|
||||
* The date items, transitions, GMT offset(s), etc. are read from a database
|
||||
* file. See {@link ZoneInfoFile} for details.
|
||||
* @see java.util.SimpleTimeZone
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class ZoneInfo extends TimeZone {
|
||||
|
||||
private static final int UTC_TIME = 0;
|
||||
private static final int STANDARD_TIME = 1;
|
||||
private static final int WALL_TIME = 2;
|
||||
|
||||
private static final long OFFSET_MASK = 0x0fL;
|
||||
private static final long DST_MASK = 0xf0L;
|
||||
private static final int DST_NSHIFT = 4;
|
||||
// this bit field is reserved for abbreviation support
|
||||
private static final long ABBR_MASK = 0xf00L;
|
||||
private static final int TRANSITION_NSHIFT = 12;
|
||||
|
||||
private static final CalendarSystem gcal = CalendarSystem.getGregorianCalendar();
|
||||
|
||||
/**
|
||||
* The raw GMT offset in milliseconds between this zone and GMT.
|
||||
* Negative offsets are to the west of Greenwich. To obtain local
|
||||
* <em>standard</em> time, add the offset to GMT time.
|
||||
* @serial
|
||||
*/
|
||||
private int rawOffset;
|
||||
|
||||
/**
|
||||
* Difference in milliseconds from the original GMT offset in case
|
||||
* the raw offset value has been modified by calling {@link
|
||||
* #setRawOffset}. The initial value is 0.
|
||||
* @serial
|
||||
*/
|
||||
private int rawOffsetDiff = 0;
|
||||
|
||||
/**
|
||||
* A CRC32 value of all pairs of transition time (in milliseconds
|
||||
* in <code>long</code>) in local time and its GMT offset (in
|
||||
* seconds in <code>int</code>) in the chronological order. Byte
|
||||
* values of each <code>long</code> and <code>int</code> are taken
|
||||
* in the big endian order (i.e., MSB to LSB).
|
||||
* @serial
|
||||
*/
|
||||
private int checksum;
|
||||
|
||||
/**
|
||||
* The amount of time in milliseconds saved during daylight saving
|
||||
* time. If <code>useDaylight</code> is false, this value is 0.
|
||||
* @serial
|
||||
*/
|
||||
private int dstSavings;
|
||||
|
||||
/**
|
||||
* This array describes transitions of GMT offsets of this time
|
||||
* zone, including both raw offset changes and daylight saving
|
||||
* time changes.
|
||||
* A long integer consists of four bit fields.
|
||||
* <ul>
|
||||
* <li>The most significant 52-bit field represents transition
|
||||
* time in milliseconds from Gregorian January 1 1970, 00:00:00
|
||||
* GMT.</li>
|
||||
* <li>The next 4-bit field is reserved and must be 0.</li>
|
||||
* <li>The next 4-bit field is an index value to {@link #offsets
|
||||
* offsets[]} for the amount of daylight saving at the
|
||||
* transition. If this value is zero, it means that no daylight
|
||||
* saving, not the index value zero.</li>
|
||||
* <li>The least significant 4-bit field is an index value to
|
||||
* {@link #offsets offsets[]} for <em>total</em> GMT offset at the
|
||||
* transition.</li>
|
||||
* </ul>
|
||||
* If this time zone doesn't observe daylight saving time and has
|
||||
* never changed any GMT offsets in the past, this value is null.
|
||||
* @serial
|
||||
*/
|
||||
private long[] transitions;
|
||||
|
||||
/**
|
||||
* This array holds all unique offset values in
|
||||
* milliseconds. Index values to this array are stored in the
|
||||
* transitions array elements.
|
||||
* @serial
|
||||
*/
|
||||
private int[] offsets;
|
||||
|
||||
/**
|
||||
* SimpleTimeZone parameter values. It has to have either 8 for
|
||||
* {@link java.util.SimpleTimeZone#SimpleTimeZone(int, String,
|
||||
* int, int , int , int , int , int , int , int , int) the
|
||||
* 11-argument SimpleTimeZone constructor} or 10 for {@link
|
||||
* java.util.SimpleTimeZone#SimpleTimeZone(int, String, int, int,
|
||||
* int , int , int , int , int , int , int, int, int) the
|
||||
* 13-argument SimpleTimeZone constructor} parameters.
|
||||
* @serial
|
||||
*/
|
||||
private int[] simpleTimeZoneParams;
|
||||
|
||||
/**
|
||||
* True if the raw GMT offset value would change after the time
|
||||
* zone data has been generated; false, otherwise. The default
|
||||
* value is false.
|
||||
* @serial
|
||||
*/
|
||||
private boolean willGMTOffsetChange = false;
|
||||
|
||||
/**
|
||||
* True if the object has been modified after its instantiation.
|
||||
*/
|
||||
transient private boolean dirty = false;
|
||||
|
||||
private static final long serialVersionUID = 2653134537216586139L;
|
||||
|
||||
/**
|
||||
* A constructor.
|
||||
*/
|
||||
public ZoneInfo() {
|
||||
}
|
||||
|
||||
/**
|
||||
* A Constructor for CustomID.
|
||||
*/
|
||||
public ZoneInfo(String ID, int rawOffset) {
|
||||
this(ID, rawOffset, 0, 0, null, null, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ZoneInfo instance.
|
||||
*
|
||||
* @param ID time zone name
|
||||
* @param rawOffset GMT offset in milliseconds
|
||||
* @param dstSavings daylight saving value in milliseconds or 0
|
||||
* (zero) if this time zone doesn't observe Daylight Saving Time.
|
||||
* @param checksum CRC32 value with all transitions table entry
|
||||
* values
|
||||
* @param transitions transition table
|
||||
* @param offsets offset value table
|
||||
* @param simpleTimeZoneParams parameter values for constructing
|
||||
* SimpleTimeZone
|
||||
* @param willGMTOffsetChange the value of willGMTOffsetChange
|
||||
*/
|
||||
ZoneInfo(String ID,
|
||||
int rawOffset,
|
||||
int dstSavings,
|
||||
int checksum,
|
||||
long[] transitions,
|
||||
int[] offsets,
|
||||
int[] simpleTimeZoneParams,
|
||||
boolean willGMTOffsetChange) {
|
||||
setID(ID);
|
||||
this.rawOffset = rawOffset;
|
||||
this.dstSavings = dstSavings;
|
||||
this.checksum = checksum;
|
||||
this.transitions = transitions;
|
||||
this.offsets = offsets;
|
||||
this.simpleTimeZoneParams = simpleTimeZoneParams;
|
||||
this.willGMTOffsetChange = willGMTOffsetChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference in milliseconds between local time and UTC
|
||||
* of given time, taking into account both the raw offset and the
|
||||
* effect of daylight savings.
|
||||
*
|
||||
* @param date the milliseconds in UTC
|
||||
* @return the milliseconds to add to UTC to get local wall time
|
||||
*/
|
||||
public int getOffset(long date) {
|
||||
return getOffsets(date, null, UTC_TIME);
|
||||
}
|
||||
|
||||
public int getOffsets(long utc, int[] offsets) {
|
||||
return getOffsets(utc, offsets, UTC_TIME);
|
||||
}
|
||||
|
||||
public int getOffsetsByStandard(long standard, int[] offsets) {
|
||||
return getOffsets(standard, offsets, STANDARD_TIME);
|
||||
}
|
||||
|
||||
public int getOffsetsByWall(long wall, int[] offsets) {
|
||||
return getOffsets(wall, offsets, WALL_TIME);
|
||||
}
|
||||
|
||||
private int getOffsets(long date, int[] offsets, int type) {
|
||||
// if dst is never observed, there is no transition.
|
||||
if (transitions == null) {
|
||||
int offset = getLastRawOffset();
|
||||
if (offsets != null) {
|
||||
offsets[0] = offset;
|
||||
offsets[1] = 0;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
date -= rawOffsetDiff;
|
||||
int index = getTransitionIndex(date, type);
|
||||
|
||||
// prior to the transition table, returns the raw offset.
|
||||
// FIXME: should support LMT.
|
||||
if (index < 0) {
|
||||
int offset = getLastRawOffset();
|
||||
if (offsets != null) {
|
||||
offsets[0] = offset;
|
||||
offsets[1] = 0;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
if (index < transitions.length) {
|
||||
long val = transitions[index];
|
||||
int offset = this.offsets[(int)(val & OFFSET_MASK)] + rawOffsetDiff;
|
||||
if (offsets != null) {
|
||||
int dst = (int)((val >>> DST_NSHIFT) & 0xfL);
|
||||
int save = (dst == 0) ? 0 : this.offsets[dst];
|
||||
offsets[0] = offset - save;
|
||||
offsets[1] = save;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
// beyond the transitions, delegate to SimpleTimeZone if there
|
||||
// is a rule; otherwise, return rawOffset.
|
||||
SimpleTimeZone tz = getLastRule();
|
||||
if (tz != null) {
|
||||
int rawoffset = tz.getRawOffset();
|
||||
long msec = date;
|
||||
if (type != UTC_TIME) {
|
||||
msec -= rawOffset;
|
||||
}
|
||||
int dstoffset = tz.getOffset(msec) - rawOffset;
|
||||
|
||||
// Check if it's in a standard-to-daylight transition.
|
||||
if (dstoffset > 0 && tz.getOffset(msec - dstoffset) == rawoffset && type == WALL_TIME) {
|
||||
dstoffset = 0;
|
||||
}
|
||||
|
||||
if (offsets != null) {
|
||||
offsets[0] = rawoffset;
|
||||
offsets[1] = dstoffset;
|
||||
}
|
||||
return rawoffset + dstoffset;
|
||||
}
|
||||
int offset = getLastRawOffset();
|
||||
if (offsets != null) {
|
||||
offsets[0] = offset;
|
||||
offsets[1] = 0;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
private int getTransitionIndex(long date, int type) {
|
||||
int low = 0;
|
||||
int high = transitions.length - 1;
|
||||
|
||||
while (low <= high) {
|
||||
int mid = (low + high) / 2;
|
||||
long val = transitions[mid];
|
||||
long midVal = val >> TRANSITION_NSHIFT; // sign extended
|
||||
if (type != UTC_TIME) {
|
||||
midVal += offsets[(int)(val & OFFSET_MASK)]; // wall time
|
||||
}
|
||||
if (type == STANDARD_TIME) {
|
||||
int dstIndex = (int)((val >>> DST_NSHIFT) & 0xfL);
|
||||
if (dstIndex != 0) {
|
||||
midVal -= offsets[dstIndex]; // make it standard time
|
||||
}
|
||||
}
|
||||
|
||||
if (midVal < date) {
|
||||
low = mid + 1;
|
||||
} else if (midVal > date) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
|
||||
// if beyond the transitions, returns that index.
|
||||
if (low >= transitions.length) {
|
||||
return low;
|
||||
}
|
||||
return low - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference in milliseconds between local time and
|
||||
* UTC, taking into account both the raw offset and the effect of
|
||||
* daylight savings, for the specified date and time. This method
|
||||
* assumes that the start and end month are distinct. This method
|
||||
* assumes a Gregorian calendar for calculations.
|
||||
* <p>
|
||||
* <em>Note: In general, clients should use
|
||||
* {@link Calendar#ZONE_OFFSET Calendar.get(ZONE_OFFSET)} +
|
||||
* {@link Calendar#DST_OFFSET Calendar.get(DST_OFFSET)}
|
||||
* instead of calling this method.</em>
|
||||
*
|
||||
* @param era The era of the given date. The value must be either
|
||||
* GregorianCalendar.AD or GregorianCalendar.BC.
|
||||
* @param year The year in the given date.
|
||||
* @param month The month in the given date. Month is 0-based. e.g.,
|
||||
* 0 for January.
|
||||
* @param day The day-in-month of the given date.
|
||||
* @param dayOfWeek The day-of-week of the given date.
|
||||
* @param millis The milliseconds in day in <em>standard</em> local time.
|
||||
* @return The milliseconds to add to UTC to get local time.
|
||||
*/
|
||||
public int getOffset(int era, int year, int month, int day,
|
||||
int dayOfWeek, int milliseconds) {
|
||||
if (milliseconds < 0 || milliseconds >= AbstractCalendar.DAY_IN_MILLIS) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if (era == java.util.GregorianCalendar.BC) { // BC
|
||||
year = 1 - year;
|
||||
} else if (era != java.util.GregorianCalendar.AD) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
CalendarDate date = gcal.newCalendarDate(null);
|
||||
date.setDate(year, month + 1, day);
|
||||
if (gcal.validate(date) == false) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// bug-for-bug compatible argument checking
|
||||
if (dayOfWeek < java.util.GregorianCalendar.SUNDAY
|
||||
|| dayOfWeek > java.util.GregorianCalendar.SATURDAY) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if (transitions == null) {
|
||||
return getLastRawOffset();
|
||||
}
|
||||
|
||||
long dateInMillis = gcal.getTime(date) + milliseconds;
|
||||
dateInMillis -= (long) rawOffset; // make it UTC
|
||||
return getOffsets(dateInMillis, null, UTC_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base time zone offset from GMT. This operation
|
||||
* modifies all the transitions of this ZoneInfo object, including
|
||||
* historical ones, if applicable.
|
||||
*
|
||||
* @param offsetMillis the base time zone offset to GMT.
|
||||
* @see getRawOffset
|
||||
*/
|
||||
public synchronized void setRawOffset(int offsetMillis) {
|
||||
if (offsetMillis == rawOffset + rawOffsetDiff) {
|
||||
return;
|
||||
}
|
||||
rawOffsetDiff = offsetMillis - rawOffset;
|
||||
if (lastRule != null) {
|
||||
lastRule.setRawOffset(offsetMillis);
|
||||
}
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GMT offset of the current date. This GMT offset
|
||||
* value is not modified during Daylight Saving Time.
|
||||
*
|
||||
* @return the GMT offset value in milliseconds to add to UTC time
|
||||
* to get local standard time
|
||||
*/
|
||||
public int getRawOffset() {
|
||||
if (!willGMTOffsetChange) {
|
||||
return rawOffset + rawOffsetDiff;
|
||||
}
|
||||
|
||||
int[] offsets = new int[2];
|
||||
getOffsets(System.currentTimeMillis(), offsets, UTC_TIME);
|
||||
return offsets[0];
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
private int getLastRawOffset() {
|
||||
return rawOffset + rawOffsetDiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if this time zone uses Daylight Saving Time in the last known rule.
|
||||
*/
|
||||
public boolean useDaylightTime() {
|
||||
return (simpleTimeZoneParams != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean observesDaylightTime() {
|
||||
if (simpleTimeZoneParams != null) {
|
||||
return true;
|
||||
}
|
||||
if (transitions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look up the transition table to see if it's in DST right
|
||||
// now or if there's any standard-to-daylight transition at
|
||||
// any future.
|
||||
long utc = System.currentTimeMillis() - rawOffsetDiff;
|
||||
int index = getTransitionIndex(utc, UTC_TIME);
|
||||
|
||||
// before transitions in the transition table
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// the time is in the table range.
|
||||
for (int i = index; i < transitions.length; i++) {
|
||||
if ((transitions[i] & DST_MASK) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// No further DST is observed.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries if the specified date is in Daylight Saving Time.
|
||||
*/
|
||||
public boolean inDaylightTime(Date date) {
|
||||
if (date == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (transitions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long utc = date.getTime() - rawOffsetDiff;
|
||||
int index = getTransitionIndex(utc, UTC_TIME);
|
||||
|
||||
// before transitions in the transition table
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// the time is in the table range.
|
||||
if (index < transitions.length) {
|
||||
return (transitions[index] & DST_MASK) != 0;
|
||||
}
|
||||
|
||||
// beyond the transition table
|
||||
SimpleTimeZone tz = getLastRule();
|
||||
if (tz != null) {
|
||||
return tz.inDaylightTime(date);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of time in milliseconds that the clock is advanced
|
||||
* during daylight saving time is in effect in its last daylight saving time rule.
|
||||
*
|
||||
* @return the number of milliseconds the time is advanced with respect to
|
||||
* standard time when daylight saving time is in effect.
|
||||
*/
|
||||
public int getDSTSavings() {
|
||||
return dstSavings;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return the last year in the transition table or -1 if this
|
||||
// * time zone doesn't observe any daylight saving time.
|
||||
// */
|
||||
// public int getMaxTransitionYear() {
|
||||
// if (transitions == null) {
|
||||
// return -1;
|
||||
// }
|
||||
// long val = transitions[transitions.length - 1];
|
||||
// int offset = this.offsets[(int)(val & OFFSET_MASK)] + rawOffsetDiff;
|
||||
// val = (val >> TRANSITION_NSHIFT) + offset;
|
||||
// CalendarDate lastDate = Gregorian.getCalendarDate(val);
|
||||
// return lastDate.getYear();
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns a string representation of this time zone.
|
||||
* @return the string
|
||||
*/
|
||||
public String toString() {
|
||||
return getClass().getName() +
|
||||
"[id=\"" + getID() + "\"" +
|
||||
",offset=" + getLastRawOffset() +
|
||||
",dstSavings=" + dstSavings +
|
||||
",useDaylight=" + useDaylightTime() +
|
||||
",transitions=" + ((transitions != null) ? transitions.length : 0) +
|
||||
",lastRule=" + (lastRule == null ? getLastRuleInstance() : lastRule) +
|
||||
"]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all available IDs supported in the Java run-time.
|
||||
*
|
||||
* @return an array of time zone IDs.
|
||||
*/
|
||||
public static String[] getAvailableIDs() {
|
||||
return ZoneInfoFile.getZoneIds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all available IDs that have the same value as the
|
||||
* specified raw GMT offset.
|
||||
*
|
||||
* @param rawOffset the GMT offset in milliseconds. This
|
||||
* value should not include any daylight saving time.
|
||||
*
|
||||
* @return an array of time zone IDs.
|
||||
*/
|
||||
public static String[] getAvailableIDs(int rawOffset) {
|
||||
return ZoneInfoFile.getZoneIds(rawOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ZoneInfo for the given ID.
|
||||
*
|
||||
* @param ID the ID for a ZoneInfo. See TimeZone for detail.
|
||||
*
|
||||
* @return the specified ZoneInfo object, or null if there is no
|
||||
* time zone of the ID.
|
||||
*/
|
||||
public static TimeZone getTimeZone(String ID) {
|
||||
return ZoneInfoFile.getZoneInfo(ID);
|
||||
}
|
||||
|
||||
private transient SimpleTimeZone lastRule;
|
||||
|
||||
/**
|
||||
* Returns a SimpleTimeZone object representing the last GMT
|
||||
* offset and DST schedule or null if this time zone doesn't
|
||||
* observe DST.
|
||||
*/
|
||||
private synchronized SimpleTimeZone getLastRule() {
|
||||
if (lastRule == null) {
|
||||
lastRule = getLastRuleInstance();
|
||||
}
|
||||
return lastRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SimpleTimeZone object that represents the last
|
||||
* known daylight saving time rules.
|
||||
*
|
||||
* @return a SimpleTimeZone object or null if this time zone
|
||||
* doesn't observe DST.
|
||||
*/
|
||||
public SimpleTimeZone getLastRuleInstance() {
|
||||
if (simpleTimeZoneParams == null) {
|
||||
return null;
|
||||
}
|
||||
if (simpleTimeZoneParams.length == 10) {
|
||||
return new SimpleTimeZone(getLastRawOffset(), getID(),
|
||||
simpleTimeZoneParams[0],
|
||||
simpleTimeZoneParams[1],
|
||||
simpleTimeZoneParams[2],
|
||||
simpleTimeZoneParams[3],
|
||||
simpleTimeZoneParams[4],
|
||||
simpleTimeZoneParams[5],
|
||||
simpleTimeZoneParams[6],
|
||||
simpleTimeZoneParams[7],
|
||||
simpleTimeZoneParams[8],
|
||||
simpleTimeZoneParams[9],
|
||||
dstSavings);
|
||||
}
|
||||
return new SimpleTimeZone(getLastRawOffset(), getID(),
|
||||
simpleTimeZoneParams[0],
|
||||
simpleTimeZoneParams[1],
|
||||
simpleTimeZoneParams[2],
|
||||
simpleTimeZoneParams[3],
|
||||
simpleTimeZoneParams[4],
|
||||
simpleTimeZoneParams[5],
|
||||
simpleTimeZoneParams[6],
|
||||
simpleTimeZoneParams[7],
|
||||
dstSavings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this <code>ZoneInfo</code>.
|
||||
*/
|
||||
public Object clone() {
|
||||
ZoneInfo zi = (ZoneInfo) super.clone();
|
||||
zi.lastRule = null;
|
||||
return zi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value calculated from the GMT offset and
|
||||
* transitions.
|
||||
* @return a hash code of this time zone
|
||||
*/
|
||||
public int hashCode() {
|
||||
return getLastRawOffset() ^ checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the equity of two ZoneInfo objects.
|
||||
*
|
||||
* @param obj the object to be compared with
|
||||
* @return true if given object is same as this ZoneInfo object,
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof ZoneInfo)) {
|
||||
return false;
|
||||
}
|
||||
ZoneInfo that = (ZoneInfo) obj;
|
||||
return (getID().equals(that.getID())
|
||||
&& (getLastRawOffset() == that.getLastRawOffset())
|
||||
&& (checksum == that.checksum));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this zone has the same raw GMT offset value and
|
||||
* transition table as another zone info. If the specified
|
||||
* TimeZone object is not a ZoneInfo instance, this method returns
|
||||
* true if the specified TimeZone object has the same raw GMT
|
||||
* offset value with no daylight saving time.
|
||||
*
|
||||
* @param other the ZoneInfo object to be compared with
|
||||
* @return true if the given <code>TimeZone</code> has the same
|
||||
* GMT offset and transition information; false, otherwise.
|
||||
*/
|
||||
public boolean hasSameRules(TimeZone other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(other instanceof ZoneInfo)) {
|
||||
if (getRawOffset() != other.getRawOffset()) {
|
||||
return false;
|
||||
}
|
||||
// if both have the same raw offset and neither observes
|
||||
// DST, they have the same rule.
|
||||
if ((transitions == null)
|
||||
&& (useDaylightTime() == false)
|
||||
&& (other.useDaylightTime() == false)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (getLastRawOffset() != ((ZoneInfo)other).getLastRawOffset()) {
|
||||
return false;
|
||||
}
|
||||
return (checksum == ((ZoneInfo)other).checksum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Map from alias time zone IDs to their standard
|
||||
* time zone IDs.
|
||||
*
|
||||
* @return the Map that holds the mappings from alias time zone IDs
|
||||
* to their standard time zone IDs, or null if
|
||||
* <code>ZoneInfoMappings</code> file is not available.
|
||||
*/
|
||||
public static Map<String, String> getAliasTable() {
|
||||
return ZoneInfoFile.getAliasMap();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream stream)
|
||||
throws IOException, ClassNotFoundException {
|
||||
stream.defaultReadObject();
|
||||
// We don't know how this object from 1.4.x or earlier has
|
||||
// been mutated. So it should always be marked as `dirty'.
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
1007
jdkSrc/jdk8/sun/util/calendar/ZoneInfoFile.java
Normal file
1007
jdkSrc/jdk8/sun/util/calendar/ZoneInfoFile.java
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user