no todos los años, que son múltiplos de 4, son años bisiestos. Los que son múltiplos de 100, pero no múltiplos de 400, son excepciones. ver: wikipedia
Sin título
¿Con qué fecha estás teniendo problemas?
Bobs
Estoy usando este algoritmo durante 6 años en mis aplicaciones.
Bobs
26
debería usarlo durante 100 años para ver el problema :)
Sin título
11
Quizás podría editar la primera oración de su respuesta, de modo que diga "... es muy precisa entre 1901 y 2099". Esto puede ser adecuado para muchas aplicaciones; pero algunos desarrolladores pueden estar interesados en fechas fuera de este rango, y sería bueno advertirles que este algoritmo no será lo suficientemente bueno.
Dawood ibn Kareem
31
Creo que esta clase de Java es más fácil de usar y más confiable. Lo encontré en un foro iraní , los iraníes usan el calendario Jalali y lo llaman "Shamsi", que significa calendario solar. esta es la clase 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
You can easily set the Gregorian Day, Month and Year, then call "getIranianDate()" method to get the date in string format, just like the sample code below:
MyUtil.CalendarTool ct = new CalendarTool(2012,10,10);
System.out.println(ct.getIranianDate());
I think there is a bug! When you convert today date(the date I'm posting this comment) it would be '1396/01/20' but it is '1395/12/20'
Mohsen Abasi
It gives wrong answer.
Meysam Mohammadi
You may help me to edit it and resolve the bug.
Reza Ameri
Code works correctly for both Apr 10'17 and Apr 14'18
MMG
I think one problem is that days of months are not bounded, for example April is 30 days, but the code answer for Apr31 and it is the same as May1
MMG
20
Use IBM's International Components for Unicode (icu4j). It is part of Unicode Consortium, is extremely reliable and can be used in any java project (Java EE, Java SE, Android, etc). Use it with Gradle, Maven or simply by downloading the 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);
}
}
Usage:
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);
}
}
Output:
Java 7 and before:
Converting Gregorian date to Persian:
1395310
۱۳۹۵ تیر ۱۰, پنجشنبه
Adding 1 month and 5 days:
1395415
۱۳۹۵ مرداد ۱۵, جمعه
Converting Persian date to Gregorian:
Thu Jun 3009: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
More detailed:
Java 7 and before:
You can expect all of functionalities of java.util.Calendar in addition to some other ones:
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
WARNING: Note that month field is zero based in Java calendar so by calendar.set(1395, 3, 10) calendar will represent 4th month of 1395, not 3rd!
If you need text outputs in persian:
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()));
If you need output to be in english, change new ULocale("fa_IR@calendar=persian") to new ULocale("en@calendar=persian").
Output:
AP 1395 Tir 10, Thu
1395
Tir
Thu
95/04/10
Other nice things:
// 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
For other functionalities see icu4j demos, specially:
In order to use java.time classes like ZonedDateTime or LocalDateTime, you could simply use this methods to convert a persian date to preferred classes:
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"));
}
@deadManN I updated my answer. I hope it's helpful.
Omid
1
@deadManN if by daysInMonth you mean maximum number of days in a certain month, what you're looking for can be achieved by invoking getActualMaximum(Calendar.DAY_OF_MONTH). I updated my answer to show how to use it.
Omid
1
I think mistake is on your part because I checked getActualMaximum(Calendar.DAY_OF_MONTH) for all months of previous, current and next year and the result was correct. Are you aware that month is zero based in Java calendars? If you put 5 in month field, it actually means 6th month not 5th! The same goes for 11 (12th month). If that's not the case, can you please provide exact dates that result in wrong behavior?
Omid
1
As far as I know the only "unconventional" thing is months being zero based, nothing more to be worried about. (Actually, it's not unconventional because month is an enum in a way!)
Omid
1
The best answer! Because that you pointed: "It is part of Unicode Consortium, is extremely reliable and can be used in any java project". Also consider that starting in Android 7.0 (API level 24), Android exposes a subset of the ICU4J APIs for app developers to use under the android.icu package. See details here.
Mir-Ismaili
11
this method is very exact and simply also support leap years
Explain:
step 1:
time today is contain current time
step 2:
create two array for gregorian and jalali day in months(g_days_in_month&j_days_in_month)
step 3:
create variable for retention difference time between calendars
(gy,gm,gd)
and variable g_day_no for days of years.
step 4:
insert day of month and collect with days.
step 5:
convert days of years to jalili years (jy)
at the end :
set jalali month from day number,
set jalali day from jalali day of month array.
good luck.
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);
}
You should attempt to explain your answer instead of just posting a block of code.
RyPeck
10
The newest version v3.10-2015g of my library Time4A (an Android adaptation of Time4J) contains support for the Jalali calendar. The library deploys the algorithm of Borkowski (valid until gregorian year 2129). Actually about 25 languages are supported for Persian months and eras (including Farsi and Pashto, based on CLDR-28).
Examples of usage:
// 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
Interoperability with java.util.Date on Android
Since Time4A manages its own set of immutable types and is not based on the primary temporal type of Android, I show following bridge:
+1 to using the Borkowski method for greatest accuracy. I wrote the Persian Chronology(s) for Joda Time. Jalali is based on observing the vernal equinox time at a longitude, Omar Khayyam (extended by Borkowski) derived a fast formula from equinox predictions for ~450 years. The caveat; Khayyam used the Tehran longitude instead of the IRST used now, so 1 or 2 leap years may be off in the next 3k. Meno, please add a tutorial on adding a chrono to Time4A on the project page.
Zubin Kavarana
@ZubinKavarana Thanks for your comment. I have indeed explicitly verified as JUnit-test that my adaptation of Borkowski is in exact agreement with Khayyam for given year range (~450 years). About tutorial: Good idea but a question: What do you mean by "adding a chrono"? I have in mind to extend my existing tutorial with a page about using various calendars. You will also find an online-javadoc there.
Meno Hochschild
@ZubinKavarana If you want to say "how to add a new calendar" by saying "adding a chrono", well, I can do this by adding an extra page to mentioned tutorial above. Have you any ideas, suggestions or plans for adding another calendar? You can also open an issue on time4j-github-issue-tracker to continue this discussion.
Meno Hochschild
I just implemented your example and I get this two lines of Error: at net.time4j.base.ResourceLoader.getInstance(Unknown Source), at net.time4j.SystemClock.<clinit>(Unknown Source). How could I debug error in the library and find the cause of it?
Eftekhari
1
@Eftekhari Have you correctly initialized your app using ApplicationStarter.initialize(this, ...);? See also code initialization example on Time4A - Usage section. Your stacktrace indicates that cause.
Meno Hochschild
5
Try this
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;
}
}
}
There is persianutils project which includes a bi-directional DateConverter; Gregorian <-> Persian (Jalali). It is written in Scala, so I suppose using it in a Java project would be quite easy.
The algorithm used is valid for Gregorian years up to ~3790 and Persian years up to ~3170.
You may use this stable and tested library with a formatter class, Roozh for Java. It's not deprecated and always getting updated with cool features which Persian date time needs.
Respuestas:
Estoy usando este algoritmo durante años y es muy preciso entre 1901 y 2099.
¡Úselo y disfrute! :)
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); } }
fuente
Creo que esta clase de Java es más fácil de usar y más confiable. Lo encontré en un foro iraní , los iraníes usan el calendario Jalali y lo llaman "Shamsi", que significa calendario solar. esta es la clase 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
You can easily set the Gregorian Day, Month and Year, then call "getIranianDate()" method to get the date in string format, just like the sample code below:
MyUtil.CalendarTool ct = new CalendarTool(2012,10,10); System.out.println(ct.getIranianDate());
I hope it helps.
fuente
Use IBM's International Components for Unicode (icu4j). It is part of Unicode Consortium, is extremely reliable and can be used in any java project (Java EE, Java SE, Android, etc). Use it with Gradle, Maven or simply by downloading the 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); } }
Usage:
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); } }
Output:
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
More detailed:
Java 7 and before:
You can expect all of functionalities of
java.util.Calendar
in addition to some other ones: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
WARNING: Note that month field is zero based in Java calendar so by
calendar.set(1395, 3, 10)
calendar will represent 4th month of 1395, not 3rd!If you need text outputs in persian:
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()));
Output:
If you need output to be in english, change
new ULocale("fa_IR@calendar=persian")
tonew ULocale("en@calendar=persian")
.Output:
AP 1395 Tir 10, Thu 1395 Tir Thu 95/04/10
Other nice things:
// 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
For other functionalities see icu4j demos, specially:
fa_IR
for locale)Also see Calendar and PersianCalendar API.
Java 8 onward:
In order to use
java.time
classes likeZonedDateTime
orLocalDateTime
, you could simply use this methods to convert a persian date to preferred classes: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")); }
Remarks About Jar Size
If you're concerned about icu4j's jar size , then you may rebuild it and just use the Calendar module (2,176KB). More Info: ver. 57 or earlier , ver. 58 or later using ICU Data Build Tool.
fuente
getActualMaximum(Calendar.DAY_OF_MONTH)
. I updated my answer to show how to use it.getActualMaximum(Calendar.DAY_OF_MONTH)
for all months of previous, current and next year and the result was correct. Are you aware that month is zero based in Java calendars? If you put 5 in month field, it actually means 6th month not 5th! The same goes for 11 (12th month). If that's not the case, can you please provide exact dates that result in wrong behavior?android.icu
package. See details here.this method is very exact and simply also support leap years
Explain:
step 1: time today is contain current time
step 2: create two array for gregorian and jalali day in months(g_days_in_month&j_days_in_month)
step 3: create variable for retention difference time between calendars (gy,gm,gd) and variable g_day_no for days of years.
step 4: insert day of month and collect with days.
step 5: convert days of years to jalili years (jy)
at the end : set jalali month from day number, set jalali day from jalali day of month array.
good luck.
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); }
fuente
The newest version v3.10-2015g of my library Time4A (an Android adaptation of Time4J) contains support for the Jalali calendar. The library deploys the algorithm of Borkowski (valid until gregorian year 2129). Actually about 25 languages are supported for Persian months and eras (including Farsi and Pashto, based on CLDR-28).
Examples of usage:
// 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
Interoperability with java.util.Date on Android
Since Time4A manages its own set of immutable types and is not based on the primary temporal type of Android, I show following bridge:
// 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);
fuente
ApplicationStarter.initialize(this, ...);
? See also code initialization example on Time4A - Usage section. Your stacktrace indicates that cause.Try this
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; } } }
create instance
PersianCalendar sc = new PersianCalendar(); String s= sc.strWeekDay + " " +sc.day + " " + sc.strMonth + " " + sc.year; System.out.print(s); //setTitle(s);
fuente
There is persianutils project which includes a bi-directional DateConverter; Gregorian <-> Persian (Jalali). It is written in Scala, so I suppose using it in a Java project would be quite easy.
The algorithm used is valid for Gregorian years up to ~3790 and Persian years up to ~3170.
DISCLAIMER: I am the author of PersianUtils
fuente
You may use this stable and tested library with a formatter class, Roozh for Java. It's not deprecated and always getting updated with cool features which Persian date time needs.
fuente
Create the calculateJalaliDate as function like so; and then return the Jalali date in 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; }
fuente
I have developed Android Shamsi datepicker widget with hijri - gerogian- shamsi event view: https://github.com/irshst/ir.shes.calendar
fuente
Beside Time4A, icu4j, which are too heavy libraries, I written a class to handle Persian calendar accurately and you can find it here: https://github.com/hadilq/java-persian-calendar/blob/master/persian/src/main/java/ir/hadilq/PersianCalendar.java
As you can find it in its tests, this class supports from year 3000 before hijra to 3000 after hijra.
fuente