4

I have jdk java version "1.8.0_45", i am using joda time api (joda-time-2.7.jar)

By using Joda time api i am getting a wrong date.

By using Jdk 8 hijri date api i am getting a correct date.

I have a requirement to convert a gregorian date to hijri date using java api.

My sample test class is as follows:

import org.joda.time.*;
import org.joda.time.chrono.*;
import java.time.*;
import java.time.chrono.HijrahChronology;
import java.util.*;
public class Test {
    public static void main(String[] args) throws Exception {
        DateTime dtISO = new DateTime();
        System.out.println("dtISO = "+dtISO);
        DateTime dtIslamic = dtISO.withChronology(IslamicChronology.getInstance(DateTimeZone.UTC  ));
        System.out.println(dtIslamic.getYear()+"-" +dtIslamic.getMonthOfYear()+ "-"+ dtIslamic.getDayOfMonth());
        java.time.chrono.HijrahDate hijradate = java.time.chrono.HijrahDate.now();
        System.out.println("hijradate "+hijradate);
    }
} 

Output of this class is

C:\>java Test
dtISO = 2015-05-24T09:44:51.704+04:00
1436-8-5
hijradate Hijrah-umalqura AH 1436-08-06

Can you please tell me joda api is correct one or wrong one?

My production server has JDK1.6 i cannot upgrade it to 1.8 as of now, so kindly let me know your suggestions to get a proper hijri date .... Awaiting for your reply....

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
  • Please have a look at my [answer](http://stackoverflow.com/a/32330227/2491410) on SO about this topic. Instead of Time4A on Android, you could use Time4J - v3.10 or higher for Java. It is really important to understand that there is not just one single Hijri calendar but many variants in real world. – Meno Hochschild Nov 02 '15 at 15:44

3 Answers3

2

The difference you are seeing between JodaTime and JDK8 is because they use different implementations of the Hijri Calendar. There are multiple algorithms to compute (approximate) a Hijri date.

Jdk8's HijrahChoronology uses an implementation of Umm-AlQura calendar which closely matches the official Hijri calendar in Saudi Arabia as defined in http://www.ummulqura.org.sa/.

JodaTime IslamicChronology has different implementations which you can select from using its factory methods see http://joda-time.sourceforge.net/apidocs/org/joda/time/chrono/IslamicChronology.html

So it really depends on system audience. If you are in Saudi Arabia or any country which relies on UmmAlQura calendar stick with the JDK8's implementation.

0

i found this code on http://junaedhalim.blogspot.com/2010/01/hijri-calendar-in-java-using-kuwaiti.html hopefully it help you

import java.util.Calendar; import java.util.Date;

/**
 *
 * @author junaed
 */
public class HijriCalendar
{

    private int[] userDateG;
    private int[] userDateH;

    private WaqtMidlet midlet;
    private Calendar cal;
    private int currentHijriDate;
    private int currentHijriMonth;
    private int currentHijriYear;
    public static final String[] HIJRI_MONTHS =
    {
        "Muharram", "Safar", "Rabi' al-awwal", "Rabi' al-thani", "Jumada al-awwal",
        "Jumada al-thani", "Rajab", "Sha'aban", "Ramadan", "Shawwal", "Dhu al-Qi'dah", "Dhu al-Hijjah"
    };
    public static final int[] BASE_DATE_G =
    {
        18, 11, 2009, 0, 0
    };
    public static final int[] BASE_DATE_H =
    {
        1, 0, 1431, 0, 0
    };
    public HijriCalendar(WaqtMidlet midlet)
    {
        this.midlet = midlet;
        cal = Calendar.getInstance();
        Date date = new Date();
        cal.setTime(date);
    }

    private void updateDefinedTime()
    {
        String uTimeH = midlet.getRmsManager().getString(ApplicationConstants.RMS_HIJRI_DATE);
//        String uTimeH = "";
        if (uTimeH == null || uTimeH.equalsIgnoreCase(""))
        {
            userDateG = ApplicationConstants.BASE_DATE_G;
            userDateH = ApplicationConstants.BASE_DATE_H;
        }
        else
        {
            System.out.println("uTimeH = " + uTimeH);
            int date = Integer.parseInt(uTimeH.substring(0, uTimeH.indexOf(';')));
            String rest = uTimeH.substring(uTimeH.indexOf(';') + 1);
            int month = Integer.parseInt(rest.substring(0, rest.indexOf(';')));
            rest = rest.substring(rest.indexOf(';') + 1);
            int year = Integer.parseInt(rest.substring(0, rest.indexOf(';')));
            rest = rest.substring(rest.indexOf(';') + 1);
            int hour = Integer.parseInt(rest.substring(0, rest.indexOf(';')));
            rest = rest.substring(rest.indexOf(';') + 1);
            int minute = Integer.parseInt(rest);

            userDateH = new int[]
                    {
                        date, month, year, hour, minute
                    };

//            String uTimeG = "";
            String uTimeG = midlet.getRmsManager().getString(ApplicationConstants.RMS_GREGORIAN_DATE);
            System.out.println("uTimeG = " + uTimeG);
            date  = Integer.parseInt(uTimeG.substring(0, uTimeG.indexOf(';')));
            rest = uTimeG.substring(uTimeG.indexOf(';') + 1);
            month = Integer.parseInt(rest.substring(0, rest.indexOf(';')));
            rest = rest.substring(rest.indexOf(';') + 1);
            year = Integer.parseInt(rest.substring(0, rest.indexOf(';')));

            userDateG = new int[]
                    {
                        date, month, year, hour, minute
                    };
        }

        cal.set(Calendar.HOUR_OF_DAY, userDateG[3]);
        cal.set(Calendar.MINUTE, userDateG[4]);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.DATE, userDateG[0]);
        cal.set(Calendar.MONTH, userDateG[1]);
        cal.set(Calendar.YEAR, userDateG[2]);

        currentHijriDate = userDateH[0];
        currentHijriMonth = userDateH[1];
        currentHijriYear = userDateH[2];
    }

    private boolean isALeapYear(int year)
    {
        int modValue = year % 30;
        switch (modValue)
        {
            case 2:
                return true;
            case 5:
                return true;
            case 7:
                return true;
            case 10:
                return true;
            case 13:
                return true;
            case 15:
                return true;
            case 18:
                return true;
            case 21:
                return true;
            case 24:
                return true;
            case 26:
                return true;
            case 29:
                return true;
        }
        return false;
    }

    private int getDaysInThisYear(int year)
    {
        if (isALeapYear(year))
        {
            return 355;
        }
        return 354;
    }

    public int getDaysInThisMonth(int month, int year)
    {
        if (month % 2 != 0)
        {
            return 30;
        }
        else
        {
            if (month == 12)
            {
                if (isALeapYear(year))
                {
                    return 30;
                }
            }
            return 29;
        }
    }

    private void addOneDayToCurrentDate()
    {
        currentHijriDate++;
        if(currentHijriDate >= 29)
        {
            int daysInCurrentMonth = getDaysInThisMonth(currentHijriMonth, currentHijriYear);
            if( currentHijriDate > daysInCurrentMonth)
            {
                currentHijriDate = 1;
                currentHijriMonth++;
                if(currentHijriMonth > 11)
                {
                    currentHijriMonth = 1;
                    currentHijriYear++;
                }
            }

        }
    }

    private void addDays(long days)
    {
        for(long i = 0; i< days; i++)
        {
            addOneDayToCurrentDate();
        }
    }

    public String getCurrentDateStr()
    {
        updateDefinedTime();
        Date date = new Date();
//        int currentTime = calendar.get(Calendar.HOUR_OF_DAY);
        long diff = date.getTime() - cal.getTime().getTime();
        long days = diff / (1000 * 86400);
        addDays(days);
        String ret = currentHijriYear + " "+HIJRI_MONTHS[currentHijriMonth] + ", " + currentHijriDate;
        return ret;
//        return midlet.getRmsManager().getString(ApplicationConstants.RMS_HIJRI_DATE);

    }

}
Alaa Abuzaghleh
  • 1,023
  • 6
  • 11
0

Try using ICU4J. Its Calendar classes do not extend java.util.Calendar, but they do properly deal with Hijri dates (and many other calendar systems). I was able to get what I believe are correct results using its IslamicCalendar class, using Java 1.6.0_31:

import java.util.Date;
import java.util.Locale;

import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.IslamicCalendar;

public class HijriDate {
    public static void main(String[] args) {

        java.util.Calendar gregorianCal =
            java.util.Calendar.getInstance(Locale.US);

        System.out.printf("%tF%n", gregorianCal);

        Date date = gregorianCal.getTime();

        Calendar cal = new IslamicCalendar();
        cal.setTime(date);

        System.out.printf("%02d-%02d-%02d%n",
            cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH) + 1,
            cal.get(Calendar.DAY_OF_MONTH));
    }
}
VGR
  • 40,506
  • 4
  • 48
  • 63