View source
<?php
define('DATEX_USE_INTL', FALSE);
define('DATEX_GREGORIAN', TRUE);
define('DATEX_JALALI', FALSE);
class DatexFormatter {
protected static $daysInGregorianMonth = array(
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31,
);
protected static $daysInJalaliMonth = array(
31,
31,
31,
31,
31,
31,
30,
30,
30,
30,
30,
29,
);
public static function format($date, $format, $tz = NULL, $use_intl = DATEX_USE_INTL, $intl_args = array()) {
if (self::hasINTL() && $use_intl) {
return self::formatINTL($date, $format, $tz, $intl_args);
}
else {
return self::formatPHP($date, $format, $tz);
}
}
public static function persianDateNames() {
static $names = NULL;
if (!$names) {
$names = array(
'months' => array(
1 => 'فروردین',
2 => 'اردیبهشت',
3 => 'خرداد',
4 => 'تیر',
5 => 'مرداد',
6 => 'شهریور',
7 => 'مهر',
8 => 'آبان',
9 => 'آذر',
10 => 'دی',
11 => 'بهمن',
12 => 'اسفند',
),
'ampm' => array(
'am' => 'ق.ظ',
'pm' => 'ب.ظ',
),
'day_abbr' => array(
6 => 'ش.',
7 => 'ی.',
1 => 'د.',
2 => 'س.',
3 => 'چ.',
4 => 'پ.',
5 => 'ج.',
),
'day' => array(
6 => 'شنبه',
7 => 'یکشنبه',
1 => 'دوشنبه',
2 => 'سهشنبه',
3 => 'چهارشنبه',
4 => 'پنجشنبه',
5 => 'جمعه',
),
'tz' => 'تهران',
);
}
return $names;
}
public static function toJalali($gregorian_year = 0, $gregorian_month = 0, $gregorian_day = 0) {
$now = getdate();
$gregorian_year = ($gregorian_year ? $gregorian_year : $now['year']) - 1600;
$gregorian_month = ($gregorian_month ? $gregorian_month : $now['mon']) - 1;
$gregorian_day = ($gregorian_day ? $gregorian_day : $now['mday']) - 1;
$gregorian_day_no = 365 * $gregorian_year + intval(($gregorian_year + 3) / 4) - intval(($gregorian_year + 99) / 100) + intval(($gregorian_year + 399) / 400);
for ($i = 0; $i < $gregorian_month; ++$i) {
$gregorian_day_no += self::$daysInGregorianMonth[$i];
}
if ($gregorian_month > 1 && ($gregorian_year % 4 == 0 && $gregorian_year % 100 != 0) || $gregorian_year % 400 == 0) {
$gregorian_day_no++;
}
$gregorian_day_no += $gregorian_day;
$jalali_day_no = $gregorian_day_no - 79;
$j_np = intval($jalali_day_no / 12053);
$jalali_day_no = $jalali_day_no % 12053;
$j_year = 979 + 33 * $j_np + 4 * intval($jalali_day_no / 1461);
$jalali_day_no %= 1461;
if ($jalali_day_no >= 366) {
$j_year += intval(($jalali_day_no - 1) / 365);
$jalali_day_no = ($jalali_day_no - 1) % 365;
}
for ($i = 0; $i < 11 && $jalali_day_no >= self::$daysInJalaliMonth[$i]; ++$i) {
$jalali_day_no -= self::$daysInJalaliMonth[$i];
}
$j_month = $i + 1;
$j_day = $jalali_day_no + 1;
return array(
'day' => $j_day,
'month' => $j_month,
'year' => $j_year,
);
}
public static function toGregorian($jalali_year = 0, $jalali_month = 0, $jalali_day = 0) {
$now = self::toJalali();
$jalali_year = ($jalali_year ? $jalali_year : $now['year']) - 979;
$jalali_month = ($jalali_month ? $jalali_month : $now['month']) - 1;
$jalali_day = ($jalali_day ? $jalali_day : $now['day']) - 1;
$jalali_day_no = 365 * $jalali_year + intval($jalali_year / 33) * 8 + intval(($jalali_year % 33 + 3) / 4);
for ($i = 0; $i < $jalali_month; ++$i) {
$jalali_day_no += self::$daysInJalaliMonth[$i];
}
$jalali_day_no += $jalali_day;
$gregorian_day_no = $jalali_day_no + 79;
$g_year = 1600 + 400 * intval($gregorian_day_no / 146097);
$gregorian_day_no = $gregorian_day_no % 146097;
$leap = TRUE;
if ($gregorian_day_no >= 36525) {
$gregorian_day_no--;
$g_year += 100 * intval($gregorian_day_no / 36524);
$gregorian_day_no = $gregorian_day_no % 36524;
if ($gregorian_day_no >= 365) {
$gregorian_day_no++;
}
else {
$leap = FALSE;
}
}
$g_year += 4 * intval($gregorian_day_no / 1461);
$gregorian_day_no %= 1461;
if ($gregorian_day_no >= 366) {
$leap = FALSE;
$gregorian_day_no--;
$g_year += intval($gregorian_day_no / 365);
$gregorian_day_no = $gregorian_day_no % 365;
}
for ($i = 0; $gregorian_day_no >= self::$daysInGregorianMonth[$i] + ($i == 1 && $leap); $i++) {
$gregorian_day_no -= self::$daysInGregorianMonth[$i] + ($i == 1 && $leap);
}
$g_month = $i + 1;
$g_day = $gregorian_day_no + 1;
return array(
'year' => $g_year,
'month' => $g_month,
'day' => $g_day,
);
}
public static function phpToIntl($format) {
static $format_map = NULL;
if (!$format_map) {
$format_map = array(
'd' => 'dd',
'D' => 'EEE',
'j' => 'd',
'l' => 'EEEE',
'N' => 'e',
'S' => 'LLLL',
'w' => '',
'z' => 'D',
'W' => 'w',
'm' => 'MM',
'M' => 'MMM',
'F' => 'MMMM',
'n' => 'M',
't' => '',
'L' => '',
'o' => 'yyyy',
'y' => 'yy',
'Y' => 'YYYY',
'a' => 'a',
'A' => 'a',
'B' => '',
'g' => 'h',
'G' => 'H',
'h' => 'hh',
'H' => 'HH',
'i' => 'mm',
's' => 'ss',
'u' => 'SSSSSS',
'e' => 'z',
'I' => '',
'O' => 'Z',
'P' => 'ZZZZ',
'T' => 'v',
'Z' => '',
'c' => '',
'r' => '',
'U' => '',
' ' => ' ',
'-' => '-',
'.' => '.',
'-' => '-',
':' => ':',
);
}
$replace_pattern = '/[^ \\:\\-\\/\\.\\\\dDjlNSwzWmMFntLoyYaABgGhHisueIOPTZcrU]/';
return strtr(preg_replace($replace_pattern, '', $format), $format_map);
}
public static function formatPHP($date, $format, $tz) {
$persian_date_names = self::persianDateNames();
$date = self::ObjectFromDate($date);
if ($tz) {
$tz = self::getTzObject($tz);
$date
->setTimezone($tz);
}
$gregorian_date = array(
'd' => intval($date
->format('j')),
'm' => intval($date
->format('n')),
'Y' => intval($date
->format('Y')),
);
$jalali_date = self::toJalali($gregorian_date['Y'], $gregorian_date['m'], $gregorian_date['d']);
$z = $jalali_date['month'] <= 6 ? $jalali_date['month'] * 31 + $jalali_date['day'] : 186 + (($jalali_date['month'] - 6) * 30 + $jalali_date['day']);
$format = preg_replace('/[\\\\][a-z]/', '', $format);
$is_leap = self::isLeap($jalali_date['year']) ? 1 : 0;
$replacements = array(
'd' => sprintf('%02d', $jalali_date['day']),
'D' => $persian_date_names['day_abbr'][$date
->format('N')],
'j' => $jalali_date['day'],
'l' => $persian_date_names['day'][$date
->format('N')],
'S' => $persian_date_names['day_abbr'][$date
->format('N')],
'F' => $persian_date_names['months'][$jalali_date['month']],
'm' => sprintf('%02d', $jalali_date['month']),
'n' => $jalali_date['month'],
'L' => str_replace('L', $is_leap, $format),
'Y' => $jalali_date['year'],
'y' => $jalali_date['year'],
'o' => $jalali_date['year'],
'a' => $persian_date_names['ampm'][$date
->format('a')],
'A' => $persian_date_names['ampm'][$date
->format('a')],
'B' => $persian_date_names['ampm'][$date
->format('a')],
'c' => $jalali_date['year'] . '-' . $jalali_date['month'] . '-' . $jalali_date['day'] . 'T' . $date
->format('H:i:sP'),
'g' => $date
->format('g'),
'G' => $date
->format('G'),
'h' => $date
->format('h'),
'H' => $date
->format('H'),
'i' => $date
->format('i'),
's' => $date
->format('s'),
'u' => $date
->format('u'),
'I' => $date
->format('I'),
'O' => $date
->format('O'),
'P' => $date
->format('P'),
'T' => $date
->format('T'),
'Z' => $date
->format('Z'),
'U' => $date
->format('U'),
'w' => $date
->format('w'),
'N' => $date
->format('N'),
'e' => $date
->format('e'),
'z' => $z,
'W' => ceil($z / 7),
't' => self::$daysInJalaliMonth[$jalali_date['month'] - 1],
);
$replacements['r'] = $persian_date_names['day_abbr'][$date
->format('N')] . ', ' . $jalali_date['day'] . ' ' . $persian_date_names['months'][$jalali_date['month']] . ' ' . $jalali_date['year'] . $date
->format('H:i:s P');
if ($is_leap && $jalali_date['month'] == 12) {
$replacements['t'] = 30;
}
else {
$replacements['t'] = self::$daysInJalaliMonth[$jalali_date['month'] - 1];
}
return strtr($format, $replacements);
}
public static function formatINTL($date, $format, $tz, $formatter_args) {
$intl_formatter = new IntlDateFormatter("fa_IR@calendar=persian", IntlDateFormatter::FULL, IntlDateFormatter::FULL, self::getTzString($tz), IntlDateFormatter::TRADITIONAL, self::phpToIntl($format));
$date = $intl_formatter
->format(self::getTimestamp($date));
return isset($formatter_args['decor']) ? $date : self::decor($date, FALSE);
}
public static function ObjectFromDate($date = NULL, $tz = NULL, $gregorian = TRUE) {
if (is_numeric($date)) {
$date = '@' . $date;
}
elseif (is_object($date)) {
$date = '@' . $date
->format('U');
}
elseif (is_array($date)) {
if (!$gregorian) {
$greg_date = self::toGregorian(@$date['year'], @$date['month'], @$date['day']);
$year = $greg_date['year'];
$month = $greg_date['month'];
$day = $greg_date['day'];
}
else {
$year = isset($date['year']) ? intval($date['year']) : intval(date('Y'));
$month = isset($date['month']) ? intval($date['month']) : intval(date('n'));
$day = isset($date['day']) ? intval($date['day']) : intval(date('j'));
}
$hour = isset($date['hour']) ? intval($date['hour']) : intval(date('G'));
$minute = isset($date['minute']) ? intval($date['minute']) : intval(date('i'));
$second = isset($date['second']) ? intval($date['second']) : intval(date('s'));
$date = '@' . mktime($hour, $minute, $second, $month, $day, $year);
}
elseif ($date == NULL) {
$date = 'now';
}
return isset($tz) ? new DateTime($date, $tz) : new DateTime($date);
}
public static function getTimestamp($date) {
$date = self::ObjectFromDate($date);
return intval($date
->format('U'));
}
public static function hasINTL() {
return class_exists('IntlDateFormatter');
}
public static function isLeap($year_value) {
return array_search(($year_value + 2346) % 2820 % 128, array(
5,
9,
13,
17,
21,
25,
29,
34,
38,
42,
46,
50,
54,
58,
62,
67,
71,
75,
79,
83,
87,
91,
95,
100,
104,
108,
112,
116,
120,
124,
0,
));
}
public static function getTzObject($tz = NULL) {
if ($tz) {
if (is_string($tz)) {
$tz = new DateTimeZone($tz);
}
elseif (!$tz instanceof DateTimeZone) {
$tz = new DateTimeZone(date_default_timezone_get());
}
}
return $tz;
}
public static function getTzString($tz) {
$tz = self::getTzObject($tz);
return method_exists($tz, 'getName') ? $tz
->getName() : NULL;
}
public static function decor($value, $decorate = FALSE) {
static $to_en = array(
'۱' => 1,
'۲' => 2,
'۳' => 3,
'۴' => 4,
'۵' => 5,
'۶' => 6,
'۷' => 7,
'۸' => 8,
'۹' => 9,
'۰' => 0,
);
static $to_fa = array(
1 => '۱',
2 => '۲',
3 => '۳',
4 => '۴',
5 => '۵',
6 => '۶',
7 => '۷',
8 => '۸',
9 => '۹',
0 => '۰',
);
return strtr($value, $decorate ? $to_fa : $to_en);
}
public static function parser($date, $format) {
if (!(is_string($date) && is_string($format))) {
throw new Exception('Datex parser: date or format not valid.');
}
$granularities = array();
$j = $i = 0;
$format_len = strlen($format);
do {
while (!ctype_alpha($format[$i]) && $i < $format_len) {
$i++;
}
while (!ctype_digit($date[$j])) {
$j++;
}
switch ($format[$i]) {
case 'd':
$granularities['day'] = $date[$j] . $date[++$j];
break;
case 'j':
if (ctype_digit($date[$j + 1])) {
$granularities['day'] = $date[$j] . $date[++$j];
}
else {
$granularities['day'] = $date[$j];
}
break;
case 'm':
$granularities['month'] = $date[$j] . $date[++$j];
break;
case 'n':
if (ctype_digit($date[$j + 1])) {
$granularities['month'] = $date[$j] . $date[++$j];
}
else {
$granularities['month'] = $date[$j];
}
break;
case 'y':
case 'Y':
$granularities['year'] = $date[$j] . $date[++$j] . $date[++$j] . $date[++$j];
case 'h':
$granularities['hour'] = $date[$j] . $date[++$j];
break;
case 'g':
if (ctype_digit($date[$j + 1])) {
$granularities['hour'] = $date[$j] . $date[++$j];
}
else {
$granularities['hour'] = $date[$j];
}
break;
case 'H':
$granularities['hour'] = $date[$j] . $date[++$j];
break;
case 'G':
if (ctype_digit($date[$j + 1])) {
$granularities['hour'] = $date[$j] . $date[++$j];
}
else {
$granularities['hour'] = $date[$j];
}
break;
case 'i':
$granularities['minute'] = $date[$j] . $date[++$j];
break;
case 's':
$granularities['second'] = $date[$j] . $date[++$j];
break;
}
$j++;
} while (++$i < $format_len);
return $granularities;
}
}
class DatexObject {
protected $dateobj;
public $error;
public $errorMessage;
public $hasError;
public $tz;
protected $formatString;
public function __construct($datetime = NULL, $is_gregorian = DATEX_GREGORIAN, $tz = NULL, $format = NULL) {
$this->hasError = FALSE;
$this->error = '';
$this->errorMessage = '';
$this
->setDatetime($datetime, $is_gregorian, $tz);
$format = $format ? $format : 'Y-m-d';
$this
->setFormat($format);
$tz = DatexFormatter::getTzObject($tz);
if ($tz instanceof DateTimeZone) {
$this->dateobj
->setTimezone($tz);
}
return $this;
}
public function __toString() {
return $this
->format();
}
public function __clone() {
$this->dateobj = clone $this->dateobj;
}
public function reset() {
$this->dateobj = new DateTime(NULL, $this->dateobj
->getTimezone());
return $this;
}
public function format($format = NULL, $use_intl = DATEX_USE_INTL) {
$format = $format ? $format : $this->formatString;
$tz = $this->dateobj
->getTimezone();
return DatexFormatter::format($this->dateobj, $format, $tz, $use_intl);
}
public function getDateobjClone() {
return clone $this->dateobj;
}
public function setDatetime($datetime = NULL, $gregorian = DATEX_GREGORIAN, $tz = NULL) {
$tz = DatexFormatter::getTzObject($tz);
$this->dateobj = DatexFormatter::ObjectFromDate($datetime, $tz, $gregorian);
return $this;
}
public function setDate($year = NULL, $month = NULL, $day = NULL, $tz = NULL) {
if (!$year) {
$year = $this
->format('Y');
}
if (!$mont) {
$month = $this
->format('n');
}
if (!$day) {
$day = $this
->format('j');
}
$date = DatexFormatter::toGregorian($year, $month, $day);
$this
->xsetDate($date['year'], $date['month'], $date['day']);
if ($tz = DatexFormatter::getTzObject($tz)) {
$this
->setTimezone($tz);
}
return $this;
}
public function setFormat($format) {
$this->formatString = $format;
return $this;
}
public function getFormat() {
return $this->formatString;
}
public function getTimezone() {
return $this->dateobj
->getTimezone();
}
public function setTimezone($timezone) {
$timezone = DatexFormatter::getTzObject($timezone);
$this->dateobj
->setTimezone($timezone);
return $this;
}
public function setTimestamp($timestamp) {
$this->dateobj
->setTimestamp($timestamp);
return $this;
}
public function setTime($hour, $minute, $second = 0) {
$this->dateobj
->setTime($hour, $minute, $second);
return $this;
}
public function getOffset() {
return $this->dateobj
->getOffset();
}
public function xdiff(DateTime $datetime2, $absolute = FALSE) {
return $this->dateobj
->diff($datetime2, $absolute);
}
public function xformat($format) {
return $this->dateobj
->format($format);
}
public function xgetLastErrors() {
return $this
->getLastErrors();
}
public function xsetDate($year, $month, $day) {
return $this->dateobj
->setDate($year, $month, $day);
}
public function getTimestamp() {
return $this->dateobj
->format('U');
}
public function modify($modify) {
$this->dateobj
->modify($modify);
return $this;
}
public function monthFirstDay() {
$date = clone $this;
$date
->setDate(NULL, NULL, 1);
return $date;
}
public function monthLastDay() {
$date = clone $this;
$date
->setDate(NULL, NULL, DatexFormatter::format($date, 't'));
return $date;
}
public function toArray() {
return array(
'year' => $this
->format('Y'),
'month' => $this
->format('n'),
'day' => $this
->format('j'),
'hour' => $this
->format('H'),
'minute' => $this
->format('i'),
'second' => $this
->format('s'),
'timezone' => $this
->format('e'),
);
}
public function difference(DatexObject $date2_in, $measure = 'seconds', $absolute = TRUE) {
$date1 = $this
->getDateobjClone();
$date2 = $date2_in
->getDateobjClone();
$diff = date_format($date2, 'U') - date_format($date1, 'U');
if ($diff == 0) {
return 0;
}
elseif ($diff < 0 && $absolute) {
$temp = $date2;
$date2 = $date1;
$date1 = $temp;
$diff = date_format($date2, 'U') - date_format($date1, 'U');
}
$year_diff = intval(date_format($date2, 'Y') - date_format($date1, 'Y'));
switch ($measure) {
case 'seconds':
return $diff;
case 'minutes':
return $diff / 60;
case 'hours':
return $diff / 3600;
case 'years':
return $year_diff;
case 'months':
$format = 'n';
$item1 = $this
->format_php($format, $date1);
$item2 = $this
->format_php($format, $date2);
if ($year_diff == 0) {
return intval($item2 - $item1);
}
else {
$item_diff = 12 - $item1;
$item_diff += intval(($year_diff - 1) * 12);
return $item_diff + $item2;
}
break;
case 'days':
$format = 'z';
$item1 = $this
->format_php($format, $date1);
$item2 = $this
->format_php($format, $date2);
if ($year_diff == 0) {
return intval($item2 - $item1);
}
else {
$item_diff = date_days_in_year($date1) - $item1;
for ($i = 1; $i < $year_diff; $i++) {
date_modify($date1, '+1 year');
$item_diff += date_days_in_year($date1);
}
return $item_diff + $item2;
}
break;
case 'weeks':
default:
break;
}
return NULL;
}
public function xtoArray() {
return array(
'year' => $this->dateobj
->format('Y'),
'month' => $this->dateobj
->format('n'),
'day' => $this->dateobj
->format('j'),
'hour' => intval($this->dateobj
->format('H')),
'minute' => intval($this->dateobj
->format('i')),
'second' => intval($this->dateobj
->format('s')),
'timezone' => $this->dateobj
->format('e'),
);
}
}
class DatexObjectUtils {
public static function monthFirstDay($date = NULL) {
$date = new DatexObject($date, FALSE);
return $date
->monthFirstDay();
}
public static function monthLastDay($date = NULL) {
$date = new DatexObject($date, FALSE);
return $date
->monthLastDay();
}
public static function toArray($date = NULL) {
if (!is_a($date, 'DatexObject')) {
$date = new DatexObject($date, FALSE);
}
return $date
->toArray();
}
public static function getJalaliObject($date = NULL) {
return new DatexObject($date, FALSE);
}
public static function getYear() {
return self::getByName('year');
}
public static function getMonth() {
return self::getByName('month');
}
public static function getDay() {
return self::getByName('day');
}
public static function getByName($name) {
$date = DatexFormatter::toJalali();
return $date[$name];
}
public static function date($format, $timestamp = NULL) {
return DatexFormatter::format($timestamp === NULL ? time() : $timestamp, $format);
}
public static function mktime($hour = NULL, $minute = NULL, $second = NULL, $month = NULL, $day = NULL, $year = NULL) {
$date = DatexFormatter::toGregorian($year, $month, $day);
$year = $year === NULL ? NULL : $date['year'];
$month = $month === NULL ? NULL : $date['month'];
$day = $day === NULL ? NULL : $date['day'];
return mktime($hour, $minute, $second, $month, $day, $year);
}
public static function getdate($timestamp = NULL) {
if ($timestamp === NULL) {
$timestamp = time();
}
$date = new DateTime($timestamp);
$ret['seconds'] = intval($date
->format('s'));
$ret['minutes'] = intval($date
->format('i'));
$ret['hours'] = intval($date
->format('G'));
$jalali = DatexFormatter::toJalali();
$ret['mday'] = intval($jalali['day']);
$ret['mon'] = intval($jalali['month']);
$ret['year'] = intval($jalali['year']);
$ret['wday'] = DatexFormatter::formatPHP($date, 'w');
$ret['yday'] = DatexFormatter::formatPHP($date, 'z');
$ret['weekday'] = DatexFormatter::formatPHP($date, 'l');
$ret['month'] = DatexFormatter::formatPHP($date, 'F');
$ret[0] = $timestamp;
return $ret;
}
}