Có thư viện hoặc thuật toán nào cho lịch Ba Tư (Shamsi hoặc Jalali) trong Android không? [đóng cửa]


81

Tôi muốn chuyển đổi ngày Gregorian (miền Tây) sang ngày Persian (Shamsi) và ngược lại cho tất cả các phiên bản Android.

Có thư viện hoặc thuật toán hoàn chỉnh và đáng tin cậy nào không?


Câu trả lời:


78

Tôi đang sử dụng thuật toán này trong nhiều năm và nó rất chính xác trong khoảng thời gian từ 1901 đến 2099.

Sử dụng nó và tận hưởng! :)

public class Utilities {

    private class SolarCalendar {

        public String strWeekDay = "";
        public String strMonth = "";

        int date;
        int month;
        int year;

        public SolarCalendar()
        {
            Date MiladiDate = new Date();
            calcSolarCalendar(MiladiDate);
        }

        public SolarCalendar(Date MiladiDate)
        {
            calcSolarCalendar(MiladiDate);
        }

        private void calcSolarCalendar(Date MiladiDate) {

            int ld;

            int miladiYear = MiladiDate.getYear() + 1900;
            int miladiMonth = MiladiDate.getMonth() + 1;
            int miladiDate = MiladiDate.getDate();
            int WeekDay = MiladiDate.getDay();

            int[] buf1 = new int[12];
            int[] buf2 = new int[12];

            buf1[0] = 0;
            buf1[1] = 31;
            buf1[2] = 59;
            buf1[3] = 90;
            buf1[4] = 120;
            buf1[5] = 151;
            buf1[6] = 181;
            buf1[7] = 212;
            buf1[8] = 243;
            buf1[9] = 273;
            buf1[10] = 304;
            buf1[11] = 334;

            buf2[0] = 0;
            buf2[1] = 31;
            buf2[2] = 60;
            buf2[3] = 91;
            buf2[4] = 121;
            buf2[5] = 152;
            buf2[6] = 182;
            buf2[7] = 213;
            buf2[8] = 244;
            buf2[9] = 274;
            buf2[10] = 305;
            buf2[11] = 335;

            if ((miladiYear % 4) != 0) {
                date = buf1[miladiMonth - 1] + miladiDate;

                if (date > 79) {
                    date = date - 79;
                    if (date <= 186) {
                        switch (date % 31) {
                        case 0:
                            month = date / 31;
                            date = 31;
                            break;
                        default:
                            month = (date / 31) + 1;
                            date = (date % 31);
                            break;
                        }
                        year = miladiYear - 621;
                    } else {
                        date = date - 186;

                        switch (date % 30) {
                        case 0:
                            month = (date / 30) + 6;
                            date = 30;
                            break;
                        default:
                            month = (date / 30) + 7;
                            date = (date % 30);
                            break;
                        }
                        year = miladiYear - 621;
                    }
                } else {
                    if ((miladiYear > 1996) && (miladiYear % 4) == 1) {
                        ld = 11;
                    } else {
                        ld = 10;
                    }
                    date = date + ld;

                    switch (date % 30) {
                    case 0:
                        month = (date / 30) + 9;
                        date = 30;
                        break;
                    default:
                        month = (date / 30) + 10;
                        date = (date % 30);
                        break;
                    }
                    year = miladiYear - 622;
                }
            } else {
                date = buf2[miladiMonth - 1] + miladiDate;

                if (miladiYear >= 1996) {
                    ld = 79;
                } else {
                    ld = 80;
                }
                if (date > ld) {
                    date = date - ld;

                    if (date <= 186) {
                        switch (date % 31) {
                        case 0:
                            month = (date / 31);
                            date = 31;
                            break;
                        default:
                            month = (date / 31) + 1;
                            date = (date % 31);
                            break;
                        }
                        year = miladiYear - 621;
                    } else {
                        date = date - 186;

                        switch (date % 30) {
                        case 0:
                            month = (date / 30) + 6;
                            date = 30;
                            break;
                        default:
                            month = (date / 30) + 7;
                            date = (date % 30);
                            break;
                        }
                        year = miladiYear - 621;
                    }
                }

                else {
                    date = date + 10;

                    switch (date % 30) {
                    case 0:
                        month = (date / 30) + 9;
                        date = 30;
                        break;
                    default:
                        month = (date / 30) + 10;
                        date = (date % 30);
                        break;
                    }
                    year = miladiYear - 622;
                }

            }

            switch (month) {
            case 1:
                strMonth = "فروردين";
                break;
            case 2:
                strMonth = "ارديبهشت";
                break;
            case 3:
                strMonth = "خرداد";
                break;
            case 4:
                strMonth = "تير";
                break;
            case 5:
                strMonth = "مرداد";
                break;
            case 6:
                strMonth = "شهريور";
                break;
            case 7:
                strMonth = "مهر";
                break;
            case 8:
                strMonth = "آبان";
                break;
            case 9:
                strMonth = "آذر";
                break;
            case 10:
                strMonth = "دي";
                break;
            case 11:
                strMonth = "بهمن";
                break;
            case 12:
                strMonth = "اسفند";
                break;
            }

            switch (WeekDay) {

            case 0:
                strWeekDay = "يکشنبه";
                break;
            case 1:
                strWeekDay = "دوشنبه";
                break;
            case 2:
                strWeekDay = "سه شنبه";
                break;
            case 3:
                strWeekDay = "چهارشنبه";
                break;
            case 4:
                strWeekDay = "پنج شنبه";
                break;
            case 5:
                strWeekDay = "جمعه";
                break;
            case 6:
                strWeekDay = "شنبه";
                break;
            }

        }

    }

    public static String getCurrentShamsidate() {
        Locale loc = new Locale("en_US");
        Utilities util = new Utilities();
        SolarCalendar sc = util.new SolarCalendar();
        return String.valueOf(sc.year) + "/" + String.format(loc, "%02d",
                sc.month) + "/" + String.format(loc, "%02d", sc.date);
    }
}

14
không phải tất cả các năm, bội số của 4, đều là năm nhuận. Những trường hợp là bội số của 100, nhưng không phải bội số của 400, là trường hợp ngoại lệ. xem: wikipedia
Untitled

Bạn đang gặp vấn đề với ngày nào?
Bobs

Tôi đang sử dụng thuật toán này trong 6 năm trong các ứng dụng của mình.
Bobs

26
bạn nên sử dụng nó cho 100 năm để xem vấn đề :)
Untitled

11
Có lẽ bạn có thể chỉnh sửa câu đầu tiên trong câu trả lời của mình để câu trả lời là "... nó rất chính xác trong khoảng từ 1901 đến 2099". Điều này có thể phù hợp cho nhiều ứng dụng; nhưng một số nhà phát triển có thể quan tâm đến những ngày nằm ngoài phạm vi này, và thật tuyệt khi cảnh báo họ rằng thuật toán này sẽ không đủ tốt.
Dawood ibn Kareem

31

Tôi nghĩ rằng lớp java này dễ sử dụng hơn và đáng tin cậy hơn. Tôi tìm thấy nó trong diễn đàn của Iran , người Iran sử dụng Lịch Jalali và gọi nó là "Shamsi" có nghĩa là lịch Mặt trời. đây là lớp Java:

package MyUtil;

import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * Title: Calender Conversion class
 * Description: Convert Iranian (Jalali), Julian, and Gregorian dates to
 * each other
 * Public Methods Summary:
 * -----------------------
 * JavaSource_Calendar();
 * JavaSource_Calendar(int year, int month, int day);
 * int getIranianYear();
 * int getIranianMonth();
 * int getIranianDay();
 * int getGregorianYear();
 * int getGregorianMonth();
 * int getGregorianDay();
 * int getJulianYear();
 * int getJulianMonth();
 * int getJulianDay();
 * String getIranianDate();
 * String getGregorianDate();
 * String getJulianDate();
 * String getWeekDayStr();
 * String toString();
 * int getDayOfWeek();
 * void nextDay();
 * void nextDay(int days);
 * void previousDay();
 * void previousDay(int days);
 * void setIranianDate(int year, int month, int day);
 * void setGregorianDate(int year, int month, int day);
 * void setJulianDate(int year, int month, int day);
 */
public class CalendarTool {

    /**
     * JavaSource_Calendar:
     * The default constructor uses the current Gregorian date to initialize the
     * other private memebers of the class (Iranian and Julian dates).
     */
    public CalendarTool()
    {
        Calendar calendar = new GregorianCalendar();
        setGregorianDate(calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH)+1,
                calendar.get(Calendar.DAY_OF_MONTH));
    }

    /**
     * JavaSource_Calendar:
     * This constructor receives a Gregorian date and initializes the other private
     * members of the class accordingly.
     * @param year int
     * @param month int
     * @param day int
     */
    public CalendarTool(int year, int month, int day)
    {
        setGregorianDate(year,month,day);
    }

    /**
     * getIranianYear:
     * Returns the 'year' part of the Iranian date.
     * @return int
     */
    public int getIranianYear() {
        return irYear;
    }

    /**
     * getIranianMonth:
     * Returns the 'month' part of the Iranian date.
     * @return int
     */
    public int getIranianMonth() {
        return irMonth;
    }

    /**
     * getIranianDay:
     * Returns the 'day' part of the Iranian date.
     * @return int
     */
    public int getIranianDay() {
        return irDay;
    }

    /**
     * getGregorianYear:
     * Returns the 'year' part of the Gregorian date.
     * @return int
     */
    public int getGregorianYear() {
        return gYear;
    }

    /**
     * getGregorianMonth:
     * Returns the 'month' part of the Gregorian date.
     * @return int
     */
    public int getGregorianMonth() {
        return gMonth;
    }

    /**
     * getGregorianDay:
     * Returns the 'day' part of the Gregorian date.
     * @return int
     */
    public int getGregorianDay() {
        return gDay;
    }

    /**
     * getJulianYear:
     * Returns the 'year' part of the Julian date.
     * @return int
     */
    public int getJulianYear() {
        return juYear;
    }

    /**
     * getJulianMonth:
     * Returns the 'month' part of the Julian date.
     * @return int
     */
    public int getJulianMonth() {
        return juMonth;
    }

    /**
     * getJulianDay()
     * Returns the 'day' part of the Julian date.
     * @return int
     */
    public int getJulianDay() {
        return juDay;
    }

    /**
     * getIranianDate:
     * Returns a string version of Iranian date
     * @return String
     */
    public String getIranianDate()
    {
        return (irYear+"/"+irMonth+"/"+irDay);
    }

    /**
     * getGregorianDate:
     * Returns a string version of Gregorian date
     * @return String
     */
    public String getGregorianDate()
    {
        return (gYear+"/"+gMonth+"/"+gDay);
    }

    /**
     * getJulianDate:
     * Returns a string version of Julian date
     * @return String
     */
    public String getJulianDate()
    {
        return (juYear+"/"+juMonth+"/"+juDay);
    }

    /**
     * getWeekDayStr:
     * Returns the week day name.
     * @return String
     */
    public String getWeekDayStr()
    {
        String weekDayStr[]={
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
        "Sunday"};
        return (weekDayStr[getDayOfWeek()]);
    }

    /**
     * toString:
     * Overrides the default toString() method to return all dates.
     * @return String
     */
    public String toString()
    {
        return (getWeekDayStr()+
                ", Gregorian:["+getGregorianDate()+
                "], Julian:["+getJulianDate()+
                "], Iranian:["+getIranianDate()+"]");
    }


    /**
     * getDayOfWeek:
     * Returns the week day number. Monday=0..Sunday=6;
     * @return int
     */
    public int getDayOfWeek()
    {
        return (JDN % 7);
    }

    /**
     * nextDay:
     * Go to next julian day number (JDN) and adjusts the other dates.
     */
    public void nextDay()
    {
        JDN++;
        JDNToIranian();
        JDNToJulian();
        JDNToGregorian();
    }
    /**
     * nextDay:
     * Overload the nextDay() method to accept the number of days to go ahead and
     * adjusts the other dates accordingly.
     * @param days int
     */
    public void nextDay(int days)
    {
        JDN+=days;
        JDNToIranian();
        JDNToJulian();
        JDNToGregorian();
    }

    /**
     * previousDay:
     * Go to previous julian day number (JDN) and adjusts the otehr dates.
     */
    public void previousDay()
    {
        JDN--;
        JDNToIranian();
        JDNToJulian();
        JDNToGregorian();
    }

    /**
     * previousDay:
     * Overload the previousDay() method to accept the number of days to go backward
     * and adjusts the other dates accordingly.
     * @param days int
     */
    public void previousDay(int days)
    {
        JDN-=days;
        JDNToIranian();
        JDNToJulian();
        JDNToGregorian();
    }

    /**
     * setIranianDate:
     * Sets the date according to the Iranian calendar and adjusts the other dates.
     * @param year int
     * @param month int
     * @param day int
     */
    public void setIranianDate(int year, int month, int day)
    {
        irYear =year;
        irMonth = month;
        irDay = day;
        JDN = IranianDateToJDN();
        JDNToIranian();
        JDNToJulian();
        JDNToGregorian();
    }

    /**
     * setGregorianDate:
     * Sets the date according to the Gregorian calendar and adjusts the other dates.
     * @param year int
     * @param month int
     * @param day int
     */
    public void setGregorianDate(int year, int month, int day)
    {
        gYear = year;
        gMonth = month;
        gDay = day;
        JDN = gregorianDateToJDN(year,month,day);
        JDNToIranian();
        JDNToJulian();
        JDNToGregorian();
    }

    /**
     * setJulianDate:
     * Sets the date according to the Julian calendar and adjusts the other dates.
     * @param year int
     * @param month int
     * @param day int
     */
    public void setJulianDate(int year, int month, int day)
    {
        juYear = year;
        juMonth = month;
        juDay = day;
        JDN = julianDateToJDN(year,month,day);
        JDNToIranian();
        JDNToJulian();
        JDNToGregorian();
    }

    /**
     * IranianCalendar:
     * This method determines if the Iranian (Jalali) year is leap (366-day long)
     * or is the common year (365 days), and finds the day in March (Gregorian
     * Calendar)of the first day of the Iranian year ('irYear').Iranian year (irYear)
     * ranges from (-61 to 3177).This method will set the following private data
     * members as follows:
     * leap: Number of years since the last leap year (0 to 4)
     * Gy: Gregorian year of the begining of Iranian year
     * march: The March day of Farvardin the 1st (first day of jaYear)
     */
    private void IranianCalendar()
    {
        // Iranian years starting the 33-year rule
        int Breaks[]=
            {-61, 9, 38, 199, 426, 686, 756, 818,1111,1181,
                1210,1635,2060,2097,2192,2262,2324,2394,2456,3178} ;
        int jm,N,leapJ,leapG,jp,j,jump;
        gYear = irYear + 621;
        leapJ = -14;
        jp = Breaks[0];
        // Find the limiting years for the Iranian year 'irYear'
        j=1;
        do{
            jm=Breaks[j];
            jump = jm-jp;
            if (irYear >= jm)
            {
                leapJ += (jump / 33 * 8 + (jump % 33) / 4);
                jp = jm;
            }
            j++;
        } while ((j<20) && (irYear >= jm));
        N = irYear - jp;
        // Find the number of leap years from AD 621 to the begining of the current
        // Iranian year in the Iranian (Jalali) calendar
        leapJ += (N/33 * 8 + ((N % 33) +3)/4);
        if ( ((jump % 33) == 4 ) && ((jump-N)==4))
            leapJ++;
        // And the same in the Gregorian date of Farvardin the first
        leapG = gYear/4 - ((gYear /100 + 1) * 3 / 4) - 150;
        march = 20 + leapJ - leapG;
        // Find how many years have passed since the last leap year
        if ( (jump - N) < 6 )
            N = N - jump + ((jump + 4)/33 * 33);
        leap = (((N+1) % 33)-1) % 4;
        if (leap == -1)
            leap = 4;
    }


    /**
     * IsLeap:
     * This method determines if the Iranian (Jalali) year is leap (366-day long)
     * or is the common year (365 days), and finds the day in March (Gregorian
     * Calendar)of the first day of the Iranian year ('irYear').Iranian year (irYear)
     * ranges from (-61 to 3177).This method will set the following private data
     * members as follows:
     * leap: Number of years since the last leap year (0 to 4)
     * Gy: Gregorian year of the begining of Iranian year
     * march: The March day of Farvardin the 1st (first day of jaYear)
     */
    public boolean IsLeap(int irYear1)
    {
        // Iranian years starting the 33-year rule
        int Breaks[]=
            {-61, 9, 38, 199, 426, 686, 756, 818,1111,1181,
                1210,1635,2060,2097,2192,2262,2324,2394,2456,3178} ;
        int jm,N,leapJ,leapG,jp,j,jump;
        gYear = irYear1 + 621;
        leapJ = -14;
        jp = Breaks[0];
        // Find the limiting years for the Iranian year 'irYear'
        j=1;
        do{
            jm=Breaks[j];
            jump = jm-jp;
            if (irYear1 >= jm)
            {
                leapJ += (jump / 33 * 8 + (jump % 33) / 4);
                jp = jm;
            }
            j++;
        } while ((j<20) && (irYear1 >= jm));
        N = irYear1 - jp;
        // Find the number of leap years from AD 621 to the begining of the current
        // Iranian year in the Iranian (Jalali) calendar
        leapJ += (N/33 * 8 + ((N % 33) +3)/4);
        if ( ((jump % 33) == 4 ) && ((jump-N)==4))
            leapJ++;
        // And the same in the Gregorian date of Farvardin the first
        leapG = gYear/4 - ((gYear /100 + 1) * 3 / 4) - 150;
        march = 20 + leapJ - leapG;
        // Find how many years have passed since the last leap year
        if ( (jump - N) < 6 )
            N = N - jump + ((jump + 4)/33 * 33);
        leap = (((N+1) % 33)-1) % 4;
        if (leap == -1)
            leap = 4;
        if (leap==4 || leap==0)
            return true;
        else
            return false;

    }



    /**
     * IranianDateToJDN:
     * Converts a date of the Iranian calendar to the Julian Day Number. It first
     * invokes the 'IranianCalender' private method to convert the Iranian date to
     * Gregorian date and then returns the Julian Day Number based on the Gregorian
     * date. The Iranian date is obtained from 'irYear'(1-3100),'irMonth'(1-12) and
     * 'irDay'(1-29/31).
     * @return long (Julian Day Number)
     */
    private int IranianDateToJDN()
    {
        IranianCalendar();
        return (gregorianDateToJDN(gYear,3,march)+ (irMonth-1) * 31 - irMonth/7 * (irMonth-7) + irDay -1);
    }

    /**
     * JDNToIranian:
     * Converts the current value of 'JDN' Julian Day Number to a date in the
     * Iranian calendar. The caller should make sure that the current value of
     * 'JDN' is set correctly. This method first converts the JDN to Gregorian
     * calendar and then to Iranian calendar.
     */
    private void JDNToIranian()
    {
        JDNToGregorian();
        irYear = gYear - 621;
        IranianCalendar(); // This invocation will update 'leap' and 'march'
        int JDN1F = gregorianDateToJDN(gYear,3,march);
        int k = JDN - JDN1F;
        if (k >= 0)
        {
            if (k <= 185)
            {
                irMonth = 1 + k/31;
                irDay = (k % 31) + 1;
                return;
            }
            else
                k -= 186;
        }
        else
        {
            irYear--;
            k += 179;
            if (leap == 1)
                k++;
        }
        irMonth = 7 + k/30;
        irDay = (k % 30) + 1;
    }


    /**
     * julianDateToJDN:
     * Calculates the julian day number (JDN) from Julian calendar dates. This
     * integer number corresponds to the noon of the date (i.e. 12 hours of
     * Universal Time). This method was tested to be good (valid) since 1 March,
     * -100100 (of both calendars) up to a few millions (10^6) years into the
     * future. The algorithm is based on D.A.Hatcher, Q.Jl.R.Astron.Soc. 25(1984),
     * 53-55 slightly modified by K.M. Borkowski, Post.Astron. 25(1987), 275-279.
     * @param year int
     * @param month int
     * @param day int
     * @return int
     */
    private int julianDateToJDN(int year, int month, int day)
    {
        return (year + (month - 8) / 6 + 100100) * 1461/4 + (153 * ((month+9) % 12) + 2)/5 + day - 34840408;
    }

    /**
     * JDNToJulian:
     * Calculates Julian calendar dates from the julian day number (JDN) for the
     * period since JDN=-34839655 (i.e. the year -100100 of both calendars) to
     * some millions (10^6) years ahead of the present. The algorithm is based on
     * D.A. Hatcher, Q.Jl.R.Astron.Soc. 25(1984), 53-55 slightly modified by K.M.
     * Borkowski, Post.Astron. 25(1987), 275-279).
     */
    private void JDNToJulian()
    {
        int j= 4 * JDN + 139361631;
        int i= ((j % 1461)/4) * 5 + 308;
        juDay = (i % 153) / 5 + 1;
        juMonth = ((i/153) % 12) + 1;
        juYear = j/1461 - 100100 + (8-juMonth)/6;
    }

    /**
     * gergorianDateToJDN:
     * Calculates the julian day number (JDN) from Gregorian calendar dates. This
     * integer number corresponds to the noon of the date (i.e. 12 hours of
     * Universal Time). This method was tested to be good (valid) since 1 March,
     * -100100 (of both calendars) up to a few millions (10^6) years into the
     * future. The algorithm is based on D.A.Hatcher, Q.Jl.R.Astron.Soc. 25(1984),
     * 53-55 slightly modified by K.M. Borkowski, Post.Astron. 25(1987), 275-279.
     * @param year int
     * @param month int
     * @param day int
     * @return int
     */
    private int gregorianDateToJDN(int year, int month, int day)
    {
        int jdn = (year + (month - 8) / 6 + 100100) * 1461/4 + (153 * ((month+9) % 12) + 2)/5 + day - 34840408;
        jdn = jdn - (year + 100100+(month-8)/6)/100*3/4+752;
        return (jdn);
    }
    /**
     * JDNToGregorian:
     * Calculates Gregorian calendar dates from the julian day number (JDN) for
     * the period since JDN=-34839655 (i.e. the year -100100 of both calendars) to
     * some millions (10^6) years ahead of the present. The algorithm is based on
     * D.A. Hatcher, Q.Jl.R.Astron.Soc. 25(1984), 53-55 slightly modified by K.M.
     * Borkowski, Post.Astron. 25(1987), 275-279).
     */
    private void JDNToGregorian()
    {
        int j= 4 * JDN + 139361631;
        j = j + (((((4* JDN +183187720)/146097)*3)/4)*4-3908);
        int i= ((j % 1461)/4) * 5 + 308;
        gDay = (i % 153) / 5 + 1;
        gMonth = ((i/153) % 12) + 1;
        gYear = j/1461 - 100100 + (8-gMonth)/6;
    }


    private int irYear; // Year part of a Iranian date
    private int irMonth; // Month part of a Iranian date
    private int irDay; // Day part of a Iranian date
    private int gYear; // Year part of a Gregorian date
    private int gMonth; // Month part of a Gregorian date
    private int gDay; // Day part of a Gregorian date
    private int juYear; // Year part of a Julian date
    private int juMonth; // Month part of a Julian date
    private int juDay; // Day part of a Julian date
    private int leap; // Number of years since the last leap year (0 to 4)
    private int JDN; // Julian Day Number
    private int march; // The march day of Farvardin the first (First day of jaYear)
} // End of Class 'JavaSource_Calendar

Bạn có thể dễ dàng đặt Ngày, Tháng và Năm Gregorian, sau đó gọi phương thức "getIranianDate ()" để lấy ngày ở định dạng chuỗi, giống như mã mẫu bên dưới:

MyUtil.CalendarTool ct = new CalendarTool(2012,10,10);
System.out.println(ct.getIranianDate());

Tôi hy vọng nó sẽ giúp.


3
Tôi nghĩ rằng có một lỗi! Khi bạn chuyển đổi ngày hôm nay (ngày tôi đăng nhận xét này) nó sẽ là '1396/01/20' nhưng là '1395/12/20'
Mohsen Abasi 10/04/17

Nó đưa ra câu trả lời sai.
Meysam Mohammadi

Bạn có thể giúp tôi chỉnh sửa nó và giải quyết lỗi.
Reza Ameri

Mã hoạt động chính xác cho cả
MMG

Tôi nghĩ một vấn đề là số ngày trong tháng không bị giới hạn, ví dụ: tháng 4 là 30 ngày, nhưng câu trả lời mã cho tháng 431 và nó giống với ngày 1 tháng 5
MMG

20

Sử dụng các Thành phần Quốc tế của IBM cho Unicode ( icu4j ). Nó là một phần của Unicode Consortium , cực kỳ đáng tin cậy và có thể được sử dụng trong bất kỳ dự án java nào (Java EE, Java SE, Android, v.v.). Sử dụng nó với Gradle , Maven hoặc đơn giản bằng cách tải xuống bình.

TL; DR

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.ULocale;

public class DateTimeUtils {
    public static final ULocale PERSIAN_LOCALE = new ULocale("fa_IR@calendar=persian");
    public static final ULocale PERSIAN_EN_LOCALE = new ULocale("en@calendar=persian");
    public static final ZoneId IRAN_ZONE_ID = ZoneId.of("Asia/Tehran");

    public static Calendar fromDateToPersianCalendar(Date date) {
        Calendar persianCalendar = Calendar.getInstance(PERSIAN_LOCALE);
        persianCalendar.clear();
        persianCalendar.setTime(date);
        return persianCalendar;
    }

    /**
     * @param date
     * @param field example: Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, etc
     */
    public static int fromDateToPersianCalendarField(Date date, int field) {
        return fromDateToPersianCalendar(date).get(field);
    }

    public static String fromDateToPersianString(Date date) {
        DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, PERSIAN_LOCALE);
        return df.format(date);
    }

    public static String fromDateToPersianString(Date date, String pattern) {
        return new SimpleDateFormat(pattern, PERSIAN_LOCALE).format(date);
    }

    public static String fromDateToPersianString(Date date, String pattern, ULocale locale) {
        return new SimpleDateFormat(pattern, locale).format(date);
    }

    /**
     * @param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
     */
    public static Date fromPersianDateToDate(int year, int month, int day, int hour, int minutes, int seconds) {
        return new Date(fromPersianDate(year, month, day, hour, minutes, seconds));
    }

    /**
     * @param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
     */    
    public static String fromPersianDateToPersianString(int year, int month, int day, int hour, int minutes, int seconds) {
        return fromDateToPersianString(fromPersianDateToDate(year, month, day, hour, minutes, seconds));
    }

    /**
     * @param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
     */      
    public static LocalDateTime fromPersianDateToLocalDateTime(int year, int month, int day, int hour, int minutes, int seconds) {
        return fromPersianDateToZonedDateTime(year, month, day, hour, minutes, seconds).toLocalDateTime();
    }

    /**
     * @param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
     */  
    public static ZonedDateTime fromPersianDateToZonedDateTime(int year, int month, int day, int hour, int minutes, int seconds) {
        return toZonedDateTime(fromPersianDate(year, month, day, hour, minutes, seconds));
    }

    /**
     * @param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
     */  
    public static long fromPersianDate(int year, int month, int day, int hour, int minutes, int seconds) {
        Calendar persianCalendar = Calendar.getInstance(PERSIAN_LOCALE);
        persianCalendar.clear();
        persianCalendar.set(year, month, day, hour, minutes, seconds);
        return persianCalendar.getTimeInMillis();
    }

    public static ZonedDateTime toZonedDateTime(Long epochMilli) {
        if(epochMilli == null) return null;
        return Instant.ofEpochMilli(epochMilli).atZone(IRAN_ZONE_ID);
    }
}

Sử dụng:

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date;
import com.ibm.icu.util.Calendar;

public class DateTimeUtilsTest {
    public static void main(String[] args) {
        System.out.println("Java 7 and before:");
        Date date = new Date(1467262800000L);
        System.out.println("Converting Gregorian date to Persian:");
        Calendar persianCalendar = DateTimeUtils.fromDateToPersianCalendar(date);
        System.out.println(persianCalendar.get(Calendar.YEAR));
        System.out.println(persianCalendar.get(Calendar.MONTH));
        System.out.println(persianCalendar.get(Calendar.DAY_OF_MONTH));
        System.out.println(DateTimeUtils.fromDateToPersianString(persianCalendar.getTime()));
        
        System.out.println("\nAdding 1 month and 5 days:");
        persianCalendar.add(Calendar.MONTH, 1); // add a month
        persianCalendar.add(Calendar.DAY_OF_MONTH, 5); // add 5 days
        System.out.println(persianCalendar.get(Calendar.YEAR));
        System.out.println(persianCalendar.get(Calendar.MONTH));
        System.out.println(persianCalendar.get(Calendar.DAY_OF_MONTH));
        System.out.println(DateTimeUtils.fromDateToPersianString(persianCalendar.getTime()));
        
        System.out.println("\nConverting Persian date to Gregorian:");
        Date gregorianDate = DateTimeUtils.fromPersianDateToDate(1395, 3, 10, 9, 30, 0);
        System.out.println(gregorianDate);
        System.out.println(DateTimeUtils.fromDateToPersianString(gregorianDate)); // to Persian string
        System.out.println(DateTimeUtils.fromDateToPersianString(gregorianDate, "dd/MM/yy - H:mm:dd")); // to Persian string with custom format
        System.out.println(DateTimeUtils.fromDateToPersianString(gregorianDate, "dd/MM/yy - H:mm:dd" , DateTimeUtils.PERSIAN_EN_LOCALE)); // to Persian string with custom format and Latin characters

        System.out.println("\n"+"Java 8 onward:");
        ZonedDateTime gregorianZonedDateTime = DateTimeUtils.fromPersianDateToZonedDateTime(1395, 3, 10, 9, 30, 0);
        System.out.println(gregorianZonedDateTime);
        LocalDateTime gregorianLocalDateTime = DateTimeUtils.fromPersianDateToLocalDateTime(1395, 3, 10, 9, 30, 0);
        System.out.println(gregorianLocalDateTime);
    }
}

Đầu ra:

Java 7 and before:
Converting Gregorian date to Persian:
1395
3
10
۱۳۹۵ تیر ۱۰, پنجشنبه

Adding 1 month and 5 days:
1395
4
15
۱۳۹۵ مرداد ۱۵, جمعه

Converting Persian date to Gregorian:
Thu Jun 30 09:30:00 IRDT 2016
۱۳۹۵ تیر ۱۰, پنجشنبه
۱۰/۰۴/۹۵ - ۹:۳۰:۱۰
10/04/95 - 9:30:10

Java 8 onward:
2016-06-30T09:30+04:30[Asia/Tehran]
2016-06-30T09:30

Chi tiết hơn:

Java 7 trở về trước:

Bạn có thể mong đợi tất cả các chức năng của java.util.Calendarngoài một số chức năng khác:

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

...

ULocale locale = new ULocale("fa_IR@calendar=persian");
Calendar persianCalendar = Calendar.getInstance(locale);
persianCalendar.clear();
persianCalendar.set(1395, 3, 10); // Tir(4th month) 10th 1395 equivalent to June 30th 2016 

java.util.Date gregorianDate = persianCalendar.getTime();
System.out.println(gregorianDate); // Thu Jun 30 00:00:00 IDT 2016

// Gregorian to Persian
java.util.Calendar gregorianCal = java.util.GregorianCalendar.getInstance();
gregorianCal.set(2016, java.util.Calendar.JUNE, 30);

persianCalendar.setTime(gregorianCal.getTime());
System.out.println(persianCalendar.get(Calendar.YEAR));         // 1395
System.out.println(persianCalendar.get(Calendar.MONTH));        // 3
System.out.println(persianCalendar.get(Calendar.DAY_OF_MONTH)); // 10

CẢNH BÁO : Lưu ý rằng trường tháng là 0 dựa trên lịch Java nên theo calendar.set(1395, 3, 10)lịch sẽ đại diện cho tháng thứ 4 của năm 1395, không phải thứ 3!

Nếu bạn cần kết quả đầu ra văn bản bằng tiếng Ba Tư:

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;

...

// full date output in persian
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, locale);
System.out.println(df.format(persianCalendar.getTime()));

// year output in persian
SimpleDateFormat sdf1 = new SimpleDateFormat(SimpleDateFormat.YEAR, locale);
System.out.println(sdf1.format(persianCalendar.getTime()));

// month name output in persian
SimpleDateFormat sdf2 = new SimpleDateFormat(SimpleDateFormat.MONTH, locale);
System.out.println(sdf2.format(persianCalendar.getTime()));

// weekday name output in persian
SimpleDateFormat sdf3 = new SimpleDateFormat(SimpleDateFormat.WEEKDAY, locale);
System.out.println(sdf3.format(persianCalendar.getTime()));

// full date output in YY/MM/dd form
SimpleDateFormat sdf4 = new SimpleDateFormat("YY/MM/dd", locale);
System.out.println(sdf4.format(persianCalendar.getTime()));

Đầu ra:

ه‍.ش. ۱۳۹۵ تیر ۱۰, پنجشنبه  
۱۳۹۵  
تیر  
پنجشنبه
۹۵/۰۴/۱۰

Nếu bạn cần đầu ra bằng tiếng Anh, hãy chuyển new ULocale("fa_IR@calendar=persian")sang new ULocale("en@calendar=persian").

Đầu ra:

AP 1395 Tir 10, Thu
1395
Tir
Thu
95/04/10

Những điều tốt đẹp khác:

// Get number of days in month
System.out.println(persianCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); // 31

// Get first day of week
System.out.println(persianCalendar.getFirstDayOfWeek()); // 7 (Saturday according to docs)

// Add some amount of time
persianCalendar.add(Calendar.MONTH, 2);
System.out.println(persianCalendar.get(Calendar.YEAR));         //1395
System.out.println(persianCalendar.get(Calendar.MONTH));        // 5
System.out.println(persianCalendar.get(Calendar.DAY_OF_MONTH)); // 10

Đối với các chức năng khác, hãy xem các bản trình diễn icu4j , đặc biệt:

Cũng xem Lịch và API PersianCalendar .

Java 8 trở đi:

Để sử dụng java.timecác lớp như ZonedDateTimehoặc LocalDateTime, bạn có thể chỉ cần sử dụng các phương thức này để chuyển đổi ngày cá nhân thành các lớp ưu tiên:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.ULocale;

...

public static LocalDateTime fromPersianDateToLocalDateTime(int year, int month, int day, int hour, int minutes, int seconds) {
    return fromPersianDateToZonedDateTime(year, month, day, hour, minutes, seconds).toLocalDateTime();
}

public static ZonedDateTime fromPersianDateToZonedDateTime(int year, int month, int day, int hour, int minutes, int seconds) {
    return toZonedDateTime(fromPersianDate(year, month, day, hour, minutes, seconds));
}

public static long fromPersianDate(int year, int month, int day, int hour, int minutes, int seconds) {
    Calendar persianCalendar = Calendar.getInstance(new ULocale("fa_IR@calendar=persian"));
    persianCalendar.clear();
    persianCalendar.set(year, month, day, hour, minutes, seconds);
    return persianCalendar.getTimeInMillis();
}

public static ZonedDateTime toZonedDateTime(Long epochMilli) {
    if(epochMilli == null) return null;
    return Instant.ofEpochMilli(epochMilli).atZone(ZoneId.of("Asia/Tehran"));
}

Nhận xét về kích thước bình

Nếu bạn lo lắng về kích thước jar của icu4j, thì bạn có thể xây dựng lại nó và chỉ cần sử dụng mô-đun Lịch (2.176KB). Thông tin thêm: ver. 57 hoặc trước đó , ver. 58 trở lên bằng Công cụ Xây dựng Dữ liệu ICU .


1
@deadManN Tôi đã cập nhật câu trả lời của mình. Tôi hy vọng nó hữu ích.
Omid

1
@deadManN nếu tính theo daysInMonth nghĩa là số ngày tối đa trong một tháng nhất định, bạn có thể đạt được những gì bạn đang tìm kiếm bằng cách gọi getActualMaximum(Calendar.DAY_OF_MONTH). Tôi đã cập nhật câu trả lời của mình để hiển thị cách sử dụng nó.
Omid

1
Tôi nghĩ sai lầm là từ phía bạn vì tôi đã kiểm tra getActualMaximum(Calendar.DAY_OF_MONTH)tất cả các tháng trước đó, hiện tại và năm sau và kết quả là chính xác. Bạn có biết rằng tháng đó bằng 0 trong lịch Java không? Nếu bạn đặt 5 vào trường tháng, nó thực sự có nghĩa là tháng thứ 6 không phải tháng thứ 5! Tương tự đối với tháng 11 (tháng thứ 12). Nếu không đúng như vậy, bạn có thể vui lòng cung cấp ngày chính xác dẫn đến hành vi sai trái không?
Omid

1
Theo như tôi biết, điều "không bình thường" duy nhất là các tháng bằng 0, không có gì phải lo lắng hơn. (Trên thực tế, nó không phải là độc đáo bởi vì tháng là một enum theo một cách!)
Omid

1
Câu trả lời tốt nhất! Vì bạn đã chỉ ra rằng: "Nó là một phần của Unicode Consortium, cực kỳ đáng tin cậy và có thể được sử dụng trong bất kỳ dự án java nào". Cũng nên lưu ý rằng bắt đầu từ Android 7.0 (API cấp 24), Android sẽ hiển thị một tập hợp con các API ICU4J để các nhà phát triển ứng dụng sử dụng theo android.icugói . Xem chi tiết tại đây .
Mir-Ismaili

11

phương pháp này rất chính xác và đơn giản cũng hỗ trợ các năm nhuận

Giải thích:

bước 1: thời gian hôm nay chứa thời gian hiện tại

bước 2: tạo hai mảng cho ngày Gregorian và jalali trong tháng (g_days_in_month & j_days_in_month)

bước 3: tạo biến cho thời gian chênh lệch lưu giữ giữa các lịch (gy, gm, gd) và biến g_day_no cho các ngày trong năm.

bước 4: chèn ngày trong tháng và thu thập theo ngày.

bước 5: chuyển đổi ngày của năm thành năm jalili (jy)

ở cuối: đặt tháng jalali từ số ngày, đặt ngày jalali từ mảng ngày tháng jalali.

chúc may mắn.

    Time today = new Time(Time.getCurrentTimezone());
    today.setToNow();
    int Day = (today.monthDay);             // Day of the month (0-31)
    int Month = (today.month);              // Month (0-11)
    int Year = (today.year);                // Year

    String persianDate = GregorianToJalali(Year, Month+1, Day);

  private String GregorianToJalali(int g_y, int g_m, int g_d)
{

  int[] g_days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  int[] j_days_in_month = {31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29};

    int gy = g_y-1600;
    int gm = g_m-1;
    int gd = g_d-1;

        int g_day_no = 365*gy+div(gy+3,4)-div(gy+99,100)+div(gy+399,400);

        for (int i=0; i < gm; ++i)
          g_day_no += g_days_in_month[i];
        if (gm>1 && ((gy%4==0 && gy%100!=0) || (gy%400==0)))
         // leap and after Feb 
          g_day_no++;
        g_day_no += gd;

       int j_day_no = g_day_no-79;

        int j_np = div(j_day_no, 12053); //12053 = 365*33 + 32/4 
        j_day_no = j_day_no % 12053;

        int jy = 979+33*j_np+4*div(j_day_no,1461); // 1461 = 365*4 + 4/4 

        j_day_no %= 1461;

        if (j_day_no >= 366) {
          jy += div(j_day_no-1, 365);
          j_day_no = (j_day_no-1)%365;
        }

        int j;
        for (j=0; j < 11 && j_day_no >= j_days_in_month[j]; ++j)
          j_day_no -= j_days_in_month[j];
       int jm = j+1;
       int jd = j_day_no+1;


        String Result= jy+"/"+jm+"/"+jd;

        return (Result);
     }  


  private int div(float a, float b)
  {  
      return (int)(a/b); 
  }

1
Bạn nên cố gắng giải thích câu trả lời của mình thay vì chỉ đăng một khối mã.
RyPeck

10

Phiên bản mới nhất v3.10-2015g của thư viện của tôi Time4A (một sự thích nghi của Android Time4J) chứa hỗ trợ cho lịch Jalali. Thư viện triển khai thuật toán Borkowski (có giá trị đến năm 2129). Trên thực tế, khoảng 25 ngôn ngữ được hỗ trợ cho các tháng và thời đại Ba Tư (bao gồm cả tiếng Farsi và Pashto, dựa trên CLDR-28).

Ví dụ về cách sử dụng:

// current date
PersianCalendar jalali = SystemClock.inLocalView().now(PersianCalendar.axis());
System.out.println(jalali); // AP-1394-08-04

// tomorrow
jalali = jalali.plus(CalendarDays.ONE);
System.out.println(jalali); // AP-1394-08-05

// localized format of tomorrow (English and Farsi)
ChronoFormatter<PersianCalendar> f =
    ChronoFormatter.ofStyle(DisplayMode.FULL, Locale.ENGLISH, PersianCalendar.axis());
Locale farsi = new Locale("fa");
System.out.println(f.format(jalali)); // Tuesday, Aban 5, 1394 AP
System.out.println(f.with(farsi).format(jalali)); // سه‌شنبه, آبان 5, 1394 ه‍.ش.

// shift back to month Farvardin and format the result
jalali = jalali.with(PersianCalendar.MONTH_OF_YEAR, PersianMonth.FARVARDIN);
System.out.println(f.format(jalali)); // Wednesday, Farvardin 5, 1394 AP
System.out.println(f.with(farsi).format(jalali)); // چهارشنبه, فروردین 5, 1394 ه‍.ش.

// conversion to gregorian date
System.out.println(jalali); // AP-1394-01-05
System.out.println(jalali.transform(PlainDate.class)); // 2015-03-25

// create new year in persian calendar and show gregorian counter part
jalali = PersianCalendar.of(1394, PersianMonth.FARVARDIN, 1);
System.out.println(jalali.transform(PlainDate.class)); // 2015-03-21

// create new year in gregorian calendar and show persian counter part
PlainDate gregorianDate = PlainDate.of(2015, Month.JANUARY, 1);
System.out.println(gregorianDate.transform(PersianCalendar.class)); // AP-1393-10-11

// delta between gregorian new year and persian new year
System.out.println(CalendarDays.between(gregorianDate, jalali).getAmount()); // 79

Khả năng tương tác với java.util.Date trên Android

Vì Time4A quản lý tập hợp các kiểu bất biến của riêng nó và không dựa trên kiểu tạm thời chính của Android, tôi chỉ ra cầu nối sau:

// Time4A => Android
PlainDate gdate = jalali.transform(PlainDate.class);
Moment m1 = gdate.atStartOfDay().inTimezone(ASIA.TEHRAN);
java.util.Date jud = TemporalType.JAVA_UTIL_DATE.from(m1);

// Android => Time4A
java.util.Date input = new java.util.Date();
Moment m2 = TemporalType.JAVA_UTIL_DATE.translate(input);
jalali = m2.toZonalTimestamp(ASIA.TEHRAN).toDate().transform(PersianCalendar.class);

+1 để sử dụng phương pháp Borkowski để có độ chính xác cao nhất. Tôi đã viết (các) Niên đại Ba Tư cho Joda Time . Jalali dựa trên việc quan sát thời gian phân đỉnh ở một kinh độ, Omar Khayyam (do Borkowski mở rộng) đã rút ra một công thức nhanh từ các dự đoán về điểm phân trong ~ 450 năm. Lời báo trước; Khayyam đã sử dụng kinh độ Tehran thay vì IRST được sử dụng hiện nay, vì vậy, 1 hoặc 2 năm nhuận có thể sẽ tắt trong 3k tới. Meno, vui lòng thêm một hướng dẫn về cách thêm chrono cho Time4A trên trang dự án.
Zubin Kavarana

@ZubinKavarana Cảm ơn bình luận của bạn. Tôi thực sự đã xác minh rõ ràng với tư cách là JUnit-test rằng sự thích nghi của tôi với Borkowski hoàn toàn phù hợp với Khayyam trong phạm vi năm nhất định (~ 450 năm). Về hướng dẫn: Ý tưởng hay nhưng một câu hỏi: Bạn có nghĩa là gì khi "thêm thời gian"? Tôi có ý muốn mở rộng hướng dẫn hiện có của mình với một trang về cách sử dụng các lịch khác nhau. Bạn cũng sẽ tìm thấy một javadoc trực tuyến ở đó.
Meno Hochschild

@ZubinKavarana Nếu bạn muốn nói "cách thêm lịch mới" bằng cách nói "thêm thời gian", tôi có thể thực hiện việc này bằng cách thêm một trang bổ sung vào hướng dẫn đã đề cập ở trên. Bạn có bất kỳ ý tưởng, đề xuất hoặc kế hoạch để thêm lịch khác không? Bạn cũng có thể mở một vấn đề trên time4j-github-issue-tracker để tiếp tục thảo luận này.
Meno Hochschild

Tôi vừa triển khai ví dụ của bạn và tôi nhận được hai dòng Lỗi này: tại net.time4j.base.ResourceLoader.getInstance (Nguồn không xác định), tại net.time4j.SystemClock. <clinit> (Nguồn không xác định). Làm cách nào để gỡ lỗi trong thư viện và tìm ra nguyên nhân?
Eftekhari

1
@Eftekhari Bạn đã khởi chạy ứng dụng của mình một cách chính xác ApplicationStarter.initialize(this, ...);chưa? Xem thêm ví dụ khởi tạo mã trên Time4A - phần Sử dụng. Stacktrace của bạn chỉ ra nguyên nhân đó.
Meno Hochschild

5

Thử đi

import java.util.Calendar;
import java.util.Date;
public class PersianCalendar {

String[] weekDayNames = {
        "شنبه","یکشنبه","دوشنبه",
        "سه شنبه", "چهارشنبه",
        "پنج شنبه", "جمعه"
};
String[] monthNames ={
        "فروردین","اردیبهشت","خرداد","تیر", "مرداد","شهریور",
         "مهر", "آبان", "آذر","دی", "بهمن","اسفند"
};   
String strWeekDay = "";
String strMonth = "";    
int day;
int month;
int year;    
int ld;     
Calendar calendar = Calendar.getInstance();      
int gregorianYear =calendar.get(Calendar.YEAR);
int gregorianMonth = calendar.get(Calendar.MONTH)+1;
int gregorianDate = calendar.get(Calendar.DATE);
int WeekDay = calendar.get(Calendar.DAY_OF_WEEK);

int[] buf1 = {0,31,59,90,120,151,181,212,243,273,304,334};
int[] buf2 = {0,31,60, 91,121,152,182, 213, 244, 274,305,335};

public PersianCalendar(){
    Date gregorianDate = new Date();
    calendar.setTime(gregorianDate);
    toPersian(gregorianDate);
}

public PersianCalendar(Date gregorianDate){
    calendar.setTime(gregorianDate);
    toPersian(gregorianDate);
}    

private void toPersian(Date gregorianDate) 
{
    if ((gregorianYear % 4) != 0) 
        func1();
    else 
        func2();
    strMonth = monthNames[month-1];
    strWeekDay = weekDayNames[WeekDay];
}

private void func1()
{
    day = buf1[gregorianMonth - 1] + gregorianDate;
    if (day > 79){
        day = day - 79;
        if (day <= 186) {               
            int day2 = day;
            month = (day2 / 31) + 1;
            day = (day2 % 31);
            if(day2 % 31 == 0){
                 month--;
                 day = 31;
            }                
            year = gregorianYear - 621;
        } 
        else {
            int day2 = day - 186;
            month = (day2 / 30) + 7;
            day = (day2 % 30);
            if(day2 % 30 == 0){
                month = (day2 / 30) + 6;
                day = 30;
            }
            year = gregorianYear - 621;
        }
    } 
    else{            
        ld = gregorianYear > 1996 && gregorianYear % 4 == 1 ? 11 : 10 ;            
        int day2 = day + ld;
        month = (day2 / 30) + 10;
        day = (day2 % 30);            
        if(day2 % 30 == 0)            {
            month--;
            day = 30;
        }
        year = gregorianYear - 622;
    }
}

private void func2()
{
    day = buf2[gregorianMonth - 1] + gregorianDate;     
    ld = gregorianYear >= 1996 ? 79 : 80 ;        
    if (day > ld) {
        day = day - ld;
        if (day <= 186) {
            int day2 = day;
            month = (day2 / 31) + 1;
            day = (day2 % 31);
            if(day2 % 31 == 0){
                month--;
                day = 31;
            }
            year = gregorianYear - 621;
        } else {
            int day2 = day - 186; 
            month = (day2 / 30) + 7;
            day = (day2 % 30);
            if(day2 % 30 == 0 ){
                month--;
                day = 30;
            }
            year = gregorianYear - 621;
        }
    }
    else {
        int day2 = day + 10;
        month = (day2 / 30) + 10;
        day = (day2 % 30);
        if(day2 % 30==0){
            month--;
            day = 30;
        }
        year = gregorianYear - 622;
    }
  }
}

tạo phiên bản

PersianCalendar sc = new PersianCalendar();            
String s= sc.strWeekDay  + " " +sc.day  + " " + 
     sc.strMonth + " " + sc.year;
System.out.print(s);
//setTitle(s);

2

persianutils dự án trong đó bao gồm một DateConverter hai chiều; Gregorian <-> tiếng Ba Tư (Jalali). Nó được viết bằng Scala, vì vậy tôi cho rằng việc sử dụng nó trong một dự án Java sẽ khá dễ dàng.

Thuật toán được sử dụng có hiệu lực đối với năm Gregorian lên đến ~ 3790 và năm Ba Tư lên đến ~ 3170.

KHUYẾN CÁO: Tôi là tác giả của PersianUtils


2

Bạn có thể sử dụng thư viện ổn định và đã được thử nghiệm này với một lớp định dạng, Roozh cho Java . Nó không bị phản đối và luôn được cập nhật các tính năng thú vị mà ngày giờ Ba Tư cần.


2

Tạo hàm CalculJalaliDate dưới dạng hàm như vậy; và sau đó trả về ngày Jalali trong Chuỗi

public String calculateJalaliDate(){

    Calendar c = Calendar.getInstance();
    String jalaliDate,JalaliMonth;
    int jalaliYear,jalaliMonth,calculateMonth,jalaliDay=0,allDays=0;
    int day=c.get(Calendar.DAY_OF_MONTH);
    int month=c.get(Calendar.MONTH)+1;
    int year=c.get(Calendar.YEAR);

    switch (month){
        case 1: allDays=year*365+31+day;break;
        case 2: allDays=year*365+(31+28)+day;break;
        case 3: allDays=year*365+(31+28+31)+day;break;
        case 4: allDays=year*365+(31+28+31+30)+day;break;
        case 5: allDays=year*365+(31+28+31+30+31)+day;break;
        case 6: allDays=year*365+(31+28+31+30+31+30)+day;break;
        case 7: allDays=year*365+(31+28+31+30+31+30+31)+day;break;
        case 8: allDays=year*365+(31+28+31+30+31+30+31+31)+day;break;
        case 9: allDays=year*365+(31+28+31+30+31+30+31+31+30)+day;break;
        case 10: allDays=year*365+(31+28+31+30+31+30+31+31+30+31)+day;break;
        case 11: allDays=year*365+(31+28+31+30+31+30+31+31+30+31+30)+day;break;
        case 12: allDays=year*365+(31+28+31+30+31+30+31+31+30+31+30+31)+day;break;
    }

    //226899
    jalaliYear=( allDays - 227139 )/365+1;
    calculateMonth=( allDays - 227139 )%365;
    if(calculateMonth<32)jalaliMonth=1;
    else if((calculateMonth-31)<32){jalaliMonth=2;jalaliDay=calculateMonth-31;}
    else if((calculateMonth-62)<32){jalaliMonth=3;jalaliDay=calculateMonth-62;}
    else if((calculateMonth-93)<32){jalaliMonth=4;jalaliDay=calculateMonth-93;}
    else if((calculateMonth-124)<32){jalaliMonth=5;jalaliDay=calculateMonth-124;}
    else if((calculateMonth-155)<32){jalaliMonth=6;jalaliDay=calculateMonth-155;}
    else if((calculateMonth-186)<31){jalaliMonth=7;jalaliDay=calculateMonth-186;}
    else if((calculateMonth-216)<31){jalaliMonth=8;jalaliDay=calculateMonth-216;}
    else if((calculateMonth-246)<31){jalaliMonth=9;jalaliDay=calculateMonth-246;}
    else if((calculateMonth-276)<31){jalaliMonth=10;jalaliDay=calculateMonth-276;}
    else if((calculateMonth-306)<31){jalaliMonth=11;jalaliDay=calculateMonth-306;}
    else {
        jalaliMonth=12;
        if((jalaliYear%4)==0)jalaliDay=calculateMonth-336;
        else jalaliDay=calculateMonth-335;
    }



    /*switch (jalaliMonth){
        case 1:JalaliMonth="فروردین"; break;
        case 2:JalaliMonth="اردیبهشت"; break;
        case 3:JalaliMonth="خرداد"; break;
        case 4:JalaliMonth="تیر"; break;
        case 5:JalaliMonth="مرداد"; break;
        case 6:JalaliMonth="شهریور"; break;
        case 7:JalaliMonth="مهر"; break;
        case 8:JalaliMonth="آبان"; break;
        case 9:JalaliMonth="آذر"; break;
        case 10:JalaliMonth="دی"; break;
        case 11:JalaliMonth="بهمن"; break;
        case 12:JalaliMonth="اسفند"; break;
    }*/


    jalaliDate=String.valueOf(jalaliYear)+"/"+String.valueOf(jalaliMonth)+"/"+String.valueOf(jalaliDay);
    return jalaliDate;
}


1

Ngoài Time4A, icu4j, là những thư viện quá nặng, tôi đã viết một lớp để xử lý lịch Ba Tư một cách chính xác và bạn có thể tìm thấy nó tại đây: https://github.com/hadilq/java-persian-calendar/blob/master/persian/src /main/java/ir/hadilq/PersianCalendar.java

Như bạn có thể tìm thấy trong các thử nghiệm của nó, lớp này hỗ trợ từ năm 3000 trước hijra đến 3000 sau hijra.


Cảm ơn bạn. Đây là giải pháp tốt nhất cho những nhà phát triển không muốn đưa các thư viện nặng của bên thứ ba vào dự án.
Oleksandr Albul
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.