]> granicus.if.org Git - icu/commitdiff
ICU-10249 Implement new Islamic calendar variants tbla, rgsa
authorScott Russell <DTownSMR@gmail.com>
Tue, 3 Sep 2013 22:26:48 +0000 (22:26 +0000)
committerScott Russell <DTownSMR@gmail.com>
Tue, 3 Sep 2013 22:26:48 +0000 (22:26 +0000)
X-SVN-Rev: 34172

icu4j/main/classes/core/src/com/ibm/icu/util/Calendar.java
icu4j/main/classes/core/src/com/ibm/icu/util/IslamicCalendar.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/calendar/IslamicTest.java

index 891e763fbda8da909be42a813ce1bed3b25deb0e..06dc781e61dc9d192942461443e0ddc9f2d6c695 100644 (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.
index 1fc1b8e7aab5dc652a8947a1ba4ff07539884f06..6e691f5e85fb5554b8d0d65eb8a8239702ac5487 100644 (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 {
index 4f039be7e14d604d9aeba738e64f68fc09f9f3ec..5cdf42275e4ea5aac9159df3c9141a85853b3dea 100644 (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);
+        }
+
+    }
+
 }