не все годы, кратные 4, являются високосными. Исключение составляют числа, кратные 100, но не кратные 400. см .: wikipedia
Без названия
С какой датой у вас проблемы?
Bobs
Я использую этот алгоритм в своих приложениях уже 6 лет.
Bobs
26
вы должны использовать его в течение 100 лет, чтобы увидеть проблему :)
Без названия
11
Возможно, вы могли бы отредактировать первое предложение своего ответа, чтобы оно гласило: «... это очень точно между 1901 и 2099 годами». Этого может хватить для многих приложений; но некоторых разработчиков могут интересовать даты за пределами этого диапазона, и было бы неплохо предупредить их, что этот алгоритм будет недостаточно хорош.
Давуд ибн Карим
31
Я думаю, что этот класс Java проще в использовании и надежнее. Я нашел это в иранском форуме , иранцы используют календарь Джалали и называют его «Шамси», что означает солнечный календарь. это класс 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);
*/publicclassCalendarTool{
/**
* JavaSource_Calendar:
* The default constructor uses the current Gregorian date to initialize the
* other private memebers of the class (Iranian and Julian dates).
*/publicCalendarTool(){
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
*/publicCalendarTool(int year, int month, int day){
setGregorianDate(year,month,day);
}
/**
* getIranianYear:
* Returns the 'year' part of the Iranian date.
* @return int
*/publicintgetIranianYear(){
return irYear;
}
/**
* getIranianMonth:
* Returns the 'month' part of the Iranian date.
* @return int
*/publicintgetIranianMonth(){
return irMonth;
}
/**
* getIranianDay:
* Returns the 'day' part of the Iranian date.
* @return int
*/publicintgetIranianDay(){
return irDay;
}
/**
* getGregorianYear:
* Returns the 'year' part of the Gregorian date.
* @return int
*/publicintgetGregorianYear(){
return gYear;
}
/**
* getGregorianMonth:
* Returns the 'month' part of the Gregorian date.
* @return int
*/publicintgetGregorianMonth(){
return gMonth;
}
/**
* getGregorianDay:
* Returns the 'day' part of the Gregorian date.
* @return int
*/publicintgetGregorianDay(){
return gDay;
}
/**
* getJulianYear:
* Returns the 'year' part of the Julian date.
* @return int
*/publicintgetJulianYear(){
return juYear;
}
/**
* getJulianMonth:
* Returns the 'month' part of the Julian date.
* @return int
*/publicintgetJulianMonth(){
return juMonth;
}
/**
* getJulianDay()
* Returns the 'day' part of the Julian date.
* @return int
*/publicintgetJulianDay(){
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
*/publicintgetDayOfWeek(){
return (JDN % 7);
}
/**
* nextDay:
* Go to next julian day number (JDN) and adjusts the other dates.
*/publicvoidnextDay(){
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
*/publicvoidnextDay(int days){
JDN+=days;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
}
/**
* previousDay:
* Go to previous julian day number (JDN) and adjusts the otehr dates.
*/publicvoidpreviousDay(){
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
*/publicvoidpreviousDay(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
*/publicvoidsetIranianDate(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
*/publicvoidsetGregorianDate(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
*/publicvoidsetJulianDate(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)
*/privatevoidIranianCalendar(){
// Iranian years starting the 33-year ruleint 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 yearif ( (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)
*/publicbooleanIsLeap(int irYear1){
// Iranian years starting the 33-year ruleint 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 yearif ( (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)
returntrue;
elsereturnfalse;
}
/**
* 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)
*/privateintIranianDateToJDN(){
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.
*/privatevoidJDNToIranian(){
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
*/privateintjulianDateToJDN(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).
*/privatevoidJDNToJulian(){
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
*/privateintgregorianDateToJDN(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).
*/privatevoidJDNToGregorian(){
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;
}
privateint irYear; // Year part of a Iranian dateprivateint irMonth; // Month part of a Iranian dateprivateint irDay; // Day part of a Iranian dateprivateint gYear; // Year part of a Gregorian dateprivateint gMonth; // Month part of a Gregorian dateprivateint gDay; // Day part of a Gregorian dateprivateint juYear; // Year part of a Julian dateprivateint juMonth; // Month part of a Julian dateprivateint juDay; // Day part of a Julian dateprivateint leap; // Number of years since the last leap year (0 to 4)privateint JDN; // Julian Day Numberprivateint march; // The march day of Farvardin the first (First day of jaYear)
} // End of Class 'JavaSource_Calendar
Вы можете легко установить день, месяц и год по григорианскому календарю, а затем вызвать метод getIranianDate (), чтобы получить дату в строковом формате, как в примере кода ниже:
MyUtil.CalendarTool ct = new CalendarTool(2012,10,10);
System.out.println(ct.getIranianDate());
Думаю, это ошибка! Когда вы конвертируете сегодняшнюю дату (дату, когда я публикую этот комментарий), это будет «1396/01/20», но это будет «1395/12/20»
Мохсен Абаси,
Дает неправильный ответ.
Мейсам Мохаммади
Вы можете помочь мне отредактировать его и исправить ошибку.
Реза Амери
Код работает правильно как 10 апреля 2017 года, так и 14 апреля 2018 года
MMG
Я думаю, одна проблема заключается в том, что дни месяцев не ограничены, например, апрель - 30 дней, но кодовый ответ для 31 апреля такой же, как и 1 мая
MMG
20
Использование IBM «s International Components для Unicode ( ICU4J ). Он является частью Консорциума Unicode , чрезвычайно надежен и может использоваться в любом проекте Java (Java EE, Java SE, Android и т. Д.). Используйте его с Gradle , Maven или просто загрузив jar.
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;
publicclassDateTimeUtils{
publicstaticfinal ULocale PERSIAN_LOCALE = new ULocale("fa_IR@calendar=persian");
publicstaticfinal ULocale PERSIAN_EN_LOCALE = new ULocale("en@calendar=persian");
publicstaticfinal ZoneId IRAN_ZONE_ID = ZoneId.of("Asia/Tehran");
publicstatic 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
*/publicstaticintfromDateToPersianCalendarField(Date date, int field){
return fromDateToPersianCalendar(date).get(field);
}
publicstatic String fromDateToPersianString(Date date){
DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, PERSIAN_LOCALE);
return df.format(date);
}
publicstatic String fromDateToPersianString(Date date, String pattern){
returnnew SimpleDateFormat(pattern, PERSIAN_LOCALE).format(date);
}
publicstatic String fromDateToPersianString(Date date, String pattern, ULocale locale){
returnnew SimpleDateFormat(pattern, locale).format(date);
}
/**
* @param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
*/publicstatic Date fromPersianDateToDate(int year, int month, int day, int hour, int minutes, int seconds){
returnnew Date(fromPersianDate(year, month, day, hour, minutes, seconds));
}
/**
* @param month is zero based. (e.g. Farvardin = 0, Ordibehesht = 1, etc.)
*/publicstatic 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.)
*/publicstatic 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.)
*/publicstatic 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.)
*/publicstaticlongfromPersianDate(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();
}
publicstatic ZonedDateTime toZonedDateTime(Long epochMilli){
if(epochMilli == null) returnnull;
return Instant.ofEpochMilli(epochMilli).atZone(IRAN_ZONE_ID);
}
}
Применение:
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date;
import com.ibm.icu.util.Calendar;
publicclassDateTimeUtilsTest{
publicstaticvoidmain(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);
}
}
Вывод:
Java 7 and before:
Converting Gregorian date to Persian:
1395310
۱۳۹۵ تیر ۱۰, پنجشنبه
Adding 1 month and 5 days:
1395415
۱۳۹۵ مرداد ۱۵, جمعه
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
Более подробный:
Java 7 и ранее:
Вы можете ожидать все функции java.util.Calendarв дополнение к некоторым другим:
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
ВНИМАНИЕ ! Обратите внимание, что поле месяца в календаре Java равно нулю, поэтомуcalendar.set(1395, 3, 10) календарю будет отображаться 4-й месяц 1395 года, а не 3-й!
Если вам нужен текстовый вывод на персидском языке:
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()));
Если вам нужен вывод на английском языке, измените new ULocale("fa_IR@calendar=persian")наnew ULocale("en@calendar=persian") .
Вывод:
AP 1395 Tir 10, Thu
1395
Tir
Thu
95/04/10
Другие приятные мелочи:
// 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
Чтобы использовать java.timeтакие классы, как ZonedDateTimeили LocalDateTime, вы можете просто использовать эти методы для преобразования персидской даты в предпочтительные классы:
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;
...
publicstatic LocalDateTime fromPersianDateToLocalDateTime(int year, int month, int day, int hour, int minutes, int seconds){
return fromPersianDateToZonedDateTime(year, month, day, hour, minutes, seconds).toLocalDateTime();
}
publicstatic ZonedDateTime fromPersianDateToZonedDateTime(int year, int month, int day, int hour, int minutes, int seconds){
return toZonedDateTime(fromPersianDate(year, month, day, hour, minutes, seconds));
}
publicstaticlongfromPersianDate(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();
}
publicstatic ZonedDateTime toZonedDateTime(Long epochMilli){
if(epochMilli == null) returnnull;
return Instant.ofEpochMilli(epochMilli).atZone(ZoneId.of("Asia/Tehran"));
}
Замечания о размере банки
Если вас беспокоит размер jar-файла icu4j, вы можете перестроить его и просто использовать модуль Calendar (2176 КБ). Дополнительная информация: вер. 57 или ранее , вер. 58 или новее с помощью ICU Data Build Tool .
@deadManN Я обновил свой ответ. Надеюсь, это поможет.
Омид
1
@deadManN если под daysInMonth вы подразумеваете максимальное количество дней в определенном месяце, то, что вы ищете, может быть достигнуто путем вызова getActualMaximum(Calendar.DAY_OF_MONTH). Я обновил свой ответ, чтобы показать, как его использовать.
Омид
1
Я думаю, что ошибка с вашей стороны, потому что я проверил getActualMaximum(Calendar.DAY_OF_MONTH)все месяцы предыдущего, текущего и следующего года, и результат был правильным. Знаете ли вы, что месяц в календарях Java равен нулю? Если вы поместите 5 в поле месяца, это на самом деле означает 6-й месяц, а не 5-й! То же самое и с 11 (12-й месяц). Если это не так, не могли бы вы указать точные даты, которые могут привести к неправильному поведению?
Omid
1
Насколько я знаю, единственная «нетрадиционная» вещь - это то, что месяцы отсчитываются от нуля, больше не о чем беспокоиться. (На самом деле, в этом нет ничего необычного, потому что месяц - это в некотором роде перечисление!)
Омид
1
Лучший ответ! Потому что вы указали: «Он является частью Консорциума Unicode, чрезвычайно надежен и может использоваться в любом проекте Java». Также учтите,android.icu что начиная с Android 7.0 (уровень API 24), Android предоставляет подмножество API-интерфейсов ICU4J для разработчиков приложений для использования в пакете . Подробности здесь .
Мир-Исмаили
11
этот метод очень точен и просто поддерживает високосные годы
Объясните:
шаг 1: время сегодня содержит текущее время
шаг 2: создайте два массива для грегорианского и джалали-дня в месяцах (g_days_in_month и j_days_in_month)
Шаг 3: создайте переменную для разницы времени хранения между календарями (gy, gm, gd) и переменную g_day_no для дней в годах.
шаг 4: введите день месяца и соберите дни.
шаг 5: преобразовать дни в годах в годы джалили (jy)
в конце: установить месяц джалали из числа дня, установить день джалали из массива дней месяца джалали.
удачи.
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);
}
privateintdiv(float a, float b){
return (int)(a/b);
}
Вам следует попытаться объяснить свой ответ, а не просто опубликовать блок кода.
RyPeck
10
Последняя версия v3.10-2015g моей библиотеки Time4A (Android-адаптация Time4J) содержит поддержку календаря Jalali. Библиотека использует алгоритм Борковского (действителен до 2129 года по григорианскому календарю). Фактически для персидских месяцев и эпох поддерживаются около 25 языков (включая фарси и пушту на основе CLDR-28).
Примеры использования:
// 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
Взаимодействие с java.util.Date на Android
Поскольку Time4A управляет своим собственным набором неизменяемых типов и не основан на основном временном типе Android, я показываю следующий мост:
+1 к использованию метода Борковского для наибольшей точности. Я написал персидскую хронологию (ы) для Joda Time . Джалали основан на наблюдении времени весеннего равноденствия по долготе, Омар Хайям (расширенный Борковски) вывел быструю формулу из предсказаний равноденствия на ~ 450 лет. Предупреждение; Хайям использовал долготу Тегерана вместо IRST, используемой сейчас, поэтому 1 или 2 високосных года могут быть отключены в следующие 3 тысячи. Meno, пожалуйста, добавьте руководство по добавлению хронографа в Time4A на странице проекта.
Зубин Каварана
@ZubinKavarana Спасибо за ваш комментарий. Я действительно явно проверил в JUnit-test, что моя адаптация Борковского находится в точном соответствии с Хайямом для данного диапазона лет (~ 450 лет). Об учебнике: Хорошая идея, но вопрос: что вы подразумеваете под «добавлением хронографа»? Я собираюсь дополнить существующее руководство страницей об использовании различных календарей. Вы также найдете там онлайн-javadoc .
Meno Hochschild
@ZubinKavarana Если вы хотите сказать «как добавить новый календарь», сказав «добавление хронографа», что ж, я могу сделать это, добавив дополнительную страницу к упомянутому выше руководству. У вас есть идеи, предложения или планы по добавлению еще одного календаря? Вы также можете открыть проблему на time4j-github-issue-tracker, чтобы продолжить это обсуждение.
Мено Хохшильд
Я только что реализовал ваш пример и получаю две строки с сообщением об ошибке: в net.time4j.base.ResourceLoader.getInstance (неизвестный источник), в net.time4j.SystemClock. <clinit> (неизвестный источник). Как я мог отладить ошибку в библиотеке и найти ее причину?
Эфтехарьте
1
@Eftekhari Вы правильно инициализировали приложение с помощью ApplicationStarter.initialize(this, ...);? См. Также пример инициализации кода в Time4A - раздел Использование. Ваша трассировка стека указывает на эту причину.
Meno Hochschild
5
Попробуй это
import java.util.Calendar;
import java.util.Date;
publicclassPersianCalendar{
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};
publicPersianCalendar(){
Date gregorianDate = new Date();
calendar.setTime(gregorianDate);
toPersian(gregorianDate);
}
publicPersianCalendar(Date gregorianDate){
calendar.setTime(gregorianDate);
toPersian(gregorianDate);
}
privatevoidtoPersian(Date gregorianDate){
if ((gregorianYear % 4) != 0)
func1();
else
func2();
strMonth = monthNames[month-1];
strWeekDay = weekDayNames[WeekDay];
}
privatevoidfunc1(){
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;
}
}
privatevoidfunc2(){
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;
}
}
}
Есть persianutils проект который включает двунаправленный DateConverter; Григорианский <-> персидский (джалали). Он написан на Scala, поэтому я полагаю, что использовать его в проекте Java было бы довольно просто.
Используемый алгоритм действителен для григорианских лет до ~ 3790 и персидских лет до ~ 3170.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: я являюсь автором PersianUtils
Вы можете использовать эту стабильную и протестированную библиотеку с классом форматирования Roozh для Java . Он не устарел и постоянно обновляется с помощью интересных функций, которые нужны персидскому времени.
Ответы:
Я использую этот алгоритм годами, и он очень точен между 1901 и 2099 годами.
Используйте это и наслаждайтесь! :)
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); } }
источник
Я думаю, что этот класс Java проще в использовании и надежнее. Я нашел это в иранском форуме , иранцы используют календарь Джалали и называют его «Шамси», что означает солнечный календарь. это класс 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
Вы можете легко установить день, месяц и год по григорианскому календарю, а затем вызвать метод getIranianDate (), чтобы получить дату в строковом формате, как в примере кода ниже:
MyUtil.CalendarTool ct = new CalendarTool(2012,10,10); System.out.println(ct.getIranianDate());
Я надеюсь, что это помогает.
источник
Использование IBM «s International Components для Unicode ( ICU4J ). Он является частью Консорциума Unicode , чрезвычайно надежен и может использоваться в любом проекте Java (Java EE, Java SE, Android и т. Д.). Используйте его с Gradle , Maven или просто загрузив jar.
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); } }
Применение:
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); } }
Вывод:
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
Более подробный:
Java 7 и ранее:
Вы можете ожидать все функции
java.util.Calendar
в дополнение к некоторым другим: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
ВНИМАНИЕ ! Обратите внимание, что поле месяца в календаре Java равно нулю, поэтому
calendar.set(1395, 3, 10)
календарю будет отображаться 4-й месяц 1395 года, а не 3-й!Если вам нужен текстовый вывод на персидском языке:
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()));
Вывод:
Если вам нужен вывод на английском языке, измените
new ULocale("fa_IR@calendar=persian")
наnew ULocale("en@calendar=persian")
.Вывод:
AP 1395 Tir 10, Thu 1395 Tir Thu 95/04/10
Другие приятные мелочи:
// 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
Для других функций см. Демонстрации icu4j , особенно:
fa_IR
для локали)Также см. Календарь и PersianCalendar. API.
Java 8 и новее:
Чтобы использовать
java.time
такие классы, какZonedDateTime
илиLocalDateTime
, вы можете просто использовать эти методы для преобразования персидской даты в предпочтительные классы: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")); }
Замечания о размере банки
Если вас беспокоит размер jar-файла icu4j, вы можете перестроить его и просто использовать модуль Calendar (2176 КБ). Дополнительная информация: вер. 57 или ранее , вер. 58 или новее с помощью ICU Data Build Tool .
источник
getActualMaximum(Calendar.DAY_OF_MONTH)
. Я обновил свой ответ, чтобы показать, как его использовать.getActualMaximum(Calendar.DAY_OF_MONTH)
все месяцы предыдущего, текущего и следующего года, и результат был правильным. Знаете ли вы, что месяц в календарях Java равен нулю? Если вы поместите 5 в поле месяца, это на самом деле означает 6-й месяц, а не 5-й! То же самое и с 11 (12-й месяц). Если это не так, не могли бы вы указать точные даты, которые могут привести к неправильному поведению?android.icu
что начиная с Android 7.0 (уровень API 24), Android предоставляет подмножество API-интерфейсов ICU4J для разработчиков приложений для использования в пакете . Подробности здесь .этот метод очень точен и просто поддерживает високосные годы
Объясните:
шаг 1: время сегодня содержит текущее время
шаг 2: создайте два массива для грегорианского и джалали-дня в месяцах (g_days_in_month и j_days_in_month)
Шаг 3: создайте переменную для разницы времени хранения между календарями (gy, gm, gd) и переменную g_day_no для дней в годах.
шаг 4: введите день месяца и соберите дни.
шаг 5: преобразовать дни в годах в годы джалили (jy)
в конце: установить месяц джалали из числа дня, установить день джалали из массива дней месяца джалали.
удачи.
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); }
источник
Последняя версия v3.10-2015g моей библиотеки Time4A (Android-адаптация Time4J) содержит поддержку календаря Jalali. Библиотека использует алгоритм Борковского (действителен до 2129 года по григорианскому календарю). Фактически для персидских месяцев и эпох поддерживаются около 25 языков (включая фарси и пушту на основе CLDR-28).
Примеры использования:
// 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
Взаимодействие с java.util.Date на Android
Поскольку Time4A управляет своим собственным набором неизменяемых типов и не основан на основном временном типе Android, я показываю следующий мост:
// 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);
источник
ApplicationStarter.initialize(this, ...);
? См. Также пример инициализации кода в Time4A - раздел Использование. Ваша трассировка стека указывает на эту причину.Попробуй это
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; } } }
создать экземпляр
PersianCalendar sc = new PersianCalendar(); String s= sc.strWeekDay + " " +sc.day + " " + sc.strMonth + " " + sc.year; System.out.print(s); //setTitle(s);
источник
Есть persianutils проект который включает двунаправленный DateConverter; Григорианский <-> персидский (джалали). Он написан на Scala, поэтому я полагаю, что использовать его в проекте Java было бы довольно просто.
Используемый алгоритм действителен для григорианских лет до ~ 3790 и персидских лет до ~ 3170.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: я являюсь автором PersianUtils
источник
Вы можете использовать эту стабильную и протестированную библиотеку с классом форматирования Roozh для Java . Он не устарел и постоянно обновляется с помощью интересных функций, которые нужны персидскому времени.
источник
Создайте CalculJalaliDate как функцию: а затем верните дату Джалали в String
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; }
источник
Я разработал виджет DatePicker для Android Shamsi с просмотром событий hijri - gerogian- shamsi: https://github.com/irshst/ir.shes.calendar
источник
Помимо Time4A, icu4j, которые являются слишком тяжелыми библиотеками, я написал класс для точной обработки персидского календаря, и вы можете найти его здесь: https://github.com/hadilq/java-persian-calendar/blob/master/persian/src /main/java/ir/hadilq/PersianCalendar.java
Как вы можете убедиться в его тестах, этот класс поддерживает от 3000 года до хиджры до 3000 года после хиджры.
источник