Answer the question
In order to leave comments, you need to log in
How to write a converter from Gregorian to Iranian calendars and vice versa?
The problem is that the more I read about the Iranian calendar, the more questions appear)))
Maybe someone has already dealt with this problem? I will be glad if you help with the algorithms.
And then there are too many different conditions, in connection with which the number of days changes.
Or, in the most extreme case, can it somehow be converted through the database with queries?))
Answer the question
In order to leave comments, you need to log in
found somewhere on the eastern sites a piece on JS. I rewrote it in PHP, the people of Iran appreciated it and said that it works correctly ;-)
class IranCalendarParser
{
const GREGORIAN_EPOCH = 1721425.5;
const PERSIAN_EPOCH = 1948320.5;
const ISLAMIC_EPOCH = 1948439.5;
static public $MONTH_NAME = array(
1 => 'Farvardin',
2 => 'Ordibehesht',
3 => 'Khordad',
4 => 'Tir',
5 => 'Mordad',
6 => 'Shahrivar',
7 => 'Mehr',
8 => 'Aban',
9 => 'Azar',
10 => 'Dey',
11 => 'Bahman',
12 => 'Esfand',
);
static function GregorianToIran($year, $month, $day)
{
return self::jd_to_persian(self::gregorian_to_jd($year, $month, $day));
}
static function IranToGregorian($year, $month, $day)
{
return self::jd_to_gregorian(self::persian_to_jd($year, $month, $day));
}
static public function GetMonthName($month)
{
return self::$MONTH_NAME[$month];
}
public function jd_to_gregorian($jd)
{
// self::GREGORIAN_EPOCH = 1721425.5;
$wjd = floor($jd - 0.5) + 0.5;
$depoch = $wjd - self::GREGORIAN_EPOCH;
$quadricent = floor($depoch / 146097);
$dqc = self::mod($depoch, 146097);
$cent = floor($dqc / 36524);
$dcent = self::mod($dqc, 36524);
$quad = floor($dcent / 1461);
$dquad = self::mod($dcent, 1461);
$yindex = floor($dquad / 365);
$year = ($quadricent * 400) + ($cent * 100) + ($quad * 4) + $yindex;
if (!(($cent == 4) || ($yindex == 4))) {
$year++;
}
$yearday = $wjd - self::gregorian_to_jd($year, 1, 1);
$leapadj = (($wjd < self::gregorian_to_jd($year, 3, 1)) ? 0
:
(self::leap_gregorian($year) ? 1 : 2)
);
$month = floor(((($yearday + $leapadj) * 12) + 373) / 367);
$day = ($wjd - self::gregorian_to_jd($year, $month, 1)) + 1;
return array( 'day'=>$day,'month'=>$month,'year'=>$year );
}
public function mod($a, $b)
{
return $a - ($b * floor($a / $b));
}
public function gregorian_to_jd($year, $month, $day)
{
return (self::GREGORIAN_EPOCH - 1) +
(365 * ($year - 1)) +
floor(($year - 1) / 4) +
(-floor(($year - 1) / 100)) +
floor(($year - 1) / 400)+
floor((((367 * $month) - 362) / 12) +
(($month <= 2) ? 0 :
(self::leap_gregorian($year) ? -1 : -2)
) +
$day)
;
}
public function leap_gregorian($year)
{
return (($year % 4) == 0) &&
(!((($year % 100) == 0) && (($year % 400) != 0)));
}
public function persian_to_jd($year, $month, $day)
{
$epbase = $year - (($year >= 0) ? 474 : 473);
$epyear = 474 + self::mod($epbase, 2820);
return $day +
(($month <= 7) ?
(($month - 1) * 31) :
((($month - 1) * 30) + 6)
) +
floor((($epyear * 682) - 110) / 2816) +
($epyear - 1) * 365 +
floor($epbase / 2820) * 1029983 +
(self::PERSIAN_EPOCH - 1);
}
public function jd_to_persian($jd)
{
$jd = floor($jd) + 0.5;
$depoch = $jd - self::persian_to_jd(475, 1, 1);
$cycle = floor($depoch / 1029983);
$cyear = self::mod($depoch, 1029983);
if ($cyear == 1029982) {
$ycycle = 2820;
} else {
$aux1 = floor($cyear / 366);
$aux2 = self::mod($cyear, 366);
$ycycle = floor(((2134 * $aux1) + (2816 * $aux2) + 2815) / 1028522) +
$aux1 + 1;
}
$year = $ycycle + (2820 * $cycle) + 474;
if ($year <= 0) {
$year--;
}
$yday = ($jd - self::persian_to_jd($year, 1, 1)) + 1;
$month = ($yday <= 186) ? ceil($yday / 31) : ceil(($yday - 6) / 30);
$day = ($jd - self::persian_to_jd($year, $month, 1)) + 1;
return array( 'day'=>$day,'month'=>$month,'year'=>$year );
}
public function jd_to_islamic($jd)
{
$jd = floor($jd) + 0.5;
$year = floor(((30 * ($jd - self::ISLAMIC_EPOCH)) + 10646) / 10631);
$month = min(12,
ceil(($jd - (29 + self::islamic_to_jd($year, 1, 1))) / 29.5) + 1);
$day = ($jd - self::islamic_to_jd($year, $month, 1)) + 1;
return array( 'day'=>$day,'month'=>$month,'year'=>$year );
}
public function islamic_to_jd($year, $month, $day)
{
return ($day +
ceil(29.5 * ($month - 1)) +
($year - 1) * 354 +
floor((3 + (11 * $year)) / 30) +
self::ISLAMIC_EPOCH) - 1;
}
public function leap_islamic($year)
{
return ((($year * 11) + 14) % 30) < 11;
}
}
/**
* Example
*/
IranCalendarParser::GregorianToIran(2017,2,10);
IranCalendarParser::IranToGregorian(1395,11,22);
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question