diff options
Diffstat (limited to 'system/helpers/date.php')
-rw-r--r-- | system/helpers/date.php | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/system/helpers/date.php b/system/helpers/date.php new file mode 100644 index 00000000..7d5a9ab6 --- /dev/null +++ b/system/helpers/date.php @@ -0,0 +1,405 @@ +<?php defined('SYSPATH') OR die('No direct access allowed.'); +/** + * Date helper class. + * + * $Id: date.php 4316 2009-05-04 01:03:54Z kiall $ + * + * @package Core + * @author Kohana Team + * @copyright (c) 2007-2008 Kohana Team + * @license http://kohanaphp.com/license.html + */ +class date_Core { + + /** + * Converts a UNIX timestamp to DOS format. + * + * @param integer UNIX timestamp + * @return integer + */ + public static function unix2dos($timestamp = FALSE) + { + $timestamp = ($timestamp === FALSE) ? getdate() : getdate($timestamp); + + if ($timestamp['year'] < 1980) + { + return (1 << 21 | 1 << 16); + } + + $timestamp['year'] -= 1980; + + // What voodoo is this? I have no idea... Geert can explain it though, + // and that's good enough for me. + return ($timestamp['year'] << 25 | $timestamp['mon'] << 21 | + $timestamp['mday'] << 16 | $timestamp['hours'] << 11 | + $timestamp['minutes'] << 5 | $timestamp['seconds'] >> 1); + } + + /** + * Converts a DOS timestamp to UNIX format. + * + * @param integer DOS timestamp + * @return integer + */ + public static function dos2unix($timestamp = FALSE) + { + $sec = 2 * ($timestamp & 0x1f); + $min = ($timestamp >> 5) & 0x3f; + $hrs = ($timestamp >> 11) & 0x1f; + $day = ($timestamp >> 16) & 0x1f; + $mon = ($timestamp >> 21) & 0x0f; + $year = ($timestamp >> 25) & 0x7f; + + return mktime($hrs, $min, $sec, $mon, $day, $year + 1980); + } + + /** + * Returns the offset (in seconds) between two time zones. + * @see http://php.net/timezones + * + * @param string timezone that to find the offset of + * @param string|boolean timezone used as the baseline + * @return integer + */ + public static function offset($remote, $local = TRUE) + { + static $offsets; + + // Default values + $remote = (string) $remote; + $local = ($local === TRUE) ? date_default_timezone_get() : (string) $local; + + // Cache key name + $cache = $remote.$local; + + if (empty($offsets[$cache])) + { + // Create timezone objects + $remote = new DateTimeZone($remote); + $local = new DateTimeZone($local); + + // Create date objects from timezones + $time_there = new DateTime('now', $remote); + $time_here = new DateTime('now', $local); + + // Find the offset + $offsets[$cache] = $remote->getOffset($time_there) - $local->getOffset($time_here); + } + + return $offsets[$cache]; + } + + /** + * Number of seconds in a minute, incrementing by a step. + * + * @param integer amount to increment each step by, 1 to 30 + * @param integer start value + * @param integer end value + * @return array A mirrored (foo => foo) array from 1-60. + */ + public static function seconds($step = 1, $start = 0, $end = 60) + { + // Always integer + $step = (int) $step; + + $seconds = array(); + + for ($i = $start; $i < $end; $i += $step) + { + $seconds[$i] = ($i < 10) ? '0'.$i : $i; + } + + return $seconds; + } + + /** + * Number of minutes in an hour, incrementing by a step. + * + * @param integer amount to increment each step by, 1 to 30 + * @return array A mirrored (foo => foo) array from 1-60. + */ + public static function minutes($step = 5) + { + // Because there are the same number of minutes as seconds in this set, + // we choose to re-use seconds(), rather than creating an entirely new + // function. Shhhh, it's cheating! ;) There are several more of these + // in the following methods. + return date::seconds($step); + } + + /** + * Number of hours in a day. + * + * @param integer amount to increment each step by + * @param boolean use 24-hour time + * @param integer the hour to start at + * @return array A mirrored (foo => foo) array from start-12 or start-23. + */ + public static function hours($step = 1, $long = FALSE, $start = NULL) + { + // Default values + $step = (int) $step; + $long = (bool) $long; + $hours = array(); + + // Set the default start if none was specified. + if ($start === NULL) + { + $start = ($long === FALSE) ? 1 : 0; + } + + $hours = array(); + + // 24-hour time has 24 hours, instead of 12 + $size = ($long === TRUE) ? 23 : 12; + + for ($i = $start; $i <= $size; $i += $step) + { + $hours[$i] = $i; + } + + return $hours; + } + + /** + * Returns AM or PM, based on a given hour. + * + * @param integer number of the hour + * @return string + */ + public static function ampm($hour) + { + // Always integer + $hour = (int) $hour; + + return ($hour > 11) ? 'PM' : 'AM'; + } + + /** + * Adjusts a non-24-hour number into a 24-hour number. + * + * @param integer hour to adjust + * @param string AM or PM + * @return string + */ + public static function adjust($hour, $ampm) + { + $hour = (int) $hour; + $ampm = strtolower($ampm); + + switch ($ampm) + { + case 'am': + if ($hour == 12) + $hour = 0; + break; + case 'pm': + if ($hour < 12) + $hour += 12; + break; + } + + return sprintf('%02s', $hour); + } + + /** + * Number of days in month. + * + * @param integer number of month + * @param integer number of year to check month, defaults to the current year + * @return array A mirrored (foo => foo) array of the days. + */ + public static function days($month, $year = FALSE) + { + static $months; + + // Always integers + $month = (int) $month; + $year = (int) $year; + + // Use the current year by default + $year = ($year == FALSE) ? date('Y') : $year; + + // We use caching for months, because time functions are used + if (empty($months[$year][$month])) + { + $months[$year][$month] = array(); + + // Use date to find the number of days in the given month + $total = date('t', mktime(1, 0, 0, $month, 1, $year)) + 1; + + for ($i = 1; $i < $total; $i++) + { + $months[$year][$month][$i] = $i; + } + } + + return $months[$year][$month]; + } + + /** + * Number of months in a year + * + * @return array A mirrored (foo => foo) array from 1-12. + */ + public static function months() + { + return date::hours(); + } + + /** + * Returns an array of years between a starting and ending year. + * Uses the current year +/- 5 as the max/min. + * + * @param integer starting year + * @param integer ending year + * @return array + */ + public static function years($start = FALSE, $end = FALSE) + { + // Default values + $start = ($start === FALSE) ? date('Y') - 5 : (int) $start; + $end = ($end === FALSE) ? date('Y') + 5 : (int) $end; + + $years = array(); + + // Add one, so that "less than" works + $end += 1; + + for ($i = $start; $i < $end; $i++) + { + $years[$i] = $i; + } + + return $years; + } + + /** + * Returns time difference between two timestamps, in human readable format. + * + * @param integer timestamp + * @param integer timestamp, defaults to the current time + * @param string formatting string + * @return string|array + */ + public static function timespan($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds') + { + // Array with the output formats + $output = preg_split('/[^a-z]+/', strtolower((string) $output)); + + // Invalid output + if (empty($output)) + return FALSE; + + // Make the output values into keys + extract(array_flip($output), EXTR_SKIP); + + // Default values + $time1 = max(0, (int) $time1); + $time2 = empty($time2) ? time() : max(0, (int) $time2); + + // Calculate timespan (seconds) + $timespan = abs($time1 - $time2); + + // All values found using Google Calculator. + // Years and months do not match the formula exactly, due to leap years. + + // Years ago, 60 * 60 * 24 * 365 + isset($years) and $timespan -= 31556926 * ($years = (int) floor($timespan / 31556926)); + + // Months ago, 60 * 60 * 24 * 30 + isset($months) and $timespan -= 2629744 * ($months = (int) floor($timespan / 2629743.83)); + + // Weeks ago, 60 * 60 * 24 * 7 + isset($weeks) and $timespan -= 604800 * ($weeks = (int) floor($timespan / 604800)); + + // Days ago, 60 * 60 * 24 + isset($days) and $timespan -= 86400 * ($days = (int) floor($timespan / 86400)); + + // Hours ago, 60 * 60 + isset($hours) and $timespan -= 3600 * ($hours = (int) floor($timespan / 3600)); + + // Minutes ago, 60 + isset($minutes) and $timespan -= 60 * ($minutes = (int) floor($timespan / 60)); + + // Seconds ago, 1 + isset($seconds) and $seconds = $timespan; + + // Remove the variables that cannot be accessed + unset($timespan, $time1, $time2); + + // Deny access to these variables + $deny = array_flip(array('deny', 'key', 'difference', 'output')); + + // Return the difference + $difference = array(); + foreach ($output as $key) + { + if (isset($$key) AND ! isset($deny[$key])) + { + // Add requested key to the output + $difference[$key] = $$key; + } + } + + // Invalid output formats string + if (empty($difference)) + return FALSE; + + // If only one output format was asked, don't put it in an array + if (count($difference) === 1) + return current($difference); + + // Return array + return $difference; + } + + /** + * Returns time difference between two timestamps, in the format: + * N year, N months, N weeks, N days, N hours, N minutes, and N seconds ago + * + * @param integer timestamp + * @param integer timestamp, defaults to the current time + * @param string formatting string + * @return string + */ + public static function timespan_string($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds') + { + if ($difference = date::timespan($time1, $time2, $output) AND is_array($difference)) + { + // Determine the key of the last item in the array + $last = end($difference); + $last = key($difference); + + $span = array(); + foreach ($difference as $name => $amount) + { + if ($amount === 0) + { + // Skip empty amounts + continue; + } + + // Add the amount to the span + $span[] = ($name === $last ? ' and ' : ', ').$amount.' '.($amount === 1 ? inflector::singular($name) : $name); + } + + // If the difference is less than 60 seconds, remove the preceding and. + if (count($span) === 1) + { + $span[0] = ltrim($span[0], 'and '); + } + + // Replace difference by making the span into a string + $difference = trim(implode('', $span), ','); + } + elseif (is_int($difference)) + { + // Single-value return + $difference = $difference.' '.($difference === 1 ? inflector::singular($output) : $output); + } + + return $difference; + } + +} // End date
\ No newline at end of file |