<?php
/*
   JDF: Jalali Date Functions
   Version: 2.70
   Author: Milad Rastian [mr.rashtian@yahoo.com]
   Web-site: http://jdf.scr.ir
*/

function jdate($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa')
{

    $T_sec = 0;/* <= رفع خطای زمان سرور ، با اعداد '+' و '-' بر حسب ثانیه میتوانید زمان سرور را تنظیم کنید */

    if ($time_zone != 'local') date_default_timezone_set(($time_zone === '') ? 'Asia/Tehran' : $time_zone);
    $ts = $T_sec + (($timestamp === '' || $timestamp == 'now') ? time() : tr_num($timestamp));
    $date = explode('_', date('H_i_j_n_O_P_s_w_Y', $ts));
    list($j_y, $j_m, $j_d) = gregorian_to_jalali($date[8], $date[3], $date[2]);
    $doy = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d : (($j_m - 7) * 30) + $j_d + 186;
    $kab = (((($date[8] - 1996) % 4) == 0) and !(($date[8] % 100) == 0 and ($date[8] % 400) != 0));
    $leap = (((($j_y + 12) % 33) % 4) == 1);
    $ty = $leap ? 366 : 365;
    $jw = $doy % 7;
    $p_j_y = $j_y - 1;
    $p_leap = (((($p_j_y + 12) % 33) % 4) == 1);
    $p_ty = $p_leap ? 366 : 365;

    $j_month = array("فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند");
    $j_weeks = array("شنبه", "یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنجشنبه", "جمعه");
    $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
    if ($leap) $j_days_in_month[11] = 30;

    $format = preg_replace_callback('/(?<!\\\\)F|(?<!\\\\)j|(?<!\\\\)l|(?<!\\\\)M|(?<!\\\\)n|(?<!\\\\)S|(?<!\\\\)w|(?<!\\\\)z|(?<!\\\\)W|(?<!\\\\)t|(?<!\\\\)L|(?<!\\\\)o|(?<!\\\\)Y|(?<!\\\\)y|(?<!\\\\)a|(?<!\\\\)A|(?<!\\\\)g|(?<!\\\\)G|(?<!\\\\)h|(?<!\\\\)H|(?<!\\\\)i|(?<!\\\\)s|(?<!\\\\)u|(?<!\\\\)I|(?<!\\\\)O|(?<!\\\\)P|(?<!\\\\)Z|(?<!\\\\)T|(?<!\\\\)B|(?<!\\\\)v|\\[[^\]]+\\]/', function ($matches) use ($date, $j_y, $j_m, $j_d, $doy, $kab, $leap, $ty, $jw, $p_j_y, $p_leap, $p_ty, $j_month, $j_weeks, $j_days_in_month) {
        $match = $matches[0];
        if ($match[0] == '[') return substr($match, 1, -1);
        switch ($match) {
            case 'F':
                return $j_month[$j_m - 1];
            case 'j':
                return $j_d;
            case 'l':
                return $j_weeks[$jw];
            case 'M':
                return substr($j_month[$j_m - 1], 0, 6);
            case 'n':
                return $j_m;
            case 'S':
                return 'م';
            case 'w':
                return $jw;
            case 'z':
                return $doy;
            case 'W':
                return is_int($doy / 7) ? ($doy / 7) : intval($doy / 7 + 1);
            case 't':
                return $j_days_in_month[$j_m - 1];
            case 'L':
                return $leap;
            case 'o':
            case 'Y':
                return $j_y;
            case 'y':
                return substr($j_y, 2, 2);
            case 'a':
                return ($date[0] < 12) ? 'ق.ظ' : 'ب.ظ';
            case 'A':
                return ($date[0] < 12) ? 'قبل از ظهر' : 'بعد از ظهر';
            case 'g':
                return ($date[0] % 12) ? $date[0] % 12 : 12;
            case 'G':
                return $date[0];
            case 'h':
                return sprintf('%02d', ($date[0] % 12) ? $date[0] % 12 : 12);
            case 'H':
                return sprintf('%02d', $date[0]);
            case 'i':
                return sprintf('%02d', $date[1]);
            case 's':
                return sprintf('%02d', $date[6]);
            case 'u':
                return 0;
            case 'I':
                return $kab;
            case 'O':
                return $date[4];
            case 'P':
                return $date[5];
            case 'Z':
                return $date[7];
            case 'T':
                return 'IRDT';
            case 'B':
                return (int)(1 + ($ts + 12600) / 86.4) % 1000;
            case 'v':
                return $p_ty;
        }
    }, $format);
    if ($tr_num != 'en') {
        $format = str_replace(array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'), $format);
    }
    if ($none != '') {
        $format = str_replace(array('ي', 'ك'), array('ی', 'ک'), $format);
    }
    return $format;
}

function jstrftime($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa')
{

    $T_sec = 0;/* <= رفع خطای زمان سرور ، با اعداد '+' و '-' بر حسب ثانیه میتوانید زمان سرور را تنظیم کنید */

    if ($time_zone != 'local') date_default_timezone_set(($time_zone === '') ? 'Asia/Tehran' : $time_zone);
    $ts = $T_sec + (($timestamp === '' || $timestamp == 'now') ? time() : tr_num($timestamp));
    $date = explode('_', date('H_i_j_n_O_P_s_w_Y', $ts));
    list($j_y, $j_m, $j_d) = gregorian_to_jalali($date[8], $date[3], $date[2]);
    $doy = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d : (($j_m - 7) * 30) + $j_d + 186;
    $kab = (((($date[8] - 1996) % 4) == 0) and !(($date[8] % 100) == 0 and ($date[8] % 400) != 0));
    $leap = (((($j_y + 12) % 33) % 4) == 1);
    $ty = $leap ? 366 : 365;
    $jw = $doy % 7;
    $p_j_y = $j_y - 1;
    $p_leap = (((($p_j_y + 12) % 33) % 4) == 1);
    $p_ty = $p_leap ? 366 : 365;

    $j_month = array("فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند");
    $j_weeks = array("شنبه", "یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنجشنبه", "جمعه");
    $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
    if ($leap) $j_days_in_month[11] = 30;

    $format = preg_replace_callback('/(?<!\\\\)%(a|A|b|B|c|C|d|D|e|F|g|G|h|H|I|j|l|m|M|n|O|p|P|r|R|s|S|t|T|u|U|V|w|W|x|X|y|Y|Z)|\\[[^\]]+\\]/', function ($matches) use ($date, $j_y, $j_m, $j_d, $doy, $kab, $leap, $ty, $jw, $p_j_y, $p_leap, $p_ty, $j_month, $j_weeks, $j_days_in_month, $ts) {
        $match = $matches[0];
        if ($match[0] == '[') return substr($match, 1, -1);
        switch ($match) {
            case '%a':
                return substr($j_weeks[$jw], 0, 2);
            case '%A':
                return $j_weeks[$jw];
            case '%b':
                return substr($j_month[$j_m - 1], 0, 6);
            case '%B':
                return $j_month[$j_m - 1];
            case '%c':
                return jdate('D M j H:i:s Y', $ts);
            case '%C':
                return intval($j_y / 100);
            case '%d':
                return sprintf('%02d', $j_d);
            case '%D':
                return jdate('m/d/y', $ts);
            case '%e':
                return sprintf('%2d', $j_d);
            case '%F':
                return jdate('Y-m-d', $ts);
            case '%g':
                return substr($j_y, 2, 2);
            case '%G':
                return $j_y;
            case '%h':
                return substr($j_month[$j_m - 1], 0, 6);
            case '%H':
                return sprintf('%02d', $date[0]);
            case '%I':
                return sprintf('%02d', ($date[0] % 12) ? $date[0] % 12 : 12);
            case '%j':
                return str_pad($doy, 3, 0, STR_PAD_LEFT);
            case '%l':
                return sprintf('%2d', ($date[0] % 12) ? $date[0] % 12 : 12);
            case '%m':
                return sprintf('%02d', $j_m);
            case '%M':
                return sprintf('%02d', $date[1]);
            case '%n':
                return "\n";
            case '%O':
                return $date[4];
            case '%p':
                return ($date[0] < 12) ? 'AM' : 'PM';
            case '%P':
                return ($date[0] < 12) ? 'am' : 'pm';
            case '%r':
                return jdate('I:M:S p', $ts);
            case '%R':
                return jdate('H:M', $ts);
            case '%s':
                return $ts;
            case '%S':
                return sprintf('%02d', $date[6]);
            case '%t':
                return "\t";
            case '%T':
                return jdate('H:i:s', $ts);
            case '%u':
                return $jw + 1;
            case '%U':
                return $doy == 0 ? 0 : intval(($doy - 1) / 7 + 1);
            case '%V':
                return is_int($doy / 7) ? ($doy / 7) : intval($doy / 7 + 1);
            case '%w':
                return $jw;
            case '%W':
                return ($doy > 0 and $jw == 0) ? intval(($doy - 1) / 7 + 1) : intval($doy / 7);
            case '%x':
                return jdate('m/d/y', $ts);
            case '%X':
                return jdate('H:i:s', $ts);
            case '%y':
                return substr($j_y, 2, 2);
            case '%Y':
                return $j_y;
            case '%Z':
                return 'IRDT';
        }
    }, $format);
    if ($tr_num != 'en') {
        $format = str_replace(array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'), $format);
    }
    if ($none != '') {
        $format = str_replace(array('ي', 'ك'), array('ی', 'ک'), $format);
    }
    return $format;
}

function jmktime($h = '', $m = '', $s = '', $jm = '', $jd = '', $jy = '', $none = '', $timezone = 'Asia/Tehran')
{
    if ($timezone != 'local') date_default_timezone_set($timezone);
    if ($h === '') {
        return time();
    } else {
        list($h, $m, $s, $jm, $jd, $jy) = explode('_', tr_num($h . '_' . $m . '_' . $s . '_' . $jm . '_' . $jd . '_' . $jy));
        if ($m === '') {
            return mktime($h);
        } else {
            if ($s === '') {
                return mktime($h, $m);
            } else {
                if ($jm === '') {
                    return mktime($h, $m, $s);
                } else {
                    $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
                    if (((((($jy + 12) % 33) % 4) - 1) == 0) and !((($jy % 100) == 0) and (($jy % 400) != 0))) $j_days_in_month[11] = 30;
                    if ($jd > $j_days_in_month[--$jm]) {
                        $jd -= $j_days_in_month[$jm];
                        $jm++;
                    }
                    if ($jm > 12) {
                        $jm -= 12;
                        $jy++;
                    }
                    list($gy, $gm, $gd) = jalali_to_gregorian($jy, $jm, $jd);
                    return mktime($h, $m, $s, $gm, $gd, $gy);
                }
            }
        }
    }
}

function jgetdate($timestamp = '', $none = '', $timezone = 'Asia/Tehran', $tn = 'en')
{
    $ts = ($timestamp === '') ? time() : tr_num($timestamp);
    $jdate = explode('_', jdate('F_j_l_M_n_S_w_z_W_t_L_o_Y_y_-A_g_G_h_H_i_s_I_O_P_Z_T_B_v', $ts, '', $timezone, $tn));
    return array(
        'seconds' => tr_num((int)tr_num($jdate[19])),
        'minutes' => tr_num((int)tr_num($jdate[18])),
        'hours' => tr_num($jdate[17]),
        'mday' => tr_num($jdate[1]),
        'wday' => tr_num($jdate[6]),
        'mon' => tr_num($jdate[4]),
        'year' => tr_num($jdate[13]),
        'yday' => tr_num($jdate[7]),
        'weekday' => $jdate[2],
        'month' => $jdate[0],
        0 => tr_num($ts),
        'seconds_en' => $jdate[19],
        'minutes_en' => $jdate[18],
        'hours_en' => $jdate[17],
        'mday_en' => $jdate[1],
        'wday_en' => $jdate[6],
        'mon_en' => $jdate[4],
        'year_en' => $jdate[13],
        'yday_en' => $jdate[7],
        'weekday_en' => $jdate[2],
        'month_en' => $jdate[0],
    );
}

function jcheckdate($jm, $jd, $jy)
{
    list($jm, $jd, $jy) = explode('_', tr_num($jm . '_' . $jd . '_' . $jy));
    $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
    if (((((($jy + 12) % 33) % 4) - 1) == 0) and !((($jy % 100) == 0) and (($jy % 400) != 0))) $j_days_in_month[11] = 30;
    return ($jm > 0 and $jd > 0 and $jy > 0 and $jm < 13 and $jd <= $j_days_in_month[--$jm]);
}

function tr_num($str, $mod = 'en', $mf = '٫')
{
    $num_a = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.');
    $num_b = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', $mf);
    return ($mod == 'fa') ? str_replace($num_a, $num_b, $str) : str_replace($num_b, $num_a, $str);
}

function gregorian_to_jalali($gy, $gm, $gd, $mod = '')
{
    list($gy, $gm, $gd) = explode('_', tr_num($gy . '_' . $gm . '_' . $gd));/* <= Extra :اين سطر ، جزء تابع اصلي نيست */
    $g_d_m = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
    $gy2 = ($gm > 2) ? ($gy + 1) : $gy;
    $days = 355666 + (365 * $gy) + intval(($gy2 + 3) / 4) - intval(($gy2 + 99) / 100) + intval(($gy2 + 399) / 400) + $gd + $g_d_m[$gm - 1];
    $jy = -1595 + (33 * intval($days / 12053));
    $days %= 12053;
    $jy += 4 * intval($days / 1461);
    $days %= 1461;
    if ($days > 365) {
        $jy += intval(($days - 1) / 365);
        $days = ($days - 1) % 365;
    }
    if ($days < 186) {
        $jm = 1 + intval($days / 31);
        $jd = 1 + ($days % 31);
    } else {
        $jm = 7 + intval(($days - 186) / 30);
        $jd = 1 + (($days - 186) % 30);
    }
    return ($mod == '') ? array($jy, $jm, $jd) : $jy . $mod . $jm . $mod . $jd;
}

function jalali_to_gregorian($jy, $jm, $jd, $mod = '')
{
    list($jy, $jm, $jd) = explode('_', tr_num($jy . '_' . $jm . '_' . $jd));/* <= Extra :اين سطر ، جزء تابع اصلي نيست */
    $jy += 1595;
    $days = -355668 + (365 * $jy) + (intval($jy / 33) * 8) + intval((($jy % 33) + 3) / 4) + $jd + (($jm < 7) ? ($jm - 1) * 31 : (($jm - 7) * 30) + 186);
    $gy = 400 * intval($days / 146097);
    $days %= 146097;
    if ($days > 36524) {
        $gy += 100 * intval(--$days / 36524);
        $days %= 36524;
        if ($days >= 365) $days++;
    }
    $gy += 4 * intval($days / 1461);
    $days %= 1461;
    if ($days > 365) {
        $gy += intval(($days - 1) / 365);
        $days = ($days - 1) % 365;
    }
    $gd = $days + 1;
    $sal_a = array(0, 31, (($gy % 4 == 0 and $gy % 100 != 0) or ($gy % 400 == 0)) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    for ($gm = 0; $gm < 13 and $gd > $sal_a[$gm]; $gm++) $gd -= $sal_a[$gm];
    return ($mod == '') ? array($gy, $gm, $gd) : $gy . $mod . $gm . $mod . $gd;
}

?>