Date.php in PersianTools 7
Namespace
ShamsiFile
includes/Date.phpView source
<?php
/**
* Date
* Exact scientific approach to create Jalali calendar
* with an interface similar to php date()
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
* @package Calendar
* @author Keyhan Sedaghat <keyhansedaghat@netscape.net>
* @author Amin Saeedi <amin.w3dev@gmail.com>
* @copyright 1371-1390 (1991-2011)
* @version 4.0
*/
namespace Shamsi;
class Date {
/**
* Length of a year
* Calculated by Khayam is 365.2422 days (approx.);
* but as the years are getting shorter the new value
* (valid from year 1380 Per./2000 A.D.) is used instead.
*/
const KHAYAM_YEAR = 365.24218956;
/**
* Recent calculations has introduced a correcting factor,
* which Khayam could not reach.
* This is used to better adjust length of each year in seconds.
*/
const KHAYAM_YEAR_CORRECTION = 6.152E-8;
/**
* Corresponding to the real date-time.
* Timestamp in format of and equivalent to standard unix time.
*
*
* @access private
* @var int
*/
private $_timestamp = 0;
/**
* Reference table made by Khayam for leap years
*
* @access private
* @var array
*/
private $_khayamii = 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,
);
/**
* Count of days at the end of each Persian month
*
* @access private
* @var array
*/
private $_mountCounter = array(
0,
31,
62,
93,
124,
155,
186,
216,
246,
276,
306,
336,
);
/**
* value of second in output time
*
* @access private
* @var int
*/
private $_second = 0;
/**
* value of minute in output time
*
* @access private
* @var int
*/
private $_minute = 0;
/**
* value of hour in output time
*
* @access private
* @var int
*/
private $_hour = 0;
/**
* value of day in output time
*
* @access private
* @var int
*/
private $_day = 0;
/**
* value of month in output time
*
* @access private
* @var int
*/
private $_month = 0;
/**
* value of year in output time
*
* @access private
* @var int
*/
private $_year = 0;
/**
* number of days from start of the current year
*
* @access private
* @var int
*/
private $_dayOfYear = 0;
/**
* standard php timeZone identifier e.g.:('Asia/Tehran')
* ::date('e')
*
* @access private
* @var string
*/
private $_timeZone = '';
/**
* standard php timeZone abbreviation e.g.:('IRST')
* ::date('T')
*
* @access private
* @var string
*/
private $_timeZoneAbb = '';
/**
* daylight saving
* ::date('I')
*
* @access private
* @var int (0|1)
*/
private $_DLS = 0;
/**
* difference from GMT in hours
* ::date('O')
*
* @access private
* @var int
*/
private $_GMTDiff = 0;
/**
* difference from GMT in hours including colon
* ::date('P')
*
* @access private
* @var string
*/
private $_GMTDiffC = "";
/**
* defference from GMT in seconds
* ::date('Z')
*
* @access private
* @var int
*/
private $_timezoneOffset = 0;
/**
* returns the week of the year
*
* @param integer $year --Optional timestamp
* @param integer $month --Optional
* @param integer $day --Optional
* @param integer $hour --Optional
* @param integer $minute --Optional
* @param integer $second --Optional
*
* single parameter is supposed to be a valid timestamp multiple
* --6-- parameters are supposed to be year, month, day, hour,
* minute, second values.
*/
public function __construct() {
if (func_num_args() == 1) {
$this->_timestamp = func_get_arg(0);
}
else {
if (func_num_args() == 6) {
$this->_timestamp = $this
->mktime(func_get_arg(0), func_get_arg(1), func_get_arg(2), func_get_arg(3), func_get_arg(4), func_get_arg(5));
}
else {
$this->_timestamp = \time();
}
}
$this
->_date();
}
/**
* converts digits to Persian traditional font face and
* corrects the no-width space in words
* use the function on the returned value in the source code
*
* @access private
* @param string $phrase
* @return string
*/
public function ParsiNumbers($phrase) {
$L = array(
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
);
$F = array(
"۰",
"۱",
"۲",
"۳",
"۴",
"۵",
"۶",
"۷",
"۸",
"۹",
);
return str_replace($L, $F, $phrase);
}
/**
* get value of the day in the year
*
* @access private
* @return int
*/
private function dayOfYear() {
return $this->{$dayOfYear};
}
/**
* returns the week of the year
* @access private
* @return int
*/
private function weekOfYear() {
$x = (7 - $this
->dayOfWeek($this->_year, 1)) % 7;
$z = $this->_dayOfYear - $x;
return abs(ceil($z / 7));
}
/**
* calculates the years from reference Observation year
*
* @param int $yearValue
* @param boolean $calendarType
* @access private
* @return int
*/
private function calcRasad($yearValue) {
$Rasad = $yearValue + 2346;
return $Rasad;
}
/**
* Checks the specified year for a leap year
* The return value is the number of the leap year (1 - 31)in one cycle
* for leap years and false for normal years
*
* @param int $yearValue
* @access private
* @return mixed
*/
private function isLeap($yearValue) {
$Rasad = $this
->calcRasad($yearValue);
$yrNam = $Rasad % 2820;
$yrNam = $yrNam % 128;
$leapCount = array_search($yrNam, $this->_khayamii);
return $leapCount;
}
/**
* returns weekday of the specified day of the year
*
* @param int $yearValue
* @param boolean $calendarType
* @access private
* @return mixed
*/
private function dayOfWeek($yearValue, $dayOfYear = 0) {
$Rasad = $this
->calcRasad($yearValue);
$count2820 = floor($Rasad / 2820);
$mod2820 = $Rasad % 2820;
$count128 = floor($mod2820 / 128);
$mod128 = $mod2820 % 128;
$leapCount = 0;
while ($mod128 > $this->_khayamii[$leapCount]) {
$leapCount++;
}
$yearStartDay = ($count2820 + 1) * 3 + $count128 * 5 + $mod128 + $leapCount;
if ($dayOfYear > 0) {
$dayOfYear--;
}
return ($yearStartDay + $dayOfYear) % 7;
}
/**
* returns names of the weekday
*
* @param int $dayValue
* @access private
* @return string
*/
private function dayName($dayValue) {
$weekAlpha = array(
'شنبه',
'يکشنبه',
'دوشنبه',
'سه شنبه',
'چهارشنبه',
'پنج شنبه',
'جمعه',
);
return $weekAlpha[$dayValue];
}
/**
* returns abbreviated names of the weekday
*
* @param int $dayValue
* @access private
* @return string
*/
private function dayShortName($dayValue) {
$weekShort = array(
'ش',
'ي',
'د',
'س',
'چ',
'پ',
'ج',
);
return $weekShort[$dayValue];
}
/**
* returns names of the month
*
* @param int $monthValue
* @access private
* @return string
*/
private function monthName($monthValue) {
$monthAlpha = array(
1 => 'فروردين',
'ارديبهشت',
'خرداد',
'تير',
'مرداد',
'شهريور',
'مهر',
'آبان',
'آذر',
'دي',
'بهمن',
'اسفند',
);
return $monthAlpha[$monthValue];
}
/**
* returns abbreviated names of the month
*
* @param int $monthValue
* @access private
* @return string
*/
private function monthShortName($monthValue) {
$monthShort = array(
1 => 'فرو',
'ارد',
'خرد',
'تير',
'مرد',
'شهر',
'مهر',
'آبا',
'آذر',
'دي',
'بهم',
'اسف',
);
return $monthShort[$monthValue];
}
/**
* returns long text day of the month
*
* @param int $monthDayValue
* @access private
* @return string
*/
private function monthDayString($monthDayValue) {
$monthDays = array(
1 => 'یکم',
'دوم',
'سوم',
'چهارم',
'پنجم',
'ششم',
'هفتم',
'هشتم',
'نهم',
'دهم',
'یازدهم',
'دوازهم',
'سیزدهم',
'چهاردهم',
'پانزدهم',
'شانزدهم',
'هفدهم',
'هژدهم',
'نوزدهم',
'بیستم',
'بیست و یکم',
'بیست و دوم',
'بیست و سوم',
'بیست و چهارم',
'بیست و پنجم',
'بیست و ششم',
'بیست و هفتم',
'بیست و هشتم',
'بیست و نهم',
'سی ام',
'سی و یکم',
);
return $monthDays[$monthDayValue];
}
/**
* sets the full date data Y;M;D;H;I;S in various class attributes
*
* @access private
* @return void
*/
private function _date() {
$this
->_zone();
$timeStamp = $this->_timestamp;
$timeStamp = $timeStamp + $this->_timezoneOffset;
$Seconds = floor($timeStamp % 60);
$Minutes = floor($timeStamp % 3600 / 60);
$Hours = floor($timeStamp % 86400 / 3600);
$Days = floor($timeStamp / 86400);
$Days += 287;
$Years = floor($Days / self::KHAYAM_YEAR - $Days * self::KHAYAM_YEAR_CORRECTION);
$dayOfYear = $Days - round($Years * self::KHAYAM_YEAR, 0);
if ($dayOfYear == 0) {
$dayOfYear = 366;
}
$Years += 1348;
$Months = 0;
while ($Months < 12 && $dayOfYear > $this->_mountCounter[$Months]) {
$Months++;
}
$Days = $dayOfYear - $this->_mountCounter[$Months - 1];
$this->_second = $Seconds;
$this->_minute = $Minutes;
$this->_hour = $Hours;
$this->_day = $Days;
$this->_month = $Months;
$this->_year = $Years;
$this->_dayOfYear = $dayOfYear;
}
/**
* set all properties related to time zone
*
* @access private
* @return void
*/
private function _zone() {
$this->_timeZone = \date_default_timezone_get();
$this->_timeZoneAbb = \date('T', $this->_timestamp);
$this->_DLS = \date('I', $this->_timestamp);
$this->_GMTDiff = \date('O', $this->_timestamp);
$this->_GMTDiffC = \date('P', $this->_timestamp);
$this->_timezoneOffset = \date('Z', $this->_timestamp);
}
/**
* this is a clone of the internal php function date()
* with a few exceptions in the acceptable parameters
*
* These are the supported formats from php.date():
* a: Lowercase Ante meridiem and Post meridiem am or pm
* A: Uppercase Ante meridiem and Post meridiem AM or PM
* d: days from 01 to 31
* D: days --short-- from ش to ج
* j: days from 1 to 31
* l (lowercase 'L'): days from شنبه to جمعه
* N: number of day in week from 1 (شنبه) to 7 (جمعه)
* w: number of day in week
* S: month days from یکم to سی و یکم
* this is slightly different from php.date()!
* z: day in the year
* W: week in the year
* F: Month name from قروردین to اسفند
* m: Month number from 01 to 12
* M: month from فرو to اسف
* n: Month number from 1 to 12
* Y: full year numeric representation -- 4 digit
* y: year numeric representation -- 2 digit
* g: 12-hour format of an hour without leading zeros 1 through 12
* G: 24-hour format of an hour without leading zeros 0 through 23
* h: 12-hour format of an hour with leading zeros 01 through 12
* H: 24-hour format of an hour with leading zeros 00 through 23
* i: Minutes with leading zeros 00 to 59
* s: Seconds, with leading zeros 00 through 59
* T: Timezone abbreviation Examples: EST, MDT ...
* U: Seconds since the Unix Epoch See also time()
* L: whether it's a leap year
* I: (capital i) Whether or not the date is in daylight saving time 1 if
* Daylight Saving Time, 0 otherwise.
* O: Difference to Greenwich time (GMT) in hours Example: +0200
* P: Difference to Greenwich time (GMT) with colon
* between hours and minutes (added in PHP 5.1.3)
* Z: Timezone offset in seconds. The offset for timezones west of UTC is
* always negative, and for those east of UTC is always positive.
* -43200 through 50400
* c: ISO 8601 date (added in PHP 5) 2004-02-12T15:19:21+00:00
* r: » RFC 2822 formatted date Example: Thu, 21 Dec 2000 16:01:07 +0200
* e: Timezone identifier (added in PHP 5.1.0) Examples: GMT, Atlantic/Azores
*
* The following identifiers are not available:
* t: number of days in the given month
* o: year number
* B: Swatch Internet time 000 through 999
* u: Microseconds (added in PHP 5.2.2) Example: 54321
* @param string $format
* @param int $timestamp the unix-type timestamp to be used for output
* @param boolean $decorate if true function decorate is used for chanhing
* the face of output. if false the normal face of output is returned.
* for numbers false returns number, true returns string.
* @access public
* @return mixed
*/
public function format($format, $timestamp = 0, $decorate = true) {
if ($timestamp) {
$this->_timestamp = $timestamp;
}
$this
->_date();
$format = str_replace("a", $this->_hour <= 12 ? "ق.ظ" : "ب.ظ", $format);
$format = str_replace("A", $this->_hour <= 12 ? "ق.ظ" : "ب.ظ", $format);
$format = str_replace("d", str_pad($this->_day, 2, '0', STR_PAD_LEFT), $format);
$format = str_replace("D", $this
->dayShortName($this
->dayOfWeek($this->_year, $this->_dayOfYear)), $format);
$format = str_replace("j", $this->_day, $format);
$format = str_replace("l", $this
->dayName($this
->dayOfWeek($this->_year, $this->_dayOfYear)), $format);
$format = str_replace("N", $this
->dayOfWeek($this->_year, $this->_dayOfYear) + 1, $format);
$format = str_replace("w", $this
->dayOfWeek($this->_year, $this->_dayOfYear), $format);
$format = str_replace("S", $this
->monthDayString($this->_day), $format);
$format = str_replace("z", $this->_dayOfYear, $format);
$format = str_replace("W", $this
->weekOfYear(), $format);
$format = str_replace("F", $this
->monthName($this->_month), $format);
$format = str_replace("m", str_pad($this->_month, 2, '0', STR_PAD_LEFT), $format);
$format = str_replace("M", $this
->monthShortName($this->_month), $format);
$format = str_replace("n", $this->_month, $format);
$format = str_replace("Y", $this->_year, $format);
$format = str_replace("y", $this->_year % 100, $format);
$format = str_replace("g", $this->_hour % 12, $format);
$format = str_replace("G", $this->_hour, $format);
$format = str_replace("h", str_pad($this->_hour % 12, 2, '0', STR_PAD_LEFT), $format);
$format = str_replace("H", str_pad($this->_hour, 2, '0', STR_PAD_LEFT), $format);
$format = str_replace("i", str_pad($this->_minute, 2, '0', STR_PAD_LEFT), $format);
$format = str_replace("s", str_pad($this->_second, 2, '0', STR_PAD_LEFT), $format);
$format = str_replace("U", $this->_timestamp, $format);
$format = str_replace("L", $this
->isLeap($this->_year), $format);
$format = str_replace("Y", $this->_year, $format);
$format = str_replace("I", $this->_DLS, $format);
$format = str_replace("O", $this->_GMTDiff, $format);
$format = str_replace("P", $this->_GMTDiffC, $format);
$format = str_replace("Z", $this->_timezoneOffset, $format);
$format = str_replace("c", $this->_year . "-" . str_pad($this->_month, 2, '0', STR_PAD_LEFT) . "-" . str_pad($this->_day, 2, '0', STR_PAD_LEFT) . "ز" . str_pad($this->_hour, 2, '0', STR_PAD_LEFT) . ":" . str_pad($this->_minute, 2, '0', STR_PAD_LEFT) . ":" . str_pad($this->_second, 2, '0', STR_PAD_LEFT) . $this->_GMTDiffC, $format);
$format = str_replace("r", $this
->dayShortName($this
->dayOfWeek($this->_year, $this->_dayOfYear)) . "، " . $this->_day . " " . $this
->monthShortName($this->_month) . " " . $this->_year . " " . $this->_hour . ":" . $this->_minute . ":" . $this->_second . $this->_GMTDiff, $format);
$format = str_replace("T", $this->_timeZoneAbb, $format);
$format = str_replace("e", $this->_timeZone, $format);
if ($decorate) {
return self::ParsiNumbers($format);
}
else {
return $format;
}
}
/**
* creates timestamp depending on the Persian time parameters
*
* @access private
*
* @param mixed $year
* @param mixed $month
* @param mixed $day
* @param mixed $hour
* @param mixed $minute
* @param mixed $second
* @return integer time stamp
*/
public function mktime($year, $month, $day, $hour = 0, $minute = 0, $second = 0) {
$timeStamp = $second;
$timeStamp += $minute * 60;
$timeStamp += $hour * 60 * 60;
$dayOfYear = $day + $this->_mountCounter[$month - 1];
if ($year < 1300) {
$year += 1300;
}
$year -= 1348;
$day = $dayOfYear + round(self::KHAYAM_YEAR * $year, 0);
$day -= 287;
$timeStamp += $day * 86400;
$this->_timestamp = $timeStamp;
$this
->_zone();
$timeStamp = $timeStamp - $this->_timezoneOffset;
return $timeStamp;
}
/**
* returns current timestamp of the object
* this time stamp is equivalent to system timestamp; for current time
*
* @access public
* @return int
*/
public function getTimestamp() {
return $this->_timestamp;
}
}
function date($format, $timestamp = 0, $decorate = true) {
$jalali = new Date();
return $jalali
->format($format, $timestamp, $decorate);
}
function mktime($year, $month, $day, $hour = 0, $minute = 0, $second = 0) {
$jalali = new Date();
return $jalali
->mktime($year, $month, $day, $hour, $minute, $second);
}