ICU-4082 Initial checkin of Indian calendar.

X-SVN-Rev: 22042
This commit is contained in:
Eric Mader 2007-07-18 23:43:50 +00:00
parent 345d157afc
commit 7b023cc660
6 changed files with 854 additions and 7 deletions

2
.gitattributes vendored
View file

@ -173,6 +173,7 @@ icu4j/src/com/ibm/icu/charset/CharsetUTF7.java -text
icu4j/src/com/ibm/icu/dev/data/rbbi/english.dict -text
icu4j/src/com/ibm/icu/dev/data/testdata.jar -text
icu4j/src/com/ibm/icu/dev/data/thai6.ucs -text
icu4j/src/com/ibm/icu/dev/test/calendar/IndianTest.java -text
icu4j/src/com/ibm/icu/dev/test/perf/data/collation/TestNames_Asian.txt -text
icu4j/src/com/ibm/icu/dev/test/perf/data/collation/TestNames_Chinese.txt -text
icu4j/src/com/ibm/icu/dev/test/perf/data/collation/TestNames_Japanese.txt -text
@ -263,6 +264,7 @@ icu4j/src/com/ibm/icu/util/AnnualTimeZoneRule.java -text
icu4j/src/com/ibm/icu/util/BasicTimeZone.java -text
icu4j/src/com/ibm/icu/util/CalendarServiceShim.java -text
icu4j/src/com/ibm/icu/util/DateTimeRule.java -text
icu4j/src/com/ibm/icu/util/IndianCalendar.java -text
icu4j/src/com/ibm/icu/util/InitialTimeZoneRule.java -text
icu4j/src/com/ibm/icu/util/RuleBasedTimeZone.java -text
icu4j/src/com/ibm/icu/util/TaiwanCalendar.java -text

View file

@ -0,0 +1,235 @@
/*
*******************************************************************************
* Copyright (C) 2005-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.test.calendar;
import java.util.Date;
import java.util.Locale;
import java.util.MissingResourceException;
import com.ibm.icu.impl.LocaleUtility;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.IndianCalendar;
import com.ibm.icu.util.HebrewCalendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;
/**
* Tests for the <code>IndianCalendar</code> class.
*/
public class IndianTest extends CalendarTest
{
public static void main(String args[]) throws Exception {
new IndianTest().run(args);
}
// Months in indian calendar are 0-based. Here taking 1-based names:
public static final int CHAITRA = IndianCalendar.CHAITRA + 1;
public static final int VAISAKHA = IndianCalendar.VAISAKHA + 1;
public static final int JYAISTHA = IndianCalendar.JYAISTHA + 1;
public static final int ASADHA = IndianCalendar.ASADHA + 1;
public static final int SRAVANA = IndianCalendar.SRAVANA + 1 ;
public static final int BHADRA = IndianCalendar.BHADRA + 1 ;
public static final int ASVINA = IndianCalendar.ASVINA + 1 ;
public static final int KARTIKA = IndianCalendar.KARTIKA + 1 ;
public static final int AGRAHAYANA = IndianCalendar.AGRAHAYANA + 1 ;
public static final int PAUSA = IndianCalendar.PAUSA + 1 ;
public static final int MAGHA = IndianCalendar.MAGHA + 1 ;
public static final int PHALGUNA = IndianCalendar.PHALGUNA + 1 ;
/** Constants to save typing. */
/* Test dates generated from:
* http://www.fourmilab.ch/documents/calendar/
/** A huge list of test cases to make sure that computeTime and computeFields
* work properly for a wide range of data in the Indian civil calendar.
*/
public void TestCases()
{
final TestCase[] tests = {
//
// The months in this table are 1-based rather than 0-based,
// because it's easier to edit that way.
// Indian
// Julian Day Era Year Month Day WkDay Hour Min Sec
new TestCase(1770641.5, 0, 57, ASVINA, 10, SUN, 0, 0, 0),
new TestCase(1892731.5, 0, 391, PAUSA, 18, WED, 0, 0, 0),
new TestCase(1931579.5, 0, 498, VAISAKHA, 30, MON, 0, 0, 0),
new TestCase(1974851.5, 0, 616, KARTIKA, 19, SAT, 0, 0, 0),
new TestCase(2091164.5, 0, 935, VAISAKHA, 5, SUN, 0, 0, 0),
new TestCase(2121509.5, 0, 1018, JYAISTHA, 3, SUN, 0, 0, 0),
new TestCase(2155779.5, 0, 1112, CHAITRA, 2, FRI, 0, 0, 0),
new TestCase(2174029.5, 0, 1161, PHALGUNA, 20, SAT, 0, 0, 0),
new TestCase(2191584.5, 0, 1210, CHAITRA, 13, FRI, 0, 0, 0),
new TestCase(2195261.5, 0, 1220, VAISAKHA, 7, SUN, 0, 0, 0),
new TestCase(2229274.5, 0, 1313, JYAISTHA, 22, SUN, 0, 0, 0),
new TestCase(2245580.5, 0, 1357, MAGHA, 14, WED, 0, 0, 0),
new TestCase(2266100.5, 0, 1414, CHAITRA, 20, SAT, 0, 0, 0),
new TestCase(2288542.5, 0, 1475, BHADRA, 28, SAT, 0, 0, 0),
new TestCase(2290901.5, 0, 1481, PHALGUNA, 15, SAT, 0, 0, 0),
new TestCase(2323140.5, 0, 1570, JYAISTHA, 20, WED, 0, 0, 0),
new TestCase(2334551.5, 0, 1601, BHADRA, 16, THU, 0, 0, 0),
new TestCase(2334581.5, 0, 1601, ASVINA, 15, SAT, 0, 0, 0),
new TestCase(2334610.5, 0, 1601, KARTIKA, 14, SUN, 0, 0, 0),
new TestCase(2334639.5, 0, 1601, AGRAHAYANA, 13, MON, 0, 0, 0),
new TestCase(2334668.5, 0, 1601, PAUSA, 12, TUE, 0, 0, 0),
new TestCase(2334698.5, 0, 1601, MAGHA, 12, THU, 0, 0, 0),
new TestCase(2334728.5, 0, 1601, PHALGUNA, 12, SAT, 0, 0, 0),
new TestCase(2334757.5, 0, 1602, CHAITRA, 11, SUN, 0, 0, 0),
new TestCase(2334787.5, 0, 1602, VAISAKHA, 10, TUE, 0, 0, 0),
new TestCase(2334816.5, 0, 1602, JYAISTHA, 8, WED, 0, 0, 0),
new TestCase(2334846.5, 0, 1602, ASADHA, 7, FRI, 0, 0, 0),
new TestCase(2334848.5, 0, 1602, ASADHA, 9, SUN, 0, 0, 0),
new TestCase(2348020.5, 0, 1638, SRAVANA, 2, FRI, 0, 0, 0),
new TestCase(2334934.5, 0, 1602, ASVINA, 2, TUE, 0, 0, 0),
new TestCase(2366978.5, 0, 1690, JYAISTHA, 29, SUN, 0, 0, 0),
new TestCase(2385648.5, 0, 1741, SRAVANA, 11, MON, 0, 0, 0),
new TestCase(2392825.5, 0, 1761, CHAITRA, 6, WED, 0, 0, 0),
new TestCase(2416223.5, 0, 1825, CHAITRA, 29, SUN, 0, 0, 0),
new TestCase(2425848.5, 0, 1851, BHADRA, 3, SUN, 0, 0, 0),
new TestCase(2430266.5, 0, 1863, ASVINA, 7, MON, 0, 0, 0),
new TestCase(2430833.5, 0, 1865, CHAITRA, 29, MON, 0, 0, 0),
new TestCase(2431004.5, 0, 1865, ASVINA, 15, THU, 0, 0, 0),
new TestCase(2448698.5, 0, 1913, PHALGUNA, 27, TUE, 0, 0, 0),
new TestCase(2450138.5, 0, 1917, PHALGUNA, 6, SUN, 0, 0, 0),
new TestCase(2465737.5, 0, 1960, KARTIKA, 19, WED, 0, 0, 0),
new TestCase(2486076.5, 0, 2016, ASADHA, 27, SUN, 0, 0, 0),
};
IndianCalendar testCalendar = new IndianCalendar();
testCalendar.setLenient(true);
doTestCases(tests, testCalendar);
}
public void TestBasic() {
IndianCalendar cal = new IndianCalendar();
cal.clear();
cal.set(1000, 0, 30);
logln("1000/0/30-> " +
cal.get(YEAR) + "/" +
cal.get(MONTH) + "/" +
cal.get(DATE));
cal.clear();
cal.set(1, 0, 30);
logln("1/0/30 -> " +
cal.get(YEAR) + "/" +
cal.get(MONTH) + "/" +
cal.get(DATE));
}
public void TestCoverage() {
{
// new IndianCalendar(TimeZone)
IndianCalendar cal = new IndianCalendar(TimeZone.getDefault());
if(cal == null){
errln("could not create IndianCalendar with TimeZone");
}
}
{
// new IndianCalendar(ULocale)
IndianCalendar cal = new IndianCalendar(ULocale.getDefault());
if(cal == null){
errln("could not create IndianCalendar with ULocale");
}
}
{
// new IndianCalendar(Locale)
IndianCalendar cal = new IndianCalendar(Locale.getDefault());
if(cal == null){
errln("could not create IndianCalendar with Locale");
}
}
{
// new IndianCalendar(TimeZone, Locale)
IndianCalendar cal = new IndianCalendar(TimeZone.getDefault(),Locale.getDefault());
if(cal == null){
errln("could not create IndianCalendar with TimeZone, Locale");
}
}
{
// new IndianCalendar(TimeZone, ULocale)
IndianCalendar cal = new IndianCalendar(TimeZone.getDefault(),ULocale.getDefault());
if(cal == null){
errln("could not create IndianCalendar with TimeZone, ULocale");
}
}
{
// new IndianCalendar(Date)
IndianCalendar cal = new IndianCalendar(new Date());
if(cal == null){
errln("could not create IndianCalendar with Date");
}
}
{
// new IndianCalendar(int year, int month, int date)
IndianCalendar cal = new IndianCalendar(1917, IndianCalendar.CHAITRA, 1);
if(cal == null){
errln("could not create IndianCalendar with year,month,date");
}
}
{
// new IndianCalendar(int year, int month, int date, int hour, int minute, int second)
IndianCalendar cal = new IndianCalendar(1917, IndianCalendar.CHAITRA, 1, 1, 1, 1);
if(cal == null){
errln("could not create IndianCalendar with year,month,date,hour,minute,second");
}
}
{
// data
IndianCalendar cal = new IndianCalendar(-1039, 9, 21);
Date time = cal.getTime();
String[] calendarLocales = {
"bn_IN", "gu_IN", "hi_IN", "kn_IN", "ml_IN", "or_IN", "pa_IN", "ta_IN", "te_IN"
};
String[] formatLocales = {
"en", "fr", "bn", "gu", "hi", "kn", "ml", "or", "pa", "ta", "te"
};
for (int i = 0; i < calendarLocales.length; ++i) {
String calLocName = calendarLocales[i];
Locale calLocale = LocaleUtility.getLocaleFromName(calLocName);
cal = new IndianCalendar(calLocale);
for (int j = 0; j < formatLocales.length; j++ ) {
String locName = formatLocales[j];
Locale formatLocale = LocaleUtility.getLocaleFromName(locName);
DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale);
//logln(calLocName + "/" + locName + " --> " + format.format(time));
}
}
}
}
public void TestYear() {
// Gregorian Calendar
Calendar gCal= new GregorianCalendar();
Date gToday=gCal.getTime();
gCal.add(GregorianCalendar.MONTH,2);
Date gFuture=gCal.getTime();
DateFormat gDF = DateFormat.getDateInstance(gCal,DateFormat.FULL);
logln("gregorian calendar: " + gDF.format(gToday) +
" + 2 months = " + gDF.format(gFuture));
// Indian Calendar
IndianCalendar iCal= new IndianCalendar();
Date iToday=iCal.getTime();
iCal.add(IndianCalendar.MONTH,2);
Date iFuture=iCal.getTime();
DateFormat iDF = DateFormat.getDateInstance(iCal,DateFormat.FULL);
logln("Indian calendar: " + iDF.format(iToday) +
" + 2 months = " + iDF.format(iFuture));
}
}

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2005, International Business Machines Corporation and *
* Copyright (C) 1996-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -28,6 +28,7 @@ public class TestAll extends TestGroup {
"IslamicTest",
"JapaneseTest",
"ChineseTest",
"IndianTest",
"HolidayTest"
},
"Calendars, Holiday, and Astro tests"

View file

@ -1647,14 +1647,15 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
private static final int ETHIOPIC = 3;
private static final int GREGORIAN = 4;
private static final int HEBREW = 5;
private static final int ISLAMIC = 6;
private static final int ISLAMIC_CIVIL = 7;
private static final int JAPANESE = 8;
private static final int TAIWAN = 9;
private static final int INDIAN = 6;
private static final int ISLAMIC = 7;
private static final int ISLAMIC_CIVIL = 8;
private static final int JAPANESE = 9;
private static final int TAIWAN = 10;
private static final String[] calTypes = {
"buddhist", "chinese", "coptic", "ethiopic", "gregorian", "hebrew",
"islamic", "islamic-civil", "japanese","taiwan"
"indian", "islamic", "islamic-civil", "japanese", "taiwan"
};
private static int getCalendarType(ULocale l) {
@ -1782,6 +1783,8 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
return new JapaneseCalendar(zone, locale);
case TAIWAN:
return new TaiwanCalendar(zone, locale);
case INDIAN:
return new IndianCalendar(zone, locale);
default:
throw new IllegalStateException();
}

View file

@ -0,0 +1,605 @@
/*
*******************************************************************************
* Copyright (C) 1996-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.util;
import com.ibm.icu.util.TimeZone;
import java.util.Date;
import java.util.Locale;
/**
* <code>IndianCalendar</code> is a subclass of <code>GregorianCalendar</code>
* that numbers years since the birth of the Buddha. This is the civil calendar
* which is accepted by government of India as Indian National Calendar.
* The two calendars most widely used in India today are the Vikrama calendar
* followed in North India and the Shalivahana or Saka calendar which is followed
* in South India and Maharashtra.
* A variant of the Shalivahana Calendar was reformed and standardized as the
* Indian National calendar in 1957.
* <p>
* Some details of Indian National Calendar (to be implemented) :
* The Months
* Month Length Start date (Gregorian)
* =================================================
* 1 Chaitra 30/31 March 22*
* 2 Vaisakha 31 April 21
* 3 Jyaistha 31 May 22
* 4 Asadha 31 June 22
* 5 Sravana 31 July 23
* 6 Bhadra 31 August 23
* 7 Asvina 30 September 23
* 8 Kartika 30 October 23
* 9 Agrahayana 30 November 22
* 10 Pausa 30 December 22
* 11 Magha 30 January 21
* 12 Phalguna 30 February 20
* In leap years, Chaitra has 31 days and starts on March 21 instead.
* The leap years of Gregorian calendar and Indian National Calendar are in synchornization.
* So When its a leap year in Gregorian calendar then Chaitra has 31 days.
*
* The Years
* Years are counted in the Saka Era, which starts its year 0 in 78AD (by gregorian calendar).
* So for eg. 9th June 2006 by Gregorian Calendar, is same as 19th of Jyaistha in 1928 of Saka
* era by Indian National Calendar.
* <p>
* The Indian Calendar has only one allowable era: <code>Saka Era</code>. If the
* calendar is not in lenient mode (see <code>setLenient</code>), dates before
* 1/1/1 Saka Era are rejected with an <code>IllegalArgumentException</code>.
* <p>
* This class should not be subclassed.</p>
* <p>
* IndianCalendar usually should be instantiated using
* {@link com.ibm.icu.util.Calendar#getInstance(ULocale)} passing in a <code>ULocale</code>
* with the tag <code>"@calendar=Indian"</code>.</p>
*
* @see com.ibm.icu.util.Calendar
* @see com.ibm.icu.util.GregorianCalendar
*
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public class IndianCalendar extends Calendar {
// jdk1.4.2 serialver
private static final long serialVersionUID = 3617859668165014834L;
private static String copyright = "Copyright \u00a9 1998-2007 IBM Corp. All Rights Reserved.";
/**
* Constant for Chaitra, the 1st month of the Indian year.
* @draft ICU 3.8
*/
public static final int CHAITRA = 0;
/**
* Constant for Vaisakha, the 2nd month of the Indian year.
* @draft ICU 3.8
*/
public static final int VAISAKHA = 1;
/**
* Constant for Jyaistha, the 3rd month of the Indian year.
* @draft ICU 3.8
*/
public static final int JYAISTHA = 2;
/**
* Constant for Asadha, the 4th month of the Indian year.
* @draft ICU 3.8
*/
public static final int ASADHA = 3;
/**
* Constant for Sravana, the 5th month of the Indian year.
* @draft ICU 3.8
*/
public static final int SRAVANA = 4 ;
/**
* Constant for Bhadra, the 6th month of the Indian year.
* @draft ICU 3.8
*/
public static final int BHADRA = 5 ;
/**
* Constant for Asvina, the 7th month of the Indian year.
* @draft ICU 3.8
*/
public static final int ASVINA = 6 ;
/**
* Constant for Kartika, the 8th month of the Indian year.
* @draft ICU 3.8
*/
public static final int KARTIKA = 7 ;
/**
* Constant for Agrahayana, the 9th month of the Indian year.
* @draft ICU 3.8
*/
public static final int AGRAHAYANA = 8 ;
/**
* Constant for Pausa, the 10th month of the Indian year.
* @draft ICU 3.8
*/
public static final int PAUSA = 9 ;
/**
* Constant for Magha, the 11th month of the Indian year.
* @draft ICU 3.8
*/
public static final int MAGHA = 10;
/**
* Constant for Phalguna, the 12th month of the Indian year.
* @draft ICU 3.8
*/
public static final int PHALGUNA = 11;
//-------------------------------------------------------------------------
// Constructors...
//-------------------------------------------------------------------------
/**
* Constant for the Indian Era. This is the only allowable <code>ERA</code>
* value for the Indian calendar.
*
* @see com.ibm.icu.util.Calendar#ERA
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public static final int IE = 0;
/**
* Constructs a <code>IndianCalendar</code> using the current time
* in the default time zone with the default locale.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar() {
this(TimeZone.getDefault(), ULocale.getDefault());
}
/**
* Constructs a <code>IndianCalendar</code> based on the current time
* in the given time zone with the default locale.
*
* @param zone the given time zone.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar(TimeZone zone) {
this(zone, ULocale.getDefault());
}
/**
* Constructs a <code>IndianCalendar</code> based on the current time
* in the default time zone with the given locale.
*
* @param aLocale the given locale.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar(Locale aLocale) {
this(TimeZone.getDefault(), aLocale);
}
/**
* Constructs a <code>IndianCalendar</code> based on the current time
* in the default time zone with the given locale.
*
* @param locale the given ulocale.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar(ULocale locale) {
this(TimeZone.getDefault(), locale);
}
/**
* Constructs a <code>IndianCalendar</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.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar(TimeZone zone, Locale aLocale) {
super(zone, aLocale);
setTimeInMillis(System.currentTimeMillis());
}
/**
* Constructs a <code>IndianCalendar</code> based on the current time
* in the given time zone with the given locale.
*
* @param zone the given time zone.
*
* @param locale the given ulocale.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar(TimeZone zone, ULocale locale) {
super(zone, locale);
setTimeInMillis(System.currentTimeMillis());
}
/**
* Constructs a <code>IndianCalendar</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.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar(Date date) {
super(TimeZone.getDefault(), ULocale.getDefault());
this.setTime(date);
}
/**
* Constructs a <code>IndianCalendar</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.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar(int year, int month, int date) {
super(TimeZone.getDefault(), ULocale.getDefault());
this.set(Calendar.YEAR, year);
this.set(Calendar.MONTH, month);
this.set(Calendar.DATE, date);
}
/**
* Constructs a IndianCalendar 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.
* @draft ICU 3.8
* @provisional This API might change or be removed in a future release.
*/
public IndianCalendar(int year, int month, int date, int hour,
int minute, int second)
{
super(TimeZone.getDefault(), ULocale.getDefault());
this.set(Calendar.YEAR, year);
this.set(Calendar.MONTH, month);
this.set(Calendar.DATE, date);
this.set(Calendar.HOUR_OF_DAY, hour);
this.set(Calendar.MINUTE, minute);
this.set(Calendar.SECOND, second);
}
//-------------------------------------------------------------------------
// The only practical difference from a Gregorian calendar is that years
// are numbered since the Saka Era. A couple of overrides will
// take care of that....
//-------------------------------------------------------------------------
// Starts in 78 AD,
private static final int INDIAN_ERA_START = 78;
// The Indian year starts 80 days later than the Gregorian year.
private static final int INDIAN_YEAR_START = 80;
/**
* @stable ICU 2.8
*/
protected int handleGetExtendedYear() {
int year;
if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) {
year = internalGet(EXTENDED_YEAR, 1);
} else {
// Ignore the era, as there is only one
year = internalGet(YEAR, 1);
}
return year;
}
/**
* @stable ICU 2.8
*/
protected int handleGetYearLength(int extendedYear) {
return super.handleGetYearLength(extendedYear);
}
protected int handleGetMonthLength(int extendedYear, int month) {
if(isGregorianLeap(extendedYear) && month == 0) {
return 31;
}
if(month >= 1 && month <=5) {
return 31;
}
return 30;
}
/**
* @stable ICU 2.8
*/
protected void handleComputeFields(int julianDay){
double jdAtStartOfGregYear;
int leapMonth, IndianYear, yday, IndianMonth, IndianDayOfMonth, mday;
int[] gregorianDay; // Stores gregorian date corresponding to Julian day;
gregorianDay = jdToGregorian(julianDay); // Gregorian date for Julian day
IndianYear = gregorianDay[0] - INDIAN_ERA_START; // Year in Saka era
jdAtStartOfGregYear = gregorianToJD(gregorianDay[0], 1, 1); // JD at start of Gregorian year
yday = (int)(julianDay - jdAtStartOfGregYear); // Day number in Gregorian year (starting from 0)
leapMonth = isGregorianLeap(gregorianDay[0]) ? 31 : 30; // Days in leapMonth this year
if (yday < INDIAN_YEAR_START) {
// Day is at the end of the preceding Saka year
IndianYear -= 1;
yday += leapMonth + (31 * 5) + (30 * 3) + 10 + INDIAN_YEAR_START;
}
yday -= INDIAN_YEAR_START;
if (yday < leapMonth) {
IndianMonth = 0;
IndianDayOfMonth = yday + 1;
} else {
mday = yday - leapMonth;
if (mday < (31 * 5)) {
IndianMonth = (int)Math.floor(mday / 31) + 1;
IndianDayOfMonth = (mday % 31) + 1;
} else {
mday -= 31 * 5;
IndianMonth = (int)Math.floor(mday / 30) + 6;
IndianDayOfMonth = (mday % 30) + 1;
}
}
internalSet(ERA, 0);
internalSet(EXTENDED_YEAR, IndianYear);
internalSet(YEAR, IndianYear);
internalSet(MONTH, IndianMonth);
internalSet(DAY_OF_MONTH, IndianDayOfMonth );
}
private static final int[][] MONTH_COUNT = {
//len len2 st st2
{ 31, 31, 0, 0 }, // Jan
{ 28, 29, 31, 31 }, // Feb
{ 31, 31, 59, 60 }, // Mar
{ 30, 30, 90, 91 }, // Apr
{ 31, 31, 120, 121 }, // May
{ 30, 30, 151, 152 }, // Jun
{ 31, 31, 181, 182 }, // Jul
{ 31, 31, 212, 213 }, // Aug
{ 30, 30, 243, 244 }, // Sep
{ 31, 31, 273, 274 }, // Oct
{ 30, 30, 304, 305 }, // Nov
{ 31, 31, 334, 335 } // Dec
// 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
};
private static final int LIMITS[][] = {
// Minimum Greatest Least Maximum
// Minimum Maximum
{ 0, 0, 0, 0 }, // ERA
{ 1, 1, 5000000, 5000000 }, // YEAR
{ 0, 0, 11, 11 }, // MONTH
{ 1, 1, 52, 53 }, // WEEK_OF_YEAR
{ 0, 0, 4, 6 }, // WEEK_OF_MONTH
{ 1, 1, 30, 31 }, // 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
{ -5000001, -5000001, 5000001, 5000001 }, // YEAR_WOY
{/* */}, // DOW_LOCAL
{ -5000000, -5000000, 5000000, 5000000 }, // EXTENDED_YEAR
{/* */}, // JULIAN_DAY
{/* */}, // MILLISECONDS_IN_DAY
};
/**
* Override Calendar.
* @stable ICU 2.8
*/
protected int handleGetLimit(int field, int limitType) {
return LIMITS[field][limitType];
}
/**
* Return JD of start of given month/year
* @stable ICU 2.0
*/
protected int handleComputeMonthStart(int year, int month, boolean useMonth) {
//month is 0 based; converting it to 1-based
int imonth;
if(month == 12) {
imonth = 1;
} else {
imonth = month +1;
}
double jd = IndianToJD(year ,imonth, 1);
return (int)jd;
}
/**
* This routine converts an Indian date to the corresponding Julian date"
* @param year The year in Saka Era according to Indian calendar.
* @param month The month according to Indian calendar (between 1 to 12)
* @param date The date in month
*/
protected static double IndianToJD(int year, int month, int date) {
int leapMonth, gyear, m;
double start, jd;
gyear = year + INDIAN_ERA_START;
if(isGregorianLeap(gyear)) {
leapMonth = 31;
start = gregorianToJD(gyear, 3, 21);
} else {
leapMonth = 30;
start = gregorianToJD(gyear, 3, 22);
}
if (month == 1) {
jd = start + (date - 1);
} else {
jd = start + leapMonth;
m = month - 2;
m = Math.min(m, 5);
jd += m * 31;
if (month >= 8) {
m = month - 7;
jd += m * 30;
}
jd += date - 1;
}
return jd;
}
/*
* The following function is not needed for basic calendar functioning.
* This routine converts a gregorian date to the corresponding Julian date"
* @param year The year in standard Gregorian calendar (AD/BC) .
* @param month The month according to Gregorian calendar (between 0 to 11)
* @param date The date in month
*/
protected static double gregorianToJD(int year, int month, int date) {
double JULIAN_EPOCH = 1721425.5;
double jd = (JULIAN_EPOCH - 1) +
(365 * (year - 1)) +
Math.floor((year - 1) / 4) +
(-Math.floor((year - 1) / 100)) +
Math.floor((year - 1) / 400) +
Math.floor((((367 * month) - 362) / 12) +
((month <= 2) ? 0 :
(isGregorianLeap(year) ? -1 : -2)
) +
date);
return jd;
}
/*
* The following function is not needed for basic calendar functioning.
* This routine converts a julian day (jd) to the corresponding date in Gregorian calendar"
* @param jd The Julian date in Julian Calendar which is to be converted to Indian date"
*/
protected static int[] jdToGregorian(double jd) {
double JULIAN_EPOCH = 1721425.5;
double wjd, depoch, quadricent, dqc, cent, dcent, quad, dquad, yindex, yearday, leapadj;
int year, month, day;
wjd = Math.floor(jd - 0.5) + 0.5;
depoch = wjd - JULIAN_EPOCH;
quadricent = Math.floor(depoch / 146097);
dqc = depoch % 146097;
cent = Math.floor(dqc / 36524);
dcent = dqc % 36524;
quad = Math.floor(dcent / 1461);
dquad = dcent % 1461;
yindex = Math.floor(dquad / 365);
year = (int)((quadricent * 400) + (cent * 100) + (quad * 4) + yindex);
if (!((cent == 4) || (yindex == 4))) {
year++;
}
yearday = wjd - gregorianToJD(year, 1, 1);
leapadj = ((wjd < gregorianToJD(year, 3, 1)) ? 0
:
(isGregorianLeap(year) ? 1 : 2)
);
month = (int)Math.floor((((yearday + leapadj) * 12) + 373) / 367);
day = (int)(wjd - gregorianToJD(year, month, 1)) + 1;
int[] julianDate = new int[3];
julianDate[0] = year;
julianDate[1] = month;
julianDate[2] = day;
return julianDate;
}
/*
* The following function is not needed for basic calendar functioning.
* This routine checks if the Gregorian year is a leap year"
* @param year The year in Gregorian Calendar
*/
protected static boolean isGregorianLeap(int year)
{
return ((year % 4) == 0) &&
(!(((year % 100) == 0) && ((year % 400) != 0)));
}
/**
* Return the current Calendar type.
* @return type of calendar (gregorian, etc.)
* @internal ICU 3.0
*/
public String getType() {
return "indian";
}
}

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 2003-2006, International Business Machines Corporation and *
* Copyright (C) 2003-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
******************************************************************************
*/
@ -685,6 +685,7 @@ public final class ULocale implements Serializable {
{ "zh_XIANG", "zh__XIANG", null, null }, /* registered name */
{ "zh_YUE", "zh__YUE", null, null }, /* registered name */
{ "th_TH_TRADITIONAL", "th_TH", "calendar", "buddhist" },
{ "hi_IN_TRADITIONAL", "hi_IN", "calendar", "indian" },
{ "zh_TW_STROKE", "zh_TW", "collation", "stroke" },
{ "zh__PINYIN", "zh", "collation", "pinyin" }
};