нашел где-то на восточных сайтах кусок на JS. Переписал на PHP, жители Ирана оценили и сказали что работает правильно ;-)
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);