blob: a3644572e25aa282a629b343046a5d895b656017 [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 2005, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.util;
import java.util.Date;
import java.util.Locale;
/**
* Base class for EthiopicCalendar and CopticCalendar.
* @internal
*/
class CECalendar extends Calendar {
// jdk1.4.2 serialver
private static final long serialVersionUID = -999547623066414271L;
private static final int LIMITS[][] = {
// Minimum Greatest Least Maximum
// Minimum Maximum
{0, 0, 1, 1 }, // ERA
{1, 1, 5828963, 5838270 }, // YEAR
{0, 0, 13, 13 }, // MONTH
{1, 1, 52, 53 }, // WEEK_OF_YEAR
{0, 0, 1, 6 }, // WEEK_OF_MONTH
{1, 1, 5, 30 }, // DAY_OF_MONTH
{1, 1, 365, 366 }, // DAY_OF_YEAR
{/* */}, // DAY_OF_WEEK
{-1, -1, 4, 6 }, // DAY_OF_WEEK_IN_MONTH
{/* */}, // AM_PM
{/* */}, // HOUR
{/* */}, // HOUR_OF_DAY
{/* */}, // MINUTE
{/* */}, // SECOND
{/* */}, // MILLISECOND
{/* */}, // ZONE_OFFSET
{/* */}, // DST_OFFSET
{-5838270, -5838270, 5828964, 5838271}, // YEAR_WOY
{/* */}, // DOW_LOCAL
{-5838269, -5838269, 5828963, 5838270}, // EXTENDED_YEAR
{/* */}, // JULIAN_DAY
{/* */}, // MILLISECONDS_IN_DAY
};
private static final int[][] ceMONTH_COUNT = {
//len len2 st st2
{30, 30, 0, 0}, // Meskerem
{30, 30, 30, 30}, // Tekemt
{30, 30, 60, 60}, // Hedar
{30, 30, 90, 90}, // Tahsas
{30, 30, 120, 120}, // Ter
{30, 30, 150, 150}, // Yekatit
{30, 30, 180, 180}, // Megabit
{30, 30, 210, 210}, // Miazia
{30, 30, 240, 244}, // Genbot
{30, 30, 270, 270}, // Sene
{30, 30, 300, 300}, // Hamle
{30, 30, 330, 330}, // Nehasse
{ 5, 6, 360, 360} // Pwagme
// len length of month
// len2 length of month in a leap year
// st days in year before start of month
// st2 days in year before month in leap year
};
// The Coptic and Ethiopic calendars differ only in their epochs.
// We handle this by setting the jdOffset to the difference between
// the Julian and Coptic or Ethiopic epoch.
// This value is set in the class initialization phase of the two
// subclasses, CopticCalendar and EthiopicCalendar
protected int jdEpochOffset = -1;
protected int handleGetLimit(int field, int limitType) {
return LIMITS[field][limitType];
}
//-------------------------------------------------------------------------
// Constructors...
//-------------------------------------------------------------------------
/**
* Constructs a default <code>CECalendar</code> using the current time
* in the default time zone with the default locale.
*/
protected CECalendar() {
this(TimeZone.getDefault(), ULocale.getDefault());
}
/**
* Constructs a <code>CECalendar</code> based on the current time
* in the given time zone with the default locale.
*
* @param zone The time zone for the new calendar.
*/
protected CECalendar(TimeZone zone) {
this(zone, ULocale.getDefault());
}
/**
* Constructs a <code>CECalendar</code> based on the current time
* in the default time zone with the given locale.
*
* @param aLocale The locale for the new calendar.
*/
protected CECalendar(Locale aLocale) {
this(TimeZone.getDefault(), aLocale);
}
/**
* Constructs a <code>CECalendar</code> based on the current time
* in the default time zone with the given locale.
*
* @param locale The locale for the new calendar.
*/
protected CECalendar(ULocale locale) {
this(TimeZone.getDefault(), locale);
}
/**
* Constructs a <code>CECalendar</code> based on the current time
* in the given time zone with the given locale.
*
* @param zone The time zone for the new calendar.
*
* @param aLocale The locale for the new calendar.
*/
protected CECalendar(TimeZone zone, Locale aLocale) {
super(zone, aLocale);
setTimeInMillis(System.currentTimeMillis());
}
/**
* Constructs a <code>CECalendar</code> based on the current time
* in the given time zone with the given locale.
*
* @param zone The time zone for the new calendar.
*
* @param locale The locale for the new calendar.
*/
protected CECalendar(TimeZone zone, ULocale locale) {
super(zone, locale);
setTimeInMillis(System.currentTimeMillis());
}
/**
* Constructs a <code>CECalendar</code> with the given date set
* in the default time zone with the default locale.
*
* @param year The value used to set the calendar's {@link #YEAR YEAR} time field.
*
* @param month The value used to set the calendar's {@link #MONTH MONTH} time field.
* The value is 0-based. e.g., 0 for Tishri.
*
* @param date The value used to set the calendar's {@link #DATE DATE} time field.
*/
protected CECalendar(int year, int month, int date) {
super(TimeZone.getDefault(), ULocale.getDefault());
this.set(year, month, date);
}
/**
* Constructs a <code>CECalendar</code> with the given date set
* in the default time zone with the default locale.
*
* @param date The date to which the new calendar is set.
*/
protected CECalendar(Date date) {
super(TimeZone.getDefault(), ULocale.getDefault());
this.setTime(date);
}
/**
* Constructs a <code>CECalendar</code> with the given date
* and time set for the default time zone with the default locale.
*
* @param year The value used to set the calendar's {@link #YEAR YEAR} time field.
* @param month The value used to set the calendar's {@link #MONTH MONTH} time field.
* The value is 0-based. e.g., 0 for Tishri.
* @param date The value used to set the calendar's {@link #DATE DATE} time field.
* @param hour The value used to set the calendar's {@link #HOUR_OF_DAY HOUR_OF_DAY} time field.
* @param minute The value used to set the calendar's {@link #MINUTE MINUTE} time field.
* @param second The value used to set the calendar's {@link #SECOND SECOND} time field.
*/
protected CECalendar(int year, int month, int date, int hour,
int minute, int second)
{
super(TimeZone.getDefault(), ULocale.getDefault());
this.set(year, month, date, hour, minute, second);
}
//-------------------------------------------------------------------------
// Calendar system Converstion methods...
//-------------------------------------------------------------------------
/**
* @internal
*/
protected int handleComputeMonthStart(int eyear,
int emonth,
boolean useMonth) {
return ceToJD(eyear, emonth, 0, jdEpochOffset);
}
/**
* @internal
*/
protected int handleGetExtendedYear() {
int year;
if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) {
year = internalGet(EXTENDED_YEAR, 1); // Default to year 1
} else {
year = internalGet(YEAR, 1); // Default to year 1
}
return year;
}
/**
* @internal
*/
protected void handleComputeFields(int julianDay) {
Integer[] date = getDateFromJD(julianDay, jdEpochOffset);
int _year = date[0].intValue();
int _month = date[1].intValue();
int _day = date[2].intValue();
int ceyear = 0;
// Do we want to use EthiopicCalendar.AA, .AM here?
int era = GregorianCalendar.AD;
if (_year < 0) { // dlf: this is what the test says to do
era = GregorianCalendar.BC;
ceyear = 1 - _year;
} else {
ceyear = _year;
}
internalSet(MONTH, _month);
internalSet(DAY_OF_MONTH, _day);
internalSet(DAY_OF_YEAR, (30 * _month) + _day);
internalSet(EXTENDED_YEAR, ceyear);
internalSet(ERA, era);
internalSet(YEAR, _year);
}
/**
* @internal
*/
public static int ceToJD(long year, int month, int date, int jdEpochOffset) {
// Julian<->Ethiopic algorithms from:
// "Calendars in Ethiopia", Berhanu Beyene, Manfred Kudlek, International Conference
// of Ethiopian Studies XV, Hamburg, 2003
return (int) (
(jdEpochOffset+365) // difference from Julian epoch to 1,1,1
+ 365 * (year - 1) // number of days from years
+ quotient(year, 4) // extra day of leap year
+ 30 * (month + 1) // number of days from months
+ date // number of days for present month
- 31 // slack?
);
}
/**
* @internal
* @deprecated This is a draft API and might change in a future release of ICU.
*/
public static Integer[] getDateFromJD(int julianDay, int jdEpochOffset) {
// 1461 is the number of days in 4 years
long r4 = mod(julianDay - jdEpochOffset, 1461); // number of days within a 4 year period
long n = mod(r4, 365) + 365 * quotient(r4, 1460); // days in present year
long aprime = 4 // number of years in the leap year cycle
* quotient(julianDay - jdEpochOffset, 1461) // number of 4 year periods between epochs?
+ quotient(r4, 365) // number of regular years?
- quotient(r4, 1460) // number of 4 year periods?
- 1;
int _year = (int) (aprime + 1);
int _month = (int) (quotient(n, 30));
int _day = mod(n, 30) + 1;
return new Integer[]{ new Integer(_year), new Integer(_month), new Integer(_day) };
}
/**
* These utility functions can be replaced by equivalent
* functions from ICU if available.
*/
static int mod(long i, int j) {
return (int) (i - (long) j * quotient(i, j));
}
static int quotient(long i, int j) {
return (int) Math.floor((double) i / j);
}
}