]> granicus.if.org Git - icu/commitdiff
ICU-10249 Implement new islamic calendar variants tbla, rgsa
authorScott Russell <DTownSMR@gmail.com>
Tue, 17 Sep 2013 16:55:02 +0000 (16:55 +0000)
committerScott Russell <DTownSMR@gmail.com>
Tue, 17 Sep 2013 16:55:02 +0000 (16:55 +0000)
X-SVN-Rev: 34354

icu4c/source/i18n/calendar.cpp
icu4c/source/i18n/islamcal.cpp
icu4c/source/i18n/islamcal.h
icu4c/source/test/intltest/caltest.cpp
icu4c/source/test/intltest/caltest.h

index c76093202770e42c1cf7d3f0c9648f9ec09019fd..27825c04a2c85ec8907ebcdd03c9e23d382d02fc 100644 (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;
     }
index fec702799db4549b140ffb88370655529ba5b50b..59de71335fa6538e1272dec8629994f548ffe520 100644 (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 );
index 507e135d73df8ff204a750b7ecf68c6dd033915a..b37e8169cb26f34b3986bf4e4b19c91e6b3c0fa6 100644 (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[] = {                
index 1c47540838e50c623b4722df757c6142501063f9..30f98e8c73daff94a9a0cd1f8582f4e8e77b9799 100644 (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 */
index 7686767ee0ad29b1274169790c4eebf3ad8c5a93..1d028095bb1ec4fe92367f85108e519c1df2202b 100644 (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