ICU-10249 Implement new Islamic calendar variants tbla, rgsa

X-SVN-Rev: 34172
This commit is contained in:
Scott Russell 2013-09-03 22:26:48 +00:00
parent b8227cab88
commit d2d0d0d9f0
3 changed files with 95 additions and 16 deletions

View file

@ -25,7 +25,6 @@ import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.IslamicCalendar.CalculationType;
import com.ibm.icu.util.ULocale.Category;
/**
@ -1881,15 +1880,11 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
cal = new PersianCalendar(zone, locale);
break;
case CALTYPE_ISLAMIC_CIVIL:
cal = new IslamicCalendar(zone, locale);
break;
case CALTYPE_ISLAMIC_UMALQURA :
cal=new IslamicCalendar (zone,locale);
((IslamicCalendar)cal).setType(CalculationType.ISLAMIC_UMALQURA);
break;
case CALTYPE_ISLAMIC_TBLA:
case CALTYPE_ISLAMIC_RGSA:
case CALTYPE_ISLAMIC:
cal = new IslamicCalendar(zone, locale);
((IslamicCalendar)cal).setType(CalculationType.ISLAMIC);
break;
case CALTYPE_HEBREW:
cal = new HebrewCalendar(zone, locale);
@ -1919,9 +1914,6 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
cal.setFirstDayOfWeek(MONDAY);
cal.setMinimalDaysInFirstWeek(4);
break;
case CALTYPE_ISLAMIC_TBLA:
case CALTYPE_ISLAMIC_RGSA:
// Need to add handling for these, meanwhile fall through to default
default:
// we must not get here, because unknown type is mapped to
// Gregorian at the beginning of this method.

View file

@ -12,6 +12,7 @@ import java.util.Locale;
import com.ibm.icu.impl.CalendarAstronomer;
import com.ibm.icu.impl.CalendarCache;
import com.ibm.icu.impl.CalendarUtil;
import com.ibm.icu.util.ULocale.Category;
/**
@ -167,6 +168,15 @@ public class IslamicCalendar extends Calendar {
private static final long HIJRA_MILLIS = -42521587200000L; // 7/16/622 AD 00:00
/**
* Friday EPOC
*/
private static final long CIVIL_EPOC = 1948440;
/**
* Thursday EPOC
*/
private static final long ASTRONOMICAL_EPOC = 1948439;
//-------------------------------------------------------------------------
// Constructors...
//-------------------------------------------------------------------------
@ -228,8 +238,7 @@ public class IslamicCalendar extends Calendar {
*/
public IslamicCalendar(TimeZone zone, Locale aLocale)
{
super(zone, aLocale);
setTimeInMillis(System.currentTimeMillis());
this(zone, ULocale.forLocale(aLocale));
}
/**
@ -243,6 +252,7 @@ public class IslamicCalendar extends Calendar {
public IslamicCalendar(TimeZone zone, ULocale locale)
{
super(zone, locale);
setCalcTypeForLocale(locale);
setTimeInMillis(System.currentTimeMillis());
}
@ -504,6 +514,7 @@ public class IslamicCalendar extends Calendar {
private long yearStart(int year) {
long ys = 0;
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && year < UMALQURA_YEAR_START )) {
ys = (year-1)*354 + (long)Math.floor((3+11*year)/30.0);
} else if(cType == CalculationType.ISLAMIC) {
@ -532,6 +543,7 @@ public class IslamicCalendar extends Calendar {
int realMonth = month % 12;
long ms = 0;
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && year < UMALQURA_YEAR_START )) {
ms = (long)Math.ceil(29.5*realMonth)
+ (realYear-1)*354 + (long)Math.floor((3+11*realYear)/30.0);
@ -656,7 +668,8 @@ public class IslamicCalendar extends Calendar {
int length = 0;
if (cType == CalculationType.ISLAMIC_CIVIL
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && (extendedYear < UMALQURA_YEAR_START || extendedYear > UMALQURA_YEAR_END) )) {
length = 29 + (month+1) % 2;
if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
@ -683,6 +696,7 @@ public class IslamicCalendar extends Calendar {
protected int handleGetYearLength(int extendedYear) {
int length =0;
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && (extendedYear < UMALQURA_YEAR_START || extendedYear > UMALQURA_YEAR_END) )) {
length = 354 + (civilLeapYear(extendedYear) ? 1 : 0);
} else if (cType == CalculationType.ISLAMIC) {
@ -744,9 +758,12 @@ public class IslamicCalendar extends Calendar {
protected void handleComputeFields(int julianDay) {
int year =0, month=0, dayOfMonth=0, dayOfYear=0;
long monthStart;
long days = julianDay - 1948440;
long days = julianDay - CIVIL_EPOC;
if (cType == CalculationType.ISLAMIC_CIVIL) {
if (cType == CalculationType.ISLAMIC_CIVIL || cType == CalculationType.ISLAMIC_TBLA) {
if (cType == CalculationType.ISLAMIC_TBLA) {
days = julianDay - ASTRONOMICAL_EPOC;
}
// Use the civil calendar approximation, which is just arithmetic
year = (int)Math.floor( (30 * days + 10646) / 10631.0 );
month = (int)Math.ceil((days - 29 - yearStart(year)) / 29.5 );
@ -823,7 +840,7 @@ public class IslamicCalendar extends Calendar {
*
* @draft ICU 52
*/
public enum CalculationType {ISLAMIC, ISLAMIC_CIVIL, ISLAMIC_UMALQURA};
public enum CalculationType {ISLAMIC, ISLAMIC_CIVIL, ISLAMIC_UMALQURA, ISLAMIC_TBLA};
/**
* sets the calculation type for this calendar.
@ -840,6 +857,22 @@ public class IslamicCalendar extends Calendar {
civil = false;
}
/**
* set type based on locale
*/
private void setCalcTypeForLocale(ULocale locale) {
String localeCalType = CalendarUtil.getCalendarType(locale);
if("islamic-civil".equals(localeCalType))
setType(CalculationType.ISLAMIC_CIVIL);
else if("islamic-umalqura".equals(localeCalType))
setType(CalculationType.ISLAMIC_UMALQURA);
else if("islamic-tbla".equals(localeCalType))
setType(CalculationType.ISLAMIC_TBLA);
else
setType(CalculationType.ISLAMIC); // needs to be last so it's always the default
}
/**
* {@inheritDoc}
* @stable ICU 3.8
@ -847,6 +880,8 @@ public class IslamicCalendar extends Calendar {
public String getType() {
if(cType == CalculationType.ISLAMIC_CIVIL) {
return "islamic-civil";
} else if (cType == CalculationType.ISLAMIC_TBLA) {
return "islamic-tbla";
} else if (cType == CalculationType.ISLAMIC) {
return "islamic";
} else {

View file

@ -494,4 +494,56 @@ public class IslamicTest extends CalendarTest {
}
}
public void Test10249() {
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date date = formatter.parse("1975-05-06");
IslamicCalendar is_cal = new IslamicCalendar();
is_cal.setType(CalculationType.ISLAMIC_CIVIL);
is_cal.setTime(date);
IslamicCalendar is_cal2 = new IslamicCalendar();
is_cal2.setType(CalculationType.ISLAMIC_TBLA);
is_cal2.setTime(date);
int is_day = is_cal.get(Calendar.DAY_OF_MONTH);
int is_day2 = is_cal2.get(Calendar.DAY_OF_MONTH);
if(is_day2 - is_day != 1)
errln("unexpected difference between civil and tbla: "+is_day2+" : "+is_day);
}catch(Exception e){
errln(e.getLocalizedMessage());
}
}
public void TestCreationByLocale() {
ULocale islamicLoc = new ULocale("ar_SA@calendar=islamic-umalqura");
IslamicCalendar is_cal = new IslamicCalendar(islamicLoc);
String thisCalcType = is_cal.getType();
if(!"islamic-umalqura".equalsIgnoreCase(thisCalcType)) {
errln("non umalqura calc type generated - " + thisCalcType);
}
islamicLoc = new ULocale("ar_SA@calendar=islamic-civil");
is_cal = new IslamicCalendar(islamicLoc);
thisCalcType = is_cal.getType();
if(!"islamic-civil".equalsIgnoreCase(thisCalcType)) {
errln("non civil calc type generated - " + thisCalcType);
}
islamicLoc = new ULocale("ar_SA@calendar=islamic-tbla");
is_cal = new IslamicCalendar(islamicLoc);
thisCalcType = is_cal.getType();
if(!"islamic-tbla".equalsIgnoreCase(thisCalcType)) {
errln("non tbla calc type generated - " + thisCalcType);
}
islamicLoc = new ULocale("ar_SA@calendar=islamic-xyzzy");
is_cal = new IslamicCalendar(islamicLoc);
thisCalcType = is_cal.getType();
if(!"islamic".equalsIgnoreCase(thisCalcType)) {
errln("incorrect default calc type generated - " + thisCalcType);
}
}
}