blob: e85d794eda703e4ab79634a4916a2c43d6562514 [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 1996-2000, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/util/Attic/BuddhistCalendar.java,v $
* $Date: 2000/03/10 04:17:57 $
* $Revision: 1.2 $
*
*****************************************************************************************
*/
package com.ibm.util;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
/**
* <code>BuddhistCalendar</code> is a subclass of <code>GregorianCalendar</code>
* that numbers years since the birth of the Buddha. This is the civil calendar
* in some predominantly Buddhist countries such as Thailand, and it is used for
* religious purposes elsewhere.
* <p>
* The Buddhist calendar is identical to the Gregorian calendar in all respects
* except for the year and era. Years are numbered since the birth of the
* Buddha in 543 BC (Gregorian), so that 1 AD (Gregorian) is equivalent to 544
* BE (Buddhist Era) and 1998 AD is 2541 BE.
* <p>
* The Buddhist Calendar has only one allowable era: <code>BE</code>. If the
* calendar is not in lenient mode (see <code>setLenient</code>), dates before
* 1/1/1 BE are rejected with an <code>IllegalArgumentException</code>.
*
* @see java.util.GregorianCalendar
*
* @author Laura Werner
*/
public class BuddhistCalendar extends GregorianCalendar {
private static String copyright = "Copyright \u00a9 1998 IBM Corp. All Rights Reserved.";
//-------------------------------------------------------------------------
// Constructors...
//-------------------------------------------------------------------------
/**
* Constant for the Buddhist Era. This is the only allowable <code>ERA</code>
* value for the Buddhist calendar.
*
* @see java.util.Calendar#ERA
*/
public static final int BE = 0;
/**
* Constructs a <code>BuddhistCalendar</code> using the current time
* in the default time zone with the default locale.
*/
public BuddhistCalendar() {
super();
}
/**
* Constructs a <code>BuddhistCalendar</code> based on the current time
* in the given time zone with the default locale.
*
* @param zone the given time zone.
*/
public BuddhistCalendar(TimeZone zone) {
super(zone);
}
/**
* Constructs a <code>BuddhistCalendar</code> based on the current time
* in the default time zone with the given locale.
*
* @param aLocale the given locale.
*/
public BuddhistCalendar(Locale aLocale) {
super(aLocale);
}
/**
* Constructs a <code>BuddhistCalendar</code> based on the current time
* in the given time zone with the given locale.
*
* @param zone the given time zone.
*
* @param aLocale the given locale.
*/
public BuddhistCalendar(TimeZone zone, Locale aLocale) {
super(zone, aLocale);
}
/**
* Constructs a <code>BuddhistCalendar</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.
*/
public BuddhistCalendar(Date date) {
super(TimeZone.getDefault(), Locale.getDefault());
this.setTime(date);
}
/**
* Constructs a <code>BuddhistCalendar</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 January.
*
* @param date The value used to set the calendar's {@link #DATE DATE} time field.
*/
public BuddhistCalendar(int year, int month, int date) {
super(year, month, date);
}
/**
* Constructs a BuddhistCalendar 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 January.
*
* @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.
*/
public BuddhistCalendar(int year, int month, int date, int hour,
int minute, int second)
{
super(year, month, date, hour, minute, second);
}
//-------------------------------------------------------------------------
// The only practical difference from a Gregorian calendar is that years
// are numbered since the birth of the Buddha. A couple of overrides will
// take care of that....
//-------------------------------------------------------------------------
/**
* Override of the <code>GregorianCalendar</code> method that computes the
* fields such as <code>YEAR</code>, <code>MONTH</code>, and <code>DATE</code>
* from the date in milliseconds since 1/1/1970 AD.
*
* This method calls {@link GregorianCalendar#computeFields} to do most
* of the work,
* then adjusts the {@link #YEAR YEAR} and {@link #ERA ERA} fields to use the
* Buddhist Era rather than the Gregorian {@link #AD AD} or {@link #BC BC}.
*/
protected void computeFields() {
// Let GregorianCalendar do its thing.
super.computeFields();
// Now adjust the year and era to the proper Buddhist values
fromGregorian();
//
// If we're in strict mode and the year is less than 1, fail.
// But do this after setting both the year and era to the right values
// anyway, so that this object is in a consistent state.
//
if (!isLenient() && fields[YEAR] < 1) {
throw new IllegalArgumentException("Time before start of Buddhist era");
}
}
/**
* Override of the <code>GregorianCalendar</code> method that computes the
* elapsed time in milliseconds since 1/1/1970 AD from the fields such
* as <code>YEAR</code>, <code>MONTH</code>, and <code>DATE</code>.
*
* This method adjusts the {@link #YEAR YEAR} and {@link #ERA ERA} from their
* values in the Buddhist calendar to the corresponding Gregorian values, calls
* {@link GregorianCalendar#computeTime} to do the real millisecond
* calculation, and then restores the Buddhist <code>YEAR</code> and
* <code>ERA</code>.
*/
protected void computeTime() {
int year = fields[YEAR];
int era = fields[ERA];
if (!isLenient()) {
if (era != BE) {
throw new IllegalArgumentException("Illegal value for ERA");
}
if (year < 1) {
throw new IllegalArgumentException("YEAR must be greater than 0");
}
}
try {
toGregorian();
super.computeTime();
}
finally {
// Set the year and era back to the Buddhist values, even if
// GregorianCalendar fails because other fields are invalid.
fields[YEAR] = year;
fields[ERA] = era;
}
}
public void add(int field, int amount) {
toGregorian();
try {
super.add(field, amount);
}
finally {
fromGregorian();
}
}
public void roll(int field, boolean up) {
toGregorian();
try {
super.roll(field, up);
}
finally {
fromGregorian();
}
}
//-------------------------------------------------------------------------
// Methods for converting between Gregorian and Buddhist calendars
//-------------------------------------------------------------------------
private static int BUDDHIST_ERA_START = -543; // Starts in -543 AD, ie 544 BC
/**
* Convert the YEAR and ERA fields from Buddhist to Gregorian values
* Return the (Buddhist) value of the YEAR field on input;
*/
private void toGregorian() {
int year = fields[YEAR];
if (year > 0) {
fields[YEAR] = year + BUDDHIST_ERA_START;
fields[ERA] = AD;
} else {
fields[YEAR] = 1 - year - BUDDHIST_ERA_START;
fields[ERA] = BC;
}
}
/**
* Adjust the year and era from Gregorian to Buddhist values
*/
private void fromGregorian() {
// Now adjust the year and era to the proper Buddhist values
int year = fields[YEAR];
if (fields[ERA] == BC) {
fields[YEAR] = 1 - year - BUDDHIST_ERA_START;
} else {
fields[YEAR] = year - BUDDHIST_ERA_START;
}
fields[ERA] = BE;
}
};