/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.omidp.util;
/**
*
* @author Omid Pourhadi Email : omidpourhadi AT gmail DOT com
*
*/
public class PersianCalendar {
public static String CONSTANT_Delimiter = "/";
public static final double PERSIAN_EPOCH = 1948320.5;;
public static final double GREGORIAN_EPOCH = 1721425.5;
/**
* @param solarDateAsTimeStamp
* .toString()
* @return gregorian date format e.g 2008-03-31 or this method customize for
* adempiere
*/
public String SolarToGregorian(String solarDateAsTimeStamp) {
if (solarDateAsTimeStamp.indexOf("-") != -1) {
CONSTANT_Delimiter = "-";
} else {
CONSTANT_Delimiter = "/";
}
if (solarDateAsTimeStamp.length() > 0) {
String[] dateElement = solarDateAsTimeStamp.toString().split(
CONSTANT_Delimiter);
//
int m_currentYear = Integer.parseInt(dateElement[0]);
int m_currentMonth = Integer.parseInt(dateElement[1]);
String[] daywithtime = dateElement[2].split(" ");
int m_currentDay = Integer.parseInt(daywithtime[0]);
// in some date format like 08 year is less than 1387
if (m_currentYear < 1300)
m_currentYear += 1300;
String day, month, year;
day = Integer.toString(m_currentDay);
month = Integer.toString(m_currentMonth);
year = Integer.toString(m_currentYear);
if (m_currentDay < 10)
day = "0" + day;
if (m_currentMonth < 10)
month = "0" + month;
if (daywithtime.length > 2) {
solarDateAsTimeStamp = convertJdnToGregorian(convertPersianToJdn(
m_currentYear, m_currentMonth, m_currentDay))
+ " "
+ daywithtime[1] + " " + daywithtime[2];
solarDateAsTimeStamp = changeFormat(solarDateAsTimeStamp) + " "
+ daywithtime[1] + " " + daywithtime[2];
} else if (daywithtime.length > 1 && daywithtime.length < 3)
solarDateAsTimeStamp = convertJdnToGregorian(convertPersianToJdn(
m_currentYear, m_currentMonth, m_currentDay))
+ " "
+ daywithtime[1];
else
solarDateAsTimeStamp = convertJdnToGregorian(convertPersianToJdn(
m_currentYear, m_currentMonth, m_currentDay));
}
return solarDateAsTimeStamp;
}
/**
* @param gregorianDateAsTimeStamp
* .toString() format supported 08/07/17 10:00 AM, 2008/07/17,
* 2008-03-31 12:59:00.00, 2008-07-17 this is main method of
* convertion other methods use this
* @return solar date format e.g 1387-01-01
*/
public String GregorianToSolar(String gregorianDateAsTimeStamp) {
if (gregorianDateAsTimeStamp.indexOf("-") != -1) {
CONSTANT_Delimiter = "-";
} else {
CONSTANT_Delimiter = "/";
}
if (gregorianDateAsTimeStamp.length() > 0) {
String[] dateElement = gregorianDateAsTimeStamp.toString().split(
CONSTANT_Delimiter);
int m_currentYear = Integer.parseInt(dateElement[0]);
int m_currentMonth = Integer.parseInt(dateElement[1]);
String[] daywithtime = dateElement[2].split(" ");
int m_currentDay = Integer.parseInt(daywithtime[0]);
/**
* this check is for short simple date format 7/25/08 10:00 AM after
* format fix we don not need to use this in solar method again
* */
if (daywithtime.length > 2) {
m_currentYear = Integer.parseInt(daywithtime[0]);
m_currentMonth = Integer.parseInt(dateElement[0]);
m_currentDay = Integer.parseInt(dateElement[1]);
}
String day, month, year;
day = Integer.toString(m_currentDay);
month = Integer.toString(m_currentMonth);
year = Integer.toString(m_currentYear);
if (m_currentDay < 10)
day = "0" + day;
if (m_currentMonth < 10)
month = "0" + month;
/** usin supprot for this format 7/25/08 10:00 AM */
if (daywithtime.length > 2)
gregorianDateAsTimeStamp = convertJdnToPersian(convertGregorianToJdn(
m_currentYear, m_currentMonth, m_currentDay))
+ " "
+ daywithtime[1] + " " + daywithtime[2];
/** 2008-03-31 12:59:00.00 */
else if (daywithtime.length > 1 && daywithtime.length < 3)
gregorianDateAsTimeStamp = convertJdnToPersian(convertGregorianToJdn(
m_currentYear, m_currentMonth, m_currentDay))
+ " "
+ daywithtime[1];
/** 2008-07-17, 2008/07/17 */
else
gregorianDateAsTimeStamp = convertJdnToPersian(convertGregorianToJdn(
m_currentYear, m_currentMonth, m_currentDay));
}
return gregorianDateAsTimeStamp;
}
/**
* @param gYear
* @param gMonth
* @param gDay
* @return
*/
public String GregorianToSolar(int gYear, int gMonth, int gDay) {
String compondDate = String.valueOf(gYear) + CONSTANT_Delimiter
+ String.valueOf(gMonth).concat(CONSTANT_Delimiter)
+ String.valueOf(gDay);
return GregorianToSolar(compondDate);
}
/**
* @param gregorianDate
* as timestamp.toString()
* @return
*/
public int getSolarYear(String gregorianDate) {
int solarYear = 0;
String[] spliterDate = GregorianToSolar(gregorianDate).split(
CONSTANT_Delimiter);
solarYear = Integer.parseInt(spliterDate[0]);
return solarYear;
}
/**
* @param gYear
* @param gMonth
* @param gDay
* @return
*/
public int getSolarYear(int gYear, int gMonth, int gDay) {
int solarYear = 0;
String gregorianDate = String.valueOf(gYear) + CONSTANT_Delimiter
+ String.valueOf(gMonth).concat(CONSTANT_Delimiter)
+ String.valueOf(gDay);
String[] spliterDate = GregorianToSolar(gregorianDate).split(
CONSTANT_Delimiter);
solarYear = Integer.parseInt(spliterDate[0]);
return solarYear;
}
/**
* @param gregorianDate
* as timestamp.toString()
* @return
*/
public int getSolarMonth(String gregorianDate) {
int solarMonth = 0;
String[] spliterDate = GregorianToSolar(gregorianDate).split(
CONSTANT_Delimiter);
solarMonth = Integer.parseInt(spliterDate[1]);
return solarMonth;
}
/**
* @param gYear
* @param gMonth
* @param gDay
* @return
*/
public int getSolarMonth(int gYear, int gMonth, int gDay) {
int solarMonth = 0;
String gregorianDate = String.valueOf(gYear) + CONSTANT_Delimiter
+ String.valueOf(gMonth).concat(CONSTANT_Delimiter)
+ String.valueOf(gDay);
String[] spliterDate = GregorianToSolar(gregorianDate).split(
CONSTANT_Delimiter);
solarMonth = Integer.parseInt(spliterDate[1]);
return solarMonth;
}
/**
* @param gregorianDate
* as timestamp.toString()
* @return
*/
public int getSolarDay(String gregorianDate) {
int solarDay = 0;
String[] spliterDate = GregorianToSolar(gregorianDate).split(
CONSTANT_Delimiter);
solarDay = Integer.parseInt(spliterDate[2]);
return solarDay;
}
/**
* @param gYear
* @param gMonth
* @param gDay
* @return
*/
public int getSolarDay(int gYear, int gMonth, int gDay) {
int solarDay = 0;
String gregorianDate = String.valueOf(gYear) + CONSTANT_Delimiter
+ String.valueOf(gMonth).concat(CONSTANT_Delimiter)
+ String.valueOf(gDay);
String[] spliterDate = GregorianToSolar(gregorianDate).split(
CONSTANT_Delimiter);
solarDay = Integer.parseInt(spliterDate[2]);
return solarDay;
}
/**
* @param solarYear
* @param solarMonth
* @param solarDay
* @return only return gregorian year
*/
public int getGregorianYear(int sYear, int sMonth, int sDay) {
int gregorianYear = 0;
String solarDate = String.valueOf(sYear) + CONSTANT_Delimiter
+ String.valueOf(sMonth).concat(CONSTANT_Delimiter)
+ String.valueOf(sDay);
String[] spliterDate = SolarToGregorian(solarDate).split(
CONSTANT_Delimiter);
gregorianYear = Integer.parseInt(spliterDate[0]);
return gregorianYear;
}
/**
* @param solarYear
* @param solarMonth
* @param solarDay
* @return only return gregorian Month
*/
public int getGregorianMonth(int sYear, int sMonth, int sDay) {
int gregorianMonth = 0;
String solarDate = String.valueOf(sYear) + CONSTANT_Delimiter
+ String.valueOf(sMonth).concat(CONSTANT_Delimiter)
+ String.valueOf(sDay);
String[] spliterDate = SolarToGregorian(solarDate).split(
CONSTANT_Delimiter);
gregorianMonth = Integer.parseInt(spliterDate[1]);
return gregorianMonth;
}
/**
* @param solaarYear
* @param solarMonth
* @param solarDay
* @return only return gregorian day
*/
public int getGregorianDay(int sYear, int sMonth, int sDay) {
int gregorianDay = 0;
String solarDate = String.valueOf(sYear) + CONSTANT_Delimiter
+ String.valueOf(sMonth).concat(CONSTANT_Delimiter)
+ String.valueOf(sDay);
String[] spliterDate = SolarToGregorian(solarDate).split(
CONSTANT_Delimiter);
gregorianDay = Integer.parseInt(spliterDate[2]);
return gregorianDay;
}
public static boolean Leap_Persian(int year) {
return ((((((year - ((year > 0) ? 474 : 473)) % 2820) + 474) + 38) * 682) % 2816) < 682;
}
// LEAP_GREGORIAN -- Is a given year in the Gregorian calendar a leap year ?
public boolean Leap_Gregorian(double year) {
return ((year % 4) == 0)
&& (!(((year % 100) == 0) && ((year % 400) != 0)));
}
/** Convert to JDN */
// GREGORIAN_TO_JD -- Determine Julian day number from Gregorian calendar
// date
public double convertGregorianToJdn(double year, double month, int day) {
return (GREGORIAN_EPOCH - 1)
+ (365 * (year - 1))
+ Math.floor((year - 1) / 4)
+ (-Math.floor((year - 1) / 100))
+ Math.floor((year - 1) / 400)
+ Math.floor((((367 * month) - 362) / 12)
+ ((month <= 2) ? 0 : (Leap_Gregorian(year) ? -1 : -2))
+ day);
}
// JULIAN_TO_JD -- Determine Julian day number from Julian calendar date
public double convertJulianToJdn(int year, int month, int day) {
/* Adjust negative common era years to the zero-based notation we use. */
if (year < 1) {
year++;
}
/*
* Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page
* 61
*/
if (month <= 2) {
year--;
month += 12;
}
return ((Math.floor((365.25 * (year + 4716)))
+ Math.floor((30.6001 * (month + 1))) + day) - 1524.5);
}
// PERSIAN_TO_JD -- Determine Julian day from Persian date
public double convertPersianToJdn(double year, double month, double day) {
double epbase, epyear;
epbase = year - ((year >= 0) ? 474 : 473);
epyear = 474 + mod(epbase, 2820);
return day
+ ((month <= 7) ? ((month - 1) * 31) : (((month - 1) * 30) + 6))
+ Math.floor(((epyear * 682) - 110) / 2816) + (epyear - 1)
* 365 + Math.floor(epbase / 2820) * 1029983
+ (PERSIAN_EPOCH - 1);
}
/** JDN Converts to other */
/**
* @param jdn
* @return
*/
public String convertJdnToPersian(double jd) {
double year, month, day, depoch, cycle, cyear, ycycle, aux1, aux2, yday;
jd = Math.floor(jd) + 0.5;
depoch = jd - convertPersianToJdn(475, 1, 1);
cycle = Math.floor(depoch / 1029983);
cyear = mod(depoch, 1029983);
if (cyear == 1029982) {
ycycle = 2820;
} else {
aux1 = Math.floor(cyear / 366);
aux2 = mod(cyear, 366);
ycycle = Math
.floor(((2134 * aux1) + (2816 * aux2) + 2815) / 1028522)
+ aux1 + 1;
}
year = ycycle + (2820 * cycle) + 474;
if (year <= 0) {
year--;
}
yday = (jd - convertPersianToJdn(year, 1, 1)) + 1;
month = (yday <= 186) ? Math.ceil(yday / 31) : Math
.ceil((yday - 6) / 30);
day = (jd - convertPersianToJdn(year, month, 1)) + 1;
String strYear = Integer.toString((int) year), strMonth = Integer
.toString((int) month), strDay = Integer.toString((int) day);
if (strMonth.length() < 2)
strMonth = "0" + strMonth;
if (strDay.length() < 2)
strDay = "0" + strDay;
return strYear + CONSTANT_Delimiter + strMonth + CONSTANT_Delimiter
+ strDay;
}
/**
* @param jdn
* @return
*/
public String convertJdnToGregorian(double jd) {
double wjd, depoch, quadricent, dqc, cent, dcent, quad, dquad, yindex, dyindex, year, yearday, leapadj;
wjd = Math.floor(jd - 0.5) + 0.5;
depoch = wjd - GREGORIAN_EPOCH;
quadricent = Math.floor(depoch / 146097);
dqc = mod(depoch, 146097);
cent = Math.floor(dqc / 36524);
dcent = mod(dqc, 36524);
quad = Math.floor(dcent / 1461);
dquad = mod(dcent, 1461);
yindex = Math.floor(dquad / 365);
year = (quadricent * 400) + (cent * 100) + (quad * 4) + yindex;
if (!((cent == 4) || (yindex == 4))) {
year++;
}
yearday = wjd - convertGregorianToJdn(year, 1, 1);
leapadj = ((wjd < convertGregorianToJdn(year, 3, 1)) ? 0
: (Leap_Gregorian(year) ? 1 : 2));
double month = Math.floor((((yearday + leapadj) * 12) + 373) / 367);
double day = (wjd - convertGregorianToJdn(year, month, 1)) + 1;
String strYear = Integer.toString((int) year), strMonth = Integer
.toString((int) month), strDay = Integer.toString((int) day);
if (strMonth.length() < 2)
strMonth = "0" + strMonth;
if (strDay.length() < 2)
strDay = "0" + strDay;
return strYear + CONSTANT_Delimiter + strMonth + CONSTANT_Delimiter
+ strDay;
}
/**
* @param jdn
* @return
*/
public String convertJdnToJulian(double jdn) {
double z, a, alpha, b, c, d, e, year, month, day, td = 0;
td += 0.5;
z = Math.floor(td);
a = z;
b = a + 1524;
c = Math.floor((b - 122.1) / 365.25);
d = Math.floor(365.25 * c);
e = Math.floor((b - d) / 30.6001);
month = Math.floor((e < 14) ? (e - 1) : (e - 13));
year = Math.floor((month > 2) ? (c - 4716) : (c - 4715));
day = b - d - Math.floor(30.6001 * e);
/*
* If year is less than 1, subtract one to convert from a zero based
* date system to the common era system in which the year -1 (1 B.C.E)
* is followed by year 1 (1 C.E.).
*/
if (year < 1) {
year--;
}
String strYear = Integer.toString((int) year), strMonth = Integer
.toString((int) month), strDay = Integer.toString((int) day);
if (strMonth.length() < 2)
strMonth = "0" + strMonth;
if (strDay.length() < 2)
strDay = "0" + strDay;
return strYear + CONSTANT_Delimiter + strMonth + CONSTANT_Delimiter
+ strDay;
}
public double mod(double args1, double args2) {
return args1 % args2;
}
/**
* @param Date
* input as 1387-04-26 7:59 AM use in solartogregorian method to
* change format to 7/16/08 7:59 AM
* @return gregorian date format as 7/16/08 7:59 AM
*/
public String changeFormat(String Date) {
String[] fixFormat = Date.split(CONSTANT_Delimiter);
String newMonth = fixFormat[1].substring(1);
String newDay = fixFormat[2].substring(0, fixFormat[2].indexOf(" "));
String newYear = fixFormat[0].substring(2);
return newMonth + "/" + newDay + "/" + newYear;
}
}