PageRenderTime 26ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/core/classes/date.php

https://github.com/mzkrelx/milm-search-ui-php
PHP | 404 lines | 208 code | 63 blank | 133 comment | 29 complexity | f0d380521522c57cbdbaa5e819ec36a0 MD5 | raw file
  1. <?php
  2. /**
  3. * Part of the Fuel framework.
  4. *
  5. * @package Fuel
  6. * @version 1.0
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2012 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. /**
  14. * Date Class
  15. *
  16. * DateTime replacement that supports internationalization and does correction to GMT
  17. * when your webserver isn't configured correctly.
  18. *
  19. * @package Fuel
  20. * @subpackage Core
  21. * @category Core
  22. * @link http://docs.fuelphp.com/classes/date.html
  23. *
  24. * Notes:
  25. * - Always returns Date objects, will accept both Date objects and UNIX timestamps
  26. * - create_time() uses strptime and has currently a very bad hack to use strtotime for windows servers
  27. * - Uses strftime formatting for dates www.php.net/manual/en/function.strftime.php
  28. */
  29. class Date
  30. {
  31. /**
  32. * Time constants (and only those that are constant, thus not MONTH/YEAR)
  33. */
  34. const WEEK = 604800;
  35. const DAY = 86400;
  36. const HOUR = 3600;
  37. const MINUTE = 60;
  38. /**
  39. * @var int server's time() offset from gmt in seconds
  40. */
  41. protected static $server_gmt_offset = 0;
  42. /**
  43. * @var string the timezone to be used to output formatted data
  44. */
  45. public static $display_timezone = null;
  46. public static function _init()
  47. {
  48. static::$server_gmt_offset = \Config::get('server_gmt_offset', 0);
  49. static::$display_timezone = \Config::get('default_timezone', null);
  50. // Ugly temporary windows fix because windows doesn't support strptime()
  51. // Better fix will accept custom pattern parsing but only parse numeric input on windows servers
  52. if ( ! function_exists('strptime') && ! function_exists('Fuel\Core\strptime'))
  53. {
  54. function strptime($input, $format)
  55. {
  56. if ($ts = strtotime($input))
  57. {
  58. return array(
  59. 'tm_year' => date('Y', $ts),
  60. 'tm_mon' => date('n', $ts) - 1,
  61. 'tm_mday' => date('j', $ts),
  62. 'tm_hour' => date('H', $ts),
  63. 'tm_min' => date('i', $ts),
  64. 'tm_sec' => date('s', $ts),
  65. );
  66. }
  67. else
  68. {
  69. $masks = array(
  70. '%d' => '(?P<d>[0-9]{2})',
  71. '%m' => '(?P<m>[0-9]{2})',
  72. '%Y' => '(?P<Y>[0-9]{4})',
  73. '%H' => '(?P<H>[0-9]{2})',
  74. '%M' => '(?P<M>[0-9]{2})',
  75. '%S' => '(?P<S>[0-9]{2})',
  76. );
  77. $rexep = "#" . strtr(preg_quote($format), $masks) . "#";
  78. if ( ! preg_match($rexep, $input, $result))
  79. {
  80. return false;
  81. }
  82. return array(
  83. "tm_sec" => isset($result['S']) ? (int) $result['S'] : 0,
  84. "tm_min" => isset($result['M']) ? (int) $result['M'] : 0,
  85. "tm_hour" => isset($result['H']) ? (int) $result['H'] : 0,
  86. "tm_mday" => isset($result['d']) ? (int) $result['d'] : 0,
  87. "tm_mon" => isset($result['m']) ? ($result['m'] ? $result['m'] - 1 : 0) : 0,
  88. "tm_year" => isset($result['Y']) ? ($result['Y'] > 1900 ? $result['Y'] - 1900 : 0) : 0,
  89. );
  90. }
  91. }
  92. // This really is some fugly code, but someone at PHP HQ decided strptime should
  93. // output this awful array instead of a timestamp LIKE EVERYONE ELSE DOES!!!
  94. }
  95. }
  96. /**
  97. * Create Date object from timestamp, timezone is optional
  98. *
  99. * @param int UNIX timestamp from current server
  100. * @param string valid PHP timezone from www.php.net/timezones
  101. * @return Date
  102. */
  103. public static function forge($timestamp = null, $timezone = null)
  104. {
  105. return new static($timestamp, $timezone);
  106. }
  107. /**
  108. * Returns the current time with offset
  109. *
  110. * @return Date
  111. */
  112. public static function time($timezone = null)
  113. {
  114. return static::forge(null, $timezone);
  115. }
  116. /**
  117. * Returns the current time with offset
  118. *
  119. * @return string
  120. */
  121. public static function display_timezone($timezone = null)
  122. {
  123. is_string($timezone) and static::$display_timezone = $timezone;
  124. return static::$display_timezone;
  125. }
  126. /**
  127. * Uses the date config file to translate string input to timestamp
  128. *
  129. * @param string date/time input
  130. * @param string key name of pattern in config file
  131. * @return Date
  132. */
  133. public static function create_from_string($input, $pattern_key = 'local')
  134. {
  135. \Config::load('date', 'date');
  136. $pattern = \Config::get('date.patterns.'.$pattern_key, null);
  137. empty($pattern) and $pattern = $pattern_key;
  138. $time = strptime($input, $pattern);
  139. if ($time === false)
  140. {
  141. throw new \UnexpectedValueException('Input was not recognized by pattern.');
  142. }
  143. $timestamp = mktime($time['tm_hour'], $time['tm_min'], $time['tm_sec'],
  144. $time['tm_mon'] + 1, $time['tm_mday'], $time['tm_year'] + 1900);
  145. if ($timestamp === false)
  146. {
  147. throw new \OutOfBoundsException('Input was invalid.'.(PHP_INT_SIZE == 4?' A 32-bit system only supports dates between 1901 and 2038.':''));
  148. }
  149. return static::forge($timestamp);
  150. }
  151. /**
  152. * Fetches an array of Date objects per interval within a range
  153. *
  154. * @param int|Date start of the range
  155. * @param int|Date end of the range
  156. * @param int|string Length of the interval in seconds or valid strtotime time difference
  157. * @return array array of Date objects
  158. */
  159. public static function range_to_array($start, $end, $interval = '+1 Day')
  160. {
  161. $start = ( ! $start instanceof Date) ? static::forge($start) : $start;
  162. $end = ( ! $end instanceof Date) ? static::forge($end) : $end;
  163. is_int($interval) or $interval = strtotime($interval, $start->get_timestamp()) - $start->get_timestamp();
  164. if ($interval <= 0)
  165. {
  166. throw new \UnexpectedValueException('Input was not recognized by pattern.');
  167. }
  168. $range = array();
  169. $current = $start;
  170. while ($current->get_timestamp() <= $end->get_timestamp())
  171. {
  172. $range[] = $current;
  173. $current = static::forge($current->get_timestamp() + $interval);
  174. }
  175. return $range;
  176. }
  177. /**
  178. * Returns the number of days in the requested month
  179. *
  180. * @param int month as a number (1-12)
  181. * @param int the year, leave empty for current
  182. * @return int the number of days in the month
  183. */
  184. public static function days_in_month($month, $year = null)
  185. {
  186. $year = ! empty($year) ? (int) $year : (int) date('Y');
  187. $month = (int) $month;
  188. if ($month < 1 or $month > 12)
  189. {
  190. throw new \UnexpectedValueException('Invalid input for month given.');
  191. }
  192. elseif ($month == 2)
  193. {
  194. if ($year % 400 == 0 or ($year % 4 == 0 and $year % 100 != 0))
  195. {
  196. return 29;
  197. }
  198. }
  199. $days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  200. return $days_in_month[$month-1];
  201. }
  202. /**
  203. * Returns the time ago
  204. *
  205. * @param int UNIX timestamp from current server
  206. * @param int UNIX timestamp to compare against. Default to the current time
  207. * @param string Unit to return the result in
  208. * @return string Time ago
  209. */
  210. public static function time_ago($timestamp, $from_timestamp = null, $unit = null)
  211. {
  212. if ($timestamp === null)
  213. {
  214. return '';
  215. }
  216. ! is_numeric($timestamp) and $timestamp = static::create_from_string($timestamp)->get_timestamp();
  217. $from_timestamp == null and $from_timestamp = time();
  218. \Lang::load('date', true);
  219. $difference = $from_timestamp - $timestamp;
  220. $periods = array('second', 'minute', 'hour', 'day', 'week', 'month', 'year', 'decade');
  221. $lengths = array(60, 60, 24, 7, 4.35, 12, 10);
  222. for ($j = 0; isset($lengths[$j]) and $difference >= $lengths[$j] and (empty($unit) or $unit != $periods[$j]); $j++)
  223. {
  224. $difference /= $lengths[$j];
  225. }
  226. $difference = round($difference);
  227. if ($difference != 1)
  228. {
  229. $periods[$j] = \Inflector::pluralize($periods[$j]);
  230. }
  231. $text = \Lang::get('date.text', array(
  232. 'time' => \Lang::get('date.'.$periods[$j], array('t' => $difference))
  233. ));
  234. return $text;
  235. }
  236. /**
  237. * @var int instance timestamp
  238. */
  239. protected $timestamp;
  240. /**
  241. * @var string output timezone
  242. */
  243. protected $timezone;
  244. public function __construct($timestamp = null, $timezone = null)
  245. {
  246. ! $timestamp and $timestamp = time() + static::$server_gmt_offset;
  247. ! $timezone and $timezone = \Fuel::$timezone;
  248. $this->timestamp = $timestamp;
  249. $this->set_timezone($timezone);
  250. }
  251. /**
  252. * Returns the date formatted according to the current locale
  253. *
  254. * @param string either a named pattern from date config file or a pattern, defaults to 'local'
  255. * @param mixed vald timezone, or if true, output the time in local time instead of system time
  256. * @return string
  257. */
  258. public function format($pattern_key = 'local', $timezone = null)
  259. {
  260. \Config::load('date', 'date');
  261. $pattern = \Config::get('date.patterns.'.$pattern_key, $pattern_key);
  262. // determine the timezone to switch to
  263. $timezone === true and $timezone = static::$display_timezone;
  264. is_string($timezone) or $timezone = $this->timezone;
  265. // Temporarily change timezone when different from default
  266. if (\Fuel::$timezone != $timezone)
  267. {
  268. date_default_timezone_set($timezone);
  269. }
  270. // Create output
  271. $output = strftime($pattern, $this->timestamp);
  272. // Change timezone back to default if changed previously
  273. if (\Fuel::$timezone != $timezone)
  274. {
  275. date_default_timezone_set(\Fuel::$timezone);
  276. }
  277. return $output;
  278. }
  279. /**
  280. * Returns the internal timestamp
  281. *
  282. * @return int
  283. */
  284. public function get_timestamp()
  285. {
  286. return $this->timestamp;
  287. }
  288. /**
  289. * Returns the internal timezone
  290. *
  291. * @return string
  292. */
  293. public function get_timezone()
  294. {
  295. return $this->timezone;
  296. }
  297. /**
  298. * Returns the internal timezone or the display timezone abbreviation
  299. *
  300. * @return string
  301. */
  302. public function get_timezone_abbr($display_timezone = false)
  303. {
  304. // determine the timezone to switch to
  305. $display_timezone and $timezone = static::$display_timezone;
  306. empty($timezone) and $timezone = $this->timezone;
  307. // Temporarily change timezone when different from default
  308. if (\Fuel::$timezone != $timezone)
  309. {
  310. date_default_timezone_set($timezone);
  311. }
  312. // Create output
  313. $output = date('T');
  314. // Change timezone back to default if changed previously
  315. if (\Fuel::$timezone != $timezone)
  316. {
  317. date_default_timezone_set(\Fuel::$timezone);
  318. }
  319. return $output;
  320. }
  321. /**
  322. * Change the timezone
  323. *
  324. * @param string timezone from www.php.net/timezones
  325. * @return Date
  326. */
  327. public function set_timezone($timezone)
  328. {
  329. $this->timezone = $timezone;
  330. return $this;
  331. }
  332. /**
  333. * Allows you to just put the object in a string and get it inserted in the default pattern
  334. *
  335. * @return string
  336. */
  337. public function __toString()
  338. {
  339. return $this->format();
  340. }
  341. }