Czy istnieje biblioteka lub algorytm kalendarza perskiego (Shamsi lub Jalali) w systemie Android? [Zamknięte]


81

Chcę przekonwertować datę gregoriańską (zachodnią) na perską (Shamsi) i odwrotnie dla wszystkich wersji Androida.

Czy istnieje kompletna i niezawodna biblioteka lub algorytm?


Odpowiedzi:


78

Używam tego algorytmu od lat i jest bardzo dokładny między 1901 a 2099 rokiem.

Użyj go i ciesz się! :)

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
nie wszystkie lata, które są wielokrotnością 4, są latami przestępnymi. Wyjątki stanowią wielokrotności 100, ale nie wielokrotność 400. zobacz: wikipedia
Bez tytułu,

Z jaką datą masz problem?
Bobs

W swoich aplikacjach używam tego algorytmu od 6 lat.
Bobs,

26
powinieneś używać go przez 100 lat, aby zobaczyć problem :)
Bez tytułu,

11
Być może mógłbyś zmienić pierwsze zdanie swojej odpowiedzi, tak aby brzmiało „... jest bardzo dokładne w latach 1901-2099”. Może to być wystarczające dla wielu aplikacji; ale niektórzy programiści mogą być zainteresowani datami spoza tego zakresu i byłoby miło ostrzec ich, że ten algorytm nie będzie wystarczająco dobry.
Dawood ibn Kareem

31

Myślę, że ta klasa java jest łatwiejsza w użyciu i bardziej niezawodna. Znalazłem go na irańskim forum , Irańczycy używają kalendarza Jalali i nazywają go „Shamsi”, co oznacza kalendarz słoneczny. to jest klasa 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

Możesz łatwo ustawić dzień, miesiąc i rok gregoriański, a następnie wywołać metodę „getIranianDate ()”, aby uzyskać datę w formacie ciągu, tak jak w poniższym przykładowym kodzie:

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

Mam nadzieję, że to pomoże.


3
Myślę, że jest błąd! Po przeliczeniu daty dzisiejszej (data, w której publikuję ten komentarz), będzie to „1396/01/20”, ale jest to „1395/12/20”
Mohsen Abasi,

Daje złą odpowiedź.
Meysam Mohammadi

Możesz mi pomóc w edycji i rozwiązaniu błędu.
Reza Ameri

Kod działa poprawnie zarówno dla kwietnia 10'17, jak i 14'18
MMG

Myślę, że jednym problemem jest to, że dni miesięcy nie są ograniczone, na przykład kwiecień to 30 dni, ale odpowiedź kodu dla 31 kwietnia i jest taka sama, jak 1 maja
MMG

20

Zastosowanie IBM „s International Components dla Unicode ( icu4j ). Jest częścią Unicode Consortium , jest wyjątkowo niezawodny i może być używany w dowolnym projekcie Java (Java EE, Java SE, Android itp.). Użyj go z Gradle , Maven lub po prostu pobierając słoik.

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);
    }
}

Stosowanie:

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);
    }
}

Wynik:

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

Bardziej szczegółowe:

Java 7 i starsze:

Możesz spodziewać się wszystkich funkcji java.util.Calendaroprócz kilku innych:

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

OSTRZEŻENIE : Zauważ, że w kalendarzu Java pole miesiąca jest zerowe, więc do dniacalendar.set(1395, 3, 10) kalendarza będzie reprezentował 4 miesiąc 1395 r., A nie 3-ci!

Jeśli potrzebujesz wyników tekstowych w języku perskim:

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()));

Wynik:

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

Jeśli chcesz, aby wyjście było w języku angielskim, zmień new ULocale("fa_IR@calendar=persian")na new ULocale("en@calendar=persian").

Wynik:

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

Inne fajne rzeczy:

// 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

Aby uzyskać informacje o innych funkcjach, zobacz dema icu4j , szczególnie:

Zobacz także Calendar i PersianCalendar API.

Java 8 i nowsze wersje:

Aby użyć java.timeklas takich jak ZonedDateTimelub LocalDateTime, możesz po prostu użyć tych metod, aby przekonwertować perską datę na preferowane klasy:

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"));
}

Uwagi dotyczące rozmiaru słoika

Jeśli obawiasz się rozmiaru jar icu4j, możesz go odbudować i po prostu użyć modułu Calendar (2,176 KB). Więcej informacji: wer. 57 lub starsza , wer. 58 lub nowszy przy użyciu narzędzia ICU Data Build Tool .


1
@deadManN Zaktualizowałem odpowiedź. Mam nadzieję, że to pomocne.
Omid

1
@deadManN jeśli przez daysInMonth masz na myśli maksymalną liczbę dni w określonym miesiącu, to czego szukasz można osiągnąć poprzez wywołanie getActualMaximum(Calendar.DAY_OF_MONTH). Zaktualizowałem odpowiedź, aby pokazać, jak z niej korzystać.
Omid

1
Myślę, że popełniłeś błąd, ponieważ sprawdziłem getActualMaximum(Calendar.DAY_OF_MONTH)wszystkie miesiące poprzedniego, bieżącego i przyszłego roku i wynik był poprawny. Czy wiesz, że w kalendarzach Java miesiąc jest zerowy? Jeśli umieścisz 5 w polu miesiąca, w rzeczywistości oznacza to 6 miesiąc, a nie 5! To samo dotyczy 11 (12 miesiąca). Jeśli tak nie jest, czy możesz podać dokładne daty powodujące niewłaściwe zachowanie?
Omid

1
O ile wiem, jedyną „niekonwencjonalną” rzeczą są miesiące zerowe, nie ma się czym martwić. (Właściwie nie jest to niekonwencjonalne, ponieważ miesiąc jest w pewnym sensie wyliczeniem!)
Omid

1
Najlepsza odpowiedź! Ponieważ wskazałeś: „Jest częścią Konsorcjum Unicode, jest wyjątkowo niezawodny i może być używany w każdym projekcie Java”. Weźandroid.icu również pod uwagę, że począwszy od systemu Android 7.0 (poziom interfejsu API 24), system Android udostępnia podzbiór interfejsów API ICU4J dla deweloperów aplikacji do wykorzystania w ramach pakietu . Zobacz szczegóły tutaj .
Mir-Ismaili

11

ta metoda jest bardzo dokładna i po prostu obsługuje lata przestępne

Wyjaśnić:

krok 1: dzisiejszy czas zawiera aktualny czas

krok 2: utwórz dwie tablice dla dnia gregoriańskiego i jalali w miesiącach (g_days_in_month & j_days_in_month)

krok 3: utwórz zmienną dla różnicy czasu retencji między kalendarzami (gy, gm, gd) i zmienną g_day_no dla dni lat.

krok 4: wstaw dzień miesiąca i zbieraj dniami.

krok 5: zamień dni lat na lata jalili (jy)

na końcu: ustaw jalali miesiąc od numeru dnia, ustaw dzień jalali z tablicy jalali dzień miesiąca.

powodzenia.

    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
Powinieneś spróbować wyjaśnić swoją odpowiedź, zamiast umieszczać po prostu blok kodu.
RyPeck

10

Najnowsza wersja v3.10-2015g mojej biblioteki Time4A (adaptacja Time4J na Androida) zawiera wsparcie dla kalendarza Jalali. Biblioteka wykorzystuje algorytm Borkowskiego (ważny do gregoriańskiego roku 2129). W rzeczywistości obsługiwanych jest około 25 języków dla perskich miesięcy i epok (w tym perski i paszto, w oparciu o CLDR-28).

Przykłady użycia:

// 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

Współdziałanie z java.util.Date na Androida

Ponieważ Time4A zarządza własnym zestawem niezmiennych typów i nie jest oparty na podstawowym czasowym typie Androida, pokazuję następujący most:

// 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 do stosowania metody Borkowskiego dla największej dokładności. Napisałem perską chronologię (y) dla Joda Time . Jalali opiera się na obserwacji czasu równonocy wiosennej na długości geograficznej, Omar Khayyam (rozszerzony przez Borkowskiego) wyprowadził szybki wzór z prognoz równonocy na ~ 450 lat. Zastrzeżenie; Khayyam użył długości geograficznej Teheranu zamiast stosowanej obecnie IRST, więc 1 lub 2 lata przestępne mogą być wyłączone w ciągu najbliższych 3 km. Meno, dodaj samouczek dotyczący dodawania chronometru do Time4A na stronie projektu.
Zubin Kavarana

@ZubinKavarana Dzięki za komentarz. Rzeczywiście wyraźnie zweryfikowałem jako JUnit-test, że moja adaptacja Borkowskiego jest w ścisłej zgodności z Khayyamem dla danego zakresu lat (~ 450 lat). O samouczku: Dobry pomysł, ale pytanie: Co masz na myśli, mówiąc o „dodaniu chronografu”? Mam na myśli rozszerzenie mojego istniejącego tutoriala o stronę o używaniu różnych kalendarzy. Znajdziesz tam również javadoc online .
Meno Hochschild

@ZubinKavarana Jeśli chcesz powiedzieć „jak dodać nowy kalendarz”, mówiąc „dodaj chronograf”, mogę to zrobić, dodając dodatkową stronę do wspomnianego powyżej samouczka. Czy masz jakieś pomysły, sugestie lub plany dotyczące dodania kolejnego kalendarza? Możesz również otworzyć problem na time4j-github-issue-tracker, aby kontynuować tę dyskusję.
Meno Hochschild

Właśnie zaimplementowałem Twój przykład i otrzymuję te dwie linie błędu: w net.time4j.base.ResourceLoader.getInstance (nieznane źródło), w net.time4j.SystemClock. <clinit> (nieznane źródło). Jak mogę zdebugować błąd w bibliotece i znaleźć jego przyczynę?
Eftekhari

1
@Eftekhari Czy poprawnie zainicjowałeś swoją aplikację przy użyciu ApplicationStarter.initialize(this, ...);? Zobacz także przykład inicjalizacji kodu w sekcji Time4A - użycie. Twój ślad stosu wskazuje na tę przyczynę.
Meno Hochschild

5

Spróbuj tego

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;
    }
  }
}

utwórz instancję

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

2

Istnieje projekt persianutils , który zawiera dwukierunkowy DateConverter; Gregoriański <-> perski (Jalali). Jest napisany w Scali, więc przypuszczam, że użycie go w projekcie Java byłoby całkiem proste.

Zastosowany algorytm obowiązuje dla lat gregoriańskich do ~ 3790 i perskich do ~ 3170.

ZRZECZENIE SIĘ: Jestem autorem PersianUtils


2

Możesz używać tej stabilnej i przetestowanej biblioteki z klasą programu formatującego, Roozh for Java . Nie jest przestarzały i zawsze jest aktualizowany o fajne funkcje, których potrzebuje perska data i godzina.


2

Utwórz funkcję obliczJalaliDate jako taką funkcję; a następnie zwróć datę Jalali w ciągu znaków

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

Oprócz Time4A, icu4j, które są zbyt rozbudowanymi bibliotekami, napisałem klasę, aby dokładnie obsługiwać kalendarz perski i możesz ją znaleźć tutaj: https://github.com/hadilq/java-persian-calendar/blob/master/persian/src /main/java/ir/hadilq/PersianCalendar.java

Jak widać w jej testach, ta klasa obsługuje od roku 3000 przed hidżrą do 3000 po hidżrze.


Dziękuję Ci. To najlepsze rozwiązanie dla programistów, którzy nie chcą umieszczać w projekcie ciężkich bibliotek innych firm.
Oleksandr Albul
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.