ICU-10249 Implement new islamic calendar variants tbla, rgsa

X-SVN-Rev: 34354
This commit is contained in:
Scott Russell 2013-09-17 16:55:02 +00:00
parent 1e57298e3f
commit c42e57a06c
5 changed files with 66 additions and 12 deletions

View file

@ -323,9 +323,14 @@ static Calendar *createStandardCalendar(ECalType calType, const Locale &loc, UEr
case CALTYPE_PERSIAN:
cal = new PersianCalendar(loc, status);
break;
case CALTYPE_ISLAMIC_TBLA:
cal = new IslamicCalendar(loc, status, IslamicCalendar::TBLA);
break;
case CALTYPE_ISLAMIC_CIVIL:
cal = new IslamicCalendar(loc, status, IslamicCalendar::CIVIL);
break;
case CALTYPE_ISLAMIC_RGSA:
// default any region specific not handled individually to islamic
case CALTYPE_ISLAMIC:
cal = new IslamicCalendar(loc, status, IslamicCalendar::ASTRONOMICAL);
break;
@ -358,9 +363,6 @@ static Calendar *createStandardCalendar(ECalType calType, const Locale &loc, UEr
case CALTYPE_DANGI:
cal = new DangiCalendar(loc, status);
break;
case CALTYPE_ISLAMIC_TBLA:
case CALTYPE_ISLAMIC_RGSA:
// Need to add handling for these, meanwhile fall through to default
default:
status = U_UNSUPPORTED_ERROR;
}

View file

@ -82,6 +82,8 @@ const char *IslamicCalendar::getType() const {
return "islamic-civil";
} else if(civil==ASTRONOMICAL){
return "islamic";
} else if(civil==TBLA){
return "islamic-tbla";
} else {
return "islamic-umalqura";
}
@ -198,7 +200,7 @@ UBool IslamicCalendar::civilLeapYear(int32_t year)
* from the Hijri epoch, origin 0.
*/
int32_t IslamicCalendar::yearStart(int32_t year) const{
if (civil == CIVIL ||
if (civil == CIVIL || civil == TBLA ||
(civil == UMALQURA && year < UMALQURA_YEAR_START))
{
return (year-1)*354 + ClockMath::floorDivide((3+11*year),30);
@ -222,7 +224,7 @@ int32_t IslamicCalendar::yearStart(int32_t year) const{
* @param year The hijri month, 0-based
*/
int32_t IslamicCalendar::monthStart(int32_t year, int32_t month) const {
if (civil == CIVIL) {
if (civil == CIVIL || civil == TBLA) {
return (int32_t)uprv_ceil(29.5*month)
+ (year-1)*354 + (int32_t)ClockMath::floorDivide((3+11*year),30);
} else if(civil==ASTRONOMICAL){
@ -340,7 +342,7 @@ int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t mont
int32_t length = 0;
if (civil == CIVIL ||
if (civil == CIVIL || civil == TBLA ||
(civil == UMALQURA && (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END)) ) {
length = 29 + (month+1) % 2;
if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
@ -360,7 +362,7 @@ int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t mont
* @draft ICU 2.4
*/
int32_t IslamicCalendar::handleGetYearLength(int32_t extendedYear) const {
if (civil == CIVIL ||
if (civil == CIVIL || civil == TBLA ||
(civil == UMALQURA && (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END)) ) {
return 354 + (civilLeapYear(extendedYear) ? 1 : 0);
} else if(civil == ASTRONOMICAL){
@ -422,9 +424,11 @@ int32_t IslamicCalendar::handleGetExtendedYear() {
void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) {
int32_t year, month, dayOfMonth, dayOfYear;
UDate startDate;
int32_t days = julianDay - 1948440;
int32_t days = julianDay - CIVIL_EPOC;
if (civil == CIVIL) {
if (civil == CIVIL || civil == TBLA) {
if(civil == TBLA)
days = julianDay - ASTRONOMICAL_EPOC;
// Use the civil calendar approximation, which is just arithmetic
year = (int)ClockMath::floorDivide( (double)(30 * days + 10646) , 10631.0 );
month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 );

View file

@ -94,7 +94,8 @@ class U_I18N_API IslamicCalendar : public Calendar {
enum ECivil {
ASTRONOMICAL,
CIVIL,
UMALQURA
UMALQURA,
TBLA
};
/**
@ -178,7 +179,6 @@ class U_I18N_API IslamicCalendar : public Calendar {
};
//-------------------------------------------------------------------------
// Constructors...
//-------------------------------------------------------------------------
@ -441,6 +441,17 @@ class U_I18N_API IslamicCalendar : public Calendar {
static const int32_t UMALQURA_YEAR_END = 1480;
/**
* Friday EPOC
*/
static const int32_t CIVIL_EPOC = 1948440;
/**
* Thursday EPOC
*/
static const int32_t ASTRONOMICAL_EPOC = 1948439;
static const int getUmalqura_MonthLength(int i, int j){
static const int UMALQURA_MONTHLENGTH[] = {

View file

@ -3,7 +3,6 @@
* Copyright (c) 1997-2013, International Business Machines Corporation
* and others. All Rights Reserved.
************************************************************************/
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
@ -286,6 +285,13 @@ void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
logln("Test8449---"); logln("");
Test8449();
}
break;
case 32:
name = "Test10249";
if(exec) {
logln("Test10249---"); logln("");
Test10249();
}
break;
default: name = ""; break;
}
@ -2844,6 +2850,36 @@ void CalendarTest::Test8449() {
delete tstCal;
}
void CalendarTest::Test10249() {
UErrorCode status = U_ZERO_ERROR;
Locale islamicLoc("ar_SA@calendar=islamic-civil");
Locale tblaLoc("ar_SA@calendar=islamic-tbla");
SimpleDateFormat* formatter = new SimpleDateFormat("yyyy-MM-dd", Locale::getUS(), status);
UDate date = formatter->parse("1975-05-06", status);
Calendar* tstCal = Calendar::createInstance(islamicLoc, status);
tstCal->setTime(date, status);
int32_t is_day = tstCal->get(UCAL_DAY_OF_MONTH,status);
int32_t is_month = tstCal->get(UCAL_MONTH,status);
int32_t is_year = tstCal->get(UCAL_YEAR,status);
TEST_CHECK_STATUS;
delete tstCal;
tstCal = Calendar::createInstance(tblaLoc, status);
tstCal->setTime(date, status);
int32_t tbla_day = tstCal->get(UCAL_DAY_OF_MONTH,status);
int32_t tbla_month = tstCal->get(UCAL_MONTH,status);
int32_t tbla_year = tstCal->get(UCAL_YEAR,status);
TEST_CHECK_STATUS;
if(tbla_month != is_month || tbla_year != is_year)
errln("unexpected difference between islamic and tbla month %d : %d and/or year %d : %d",tbla_month,is_month,tbla_year,is_year);
if(tbla_day - is_day != 1)
errln("unexpected day difference between islamic and tbla: %d : %d ",tbla_day,is_day);
delete tstCal;
delete formatter;
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -220,6 +220,7 @@ public: // package
void Test3785(void);
void Test1624(void);
void Test8449(void);
void Test10249(void);
/**
* Test the time stamp array recalculation during heavy Calendar usage