235 lines
7.5 KiB
Java
235 lines
7.5 KiB
Java
/*
|
|
* 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);
|
|
}
|
|
}
|