1 <?php defined('SYSPATH') OR die('No direct access allowed.');
5 * $Id: date.php 4316 2009-05-04 01:03:54Z kiall $
9 * @copyright (c) 2007-2008 Kohana Team
10 * @license http://kohanaphp.com/license.html
15 * Converts a UNIX timestamp to DOS format.
17 * @param integer UNIX timestamp
20 public static function unix2dos($timestamp = FALSE)
22 $timestamp = ($timestamp === FALSE) ? getdate() : getdate($timestamp);
24 if ($timestamp['year'] < 1980)
26 return (1 << 21 | 1 << 16);
29 $timestamp['year'] -= 1980;
31 // What voodoo is this? I have no idea... Geert can explain it though,
32 // and that's good enough for me.
33 return ($timestamp['year'] << 25 | $timestamp['mon'] << 21 |
34 $timestamp['mday'] << 16 | $timestamp['hours'] << 11 |
35 $timestamp['minutes'] << 5 | $timestamp['seconds'] >> 1);
39 * Converts a DOS timestamp to UNIX format.
41 * @param integer DOS timestamp
44 public static function dos2unix($timestamp = FALSE)
46 $sec = 2 * ($timestamp & 0x1f);
47 $min = ($timestamp >> 5) & 0x3f;
48 $hrs = ($timestamp >> 11) & 0x1f;
49 $day = ($timestamp >> 16) & 0x1f;
50 $mon = ($timestamp >> 21) & 0x0f;
51 $year = ($timestamp >> 25) & 0x7f;
53 return mktime($hrs, $min, $sec, $mon, $day, $year + 1980);
57 * Returns the offset (in seconds) between two time zones.
58 * @see http://php.net/timezones
60 * @param string timezone that to find the offset of
61 * @param string|boolean timezone used as the baseline
64 public static function offset($remote, $local = TRUE)
69 $remote = (string) $remote;
70 $local = ($local === TRUE) ? date_default_timezone_get() : (string) $local;
73 $cache = $remote.$local;
75 if (empty($offsets[$cache]))
77 // Create timezone objects
78 $remote = new DateTimeZone($remote);
79 $local = new DateTimeZone($local);
81 // Create date objects from timezones
82 $time_there = new DateTime('now', $remote);
83 $time_here = new DateTime('now', $local);
86 $offsets[$cache] = $remote->getOffset($time_there) - $local->getOffset($time_here);
89 return $offsets[$cache];
93 * Number of seconds in a minute, incrementing by a step.
95 * @param integer amount to increment each step by, 1 to 30
96 * @param integer start value
97 * @param integer end value
98 * @return array A mirrored (foo => foo) array from 1-60.
100 public static function seconds($step = 1, $start = 0, $end = 60)
107 for ($i = $start; $i < $end; $i += $step)
109 $seconds[$i] = ($i < 10) ? '0'.$i : $i;
116 * Number of minutes in an hour, incrementing by a step.
118 * @param integer amount to increment each step by, 1 to 30
119 * @return array A mirrored (foo => foo) array from 1-60.
121 public static function minutes($step = 5)
123 // Because there are the same number of minutes as seconds in this set,
124 // we choose to re-use seconds(), rather than creating an entirely new
125 // function. Shhhh, it's cheating! ;) There are several more of these
126 // in the following methods.
127 return date::seconds($step);
131 * Number of hours in a day.
133 * @param integer amount to increment each step by
134 * @param boolean use 24-hour time
135 * @param integer the hour to start at
136 * @return array A mirrored (foo => foo) array from start-12 or start-23.
138 public static function hours($step = 1, $long = FALSE, $start = NULL)
142 $long = (bool) $long;
145 // Set the default start if none was specified.
148 $start = ($long === FALSE) ? 1 : 0;
153 // 24-hour time has 24 hours, instead of 12
154 $size = ($long === TRUE) ? 23 : 12;
156 for ($i = $start; $i <= $size; $i += $step)
165 * Returns AM or PM, based on a given hour.
167 * @param integer number of the hour
170 public static function ampm($hour)
175 return ($hour > 11) ? 'PM' : 'AM';
179 * Adjusts a non-24-hour number into a 24-hour number.
181 * @param integer hour to adjust
182 * @param string AM or PM
185 public static function adjust($hour, $ampm)
188 $ampm = strtolower($ampm);
202 return sprintf('%02s', $hour);
206 * Number of days in month.
208 * @param integer number of month
209 * @param integer number of year to check month, defaults to the current year
210 * @return array A mirrored (foo => foo) array of the days.
212 public static function days($month, $year = FALSE)
217 $month = (int) $month;
220 // Use the current year by default
221 $year = ($year == FALSE) ? date('Y') : $year;
223 // We use caching for months, because time functions are used
224 if (empty($months[$year][$month]))
226 $months[$year][$month] = array();
228 // Use date to find the number of days in the given month
229 $total = date('t', mktime(1, 0, 0, $month, 1, $year)) + 1;
231 for ($i = 1; $i < $total; $i++)
233 $months[$year][$month][$i] = $i;
237 return $months[$year][$month];
241 * Number of months in a year
243 * @return array A mirrored (foo => foo) array from 1-12.
245 public static function months()
247 return date::hours();
251 * Returns an array of years between a starting and ending year.
252 * Uses the current year +/- 5 as the max/min.
254 * @param integer starting year
255 * @param integer ending year
258 public static function years($start = FALSE, $end = FALSE)
261 $start = ($start === FALSE) ? date('Y') - 5 : (int) $start;
262 $end = ($end === FALSE) ? date('Y') + 5 : (int) $end;
266 // Add one, so that "less than" works
269 for ($i = $start; $i < $end; $i++)
278 * Returns time difference between two timestamps, in human readable format.
280 * @param integer timestamp
281 * @param integer timestamp, defaults to the current time
282 * @param string formatting string
283 * @return string|array
285 public static function timespan($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
287 // Array with the output formats
288 $output = preg_split('/[^a-z]+/', strtolower((string) $output));
294 // Make the output values into keys
295 extract(array_flip($output), EXTR_SKIP);
298 $time1 = max(0, (int) $time1);
299 $time2 = empty($time2) ? time() : max(0, (int) $time2);
301 // Calculate timespan (seconds)
302 $timespan = abs($time1 - $time2);
304 // All values found using Google Calculator.
305 // Years and months do not match the formula exactly, due to leap years.
307 // Years ago, 60 * 60 * 24 * 365
308 isset($years) and $timespan -= 31556926 * ($years = (int) floor($timespan / 31556926));
310 // Months ago, 60 * 60 * 24 * 30
311 isset($months) and $timespan -= 2629744 * ($months = (int) floor($timespan / 2629743.83));
313 // Weeks ago, 60 * 60 * 24 * 7
314 isset($weeks) and $timespan -= 604800 * ($weeks = (int) floor($timespan / 604800));
316 // Days ago, 60 * 60 * 24
317 isset($days) and $timespan -= 86400 * ($days = (int) floor($timespan / 86400));
319 // Hours ago, 60 * 60
320 isset($hours) and $timespan -= 3600 * ($hours = (int) floor($timespan / 3600));
323 isset($minutes) and $timespan -= 60 * ($minutes = (int) floor($timespan / 60));
326 isset($seconds) and $seconds = $timespan;
328 // Remove the variables that cannot be accessed
329 unset($timespan, $time1, $time2);
331 // Deny access to these variables
332 $deny = array_flip(array('deny', 'key', 'difference', 'output'));
334 // Return the difference
335 $difference = array();
336 foreach ($output as $key)
338 if (isset($$key) AND ! isset($deny[$key]))
340 // Add requested key to the output
341 $difference[$key] = $$key;
345 // Invalid output formats string
346 if (empty($difference))
349 // If only one output format was asked, don't put it in an array
350 if (count($difference) === 1)
351 return current($difference);
358 * Returns time difference between two timestamps, in the format:
359 * N year, N months, N weeks, N days, N hours, N minutes, and N seconds ago
361 * @param integer timestamp
362 * @param integer timestamp, defaults to the current time
363 * @param string formatting string
366 public static function timespan_string($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
368 if ($difference = date::timespan($time1, $time2, $output) AND is_array($difference))
370 // Determine the key of the last item in the array
371 $last = end($difference);
372 $last = key($difference);
375 foreach ($difference as $name => $amount)
379 // Skip empty amounts
383 // Add the amount to the span
384 $span[] = ($name === $last ? ' and ' : ', ').$amount.' '.($amount === 1 ? inflector::singular($name) : $name);
387 // If the difference is less than 60 seconds, remove the preceding and.
388 if (count($span) === 1)
390 $span[0] = ltrim($span[0], 'and ');
393 // Replace difference by making the span into a string
394 $difference = trim(implode('', $span), ',');
396 elseif (is_int($difference))
398 // Single-value return
399 $difference = $difference.' '.($difference === 1 ? inflector::singular($output) : $output);