123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- <?php
- // To allow overriding this function as will, if someone wants to use a derived class of `TimeAgo`
- if (!function_exists('timeAgoInWords')) {
- function timeAgoInWords($timestring, $timezone = null, $language = 'en')
- {
- $timeAgo = new TimeAgo($timezone, $language);
- return $timeAgo->inWords($timestring, "now");
- }
- }
- /**
- * This class can help you find out just how much time has passed between
- * two dates.
- *
- * It has two functions you can call:
- * inWords() which gives you the "time ago in words" between two dates.
- * dateDifference() which returns an array of years,months,days,hours,minutes and
- * seconds between the two dates.
- *
- * @author jimmiw
- * @since 0.2.0 (2010/05/05)
- * @site http://github.com/jimmiw/php-time-ago
- */
- class TimeAgo
- {
- // defines the number of seconds per "unit"
- private $secondsPerMinute = 60;
- private $secondsPerHour = 3600;
- private $secondsPerDay = 86400;
- private $secondsPerMonth = 2592000;
- private $secondsPerYear = 31536000; // 31622400 seconds on leap years though...
- private $timezone;
- private $previousTimezone;
- // translations variables
- private static $language;
- private static $timeAgoStrings = null;
- /**
- * TimeAgo constructor.
- * @param null|DateTimeZone $timezone the timezone to use (uses system if none is given)
- * @param string $language the language to use (defaults to 'en' for english)
- */
- public function __construct($timezone = null, $language = 'en')
- {
- // loads the translation files
- self::_loadTranslations($language);
- // storing the current timezone
- $this->timezone = $timezone;
- }
- /**
- * Fetches the different between $past and $now in a spoken format.
- * NOTE: both past and now should be parseable by strtotime
- * @param string $past the past date to use
- * @param string $now the current time, defaults to now (can be an other time though)
- * @return string the difference in spoken format, e.g. 1 day ago
- */
- public function inWords($past, $now = "now")
- {
- // sets the default timezone
- $this->changeTimezone();
- // finds the past in datetime
- $past = strtotime($past);
- // finds the current datetime
- $now = strtotime($now);
- // creates the "time ago" string. This always starts with an "about..."
- $timeAgo = "";
- // finds the time difference
- $timeDifference = $now - $past;
- // rule 0
- // $past is null or empty or ''
- if ($past === '' || is_null($past) || empty($past)) {
- $timeAgo = $this->_translate('never');
- }
- // rule 1
- // less than 29secs
- else if ($timeDifference <= 29) {
- $timeAgo = $this->_translate('lessThanAMinute');
- }
- // rule 2
- // more than 29secs and less than 1min29secss
- else if ($timeDifference >= 30 && $timeDifference <= 89) {
- $timeAgo = $this->_translate('oneMinute');
- }
- // rule 3
- // between 1min30secs and 44mins29secs
- else if ($timeDifference >= 90 &&
- $timeDifference <= (($this->secondsPerMinute * 44) + 29)
- ) {
- $minutes = round($timeDifference / $this->secondsPerMinute);
- $timeAgo = $this->_translate('lessThanOneHour', $minutes);
- }
- // rule 4
- // between 44mins30secs and 1hour29mins59secs
- else if (
- $timeDifference >= (($this->secondsPerMinute * 44) + 30)
- &&
- $timeDifference <= ($this->secondsPerHour + ($this->secondsPerMinute * 29) + 59)
- ) {
- $timeAgo = $this->_translate('aboutOneHour');
- }
- // rule 5
- // between 1hour29mins59secs and 23hours59mins29secs
- else if (
- $timeDifference >= (
- $this->secondsPerHour +
- ($this->secondsPerMinute * 30)
- )
- &&
- $timeDifference <= (
- ($this->secondsPerHour * 23) +
- ($this->secondsPerMinute * 59) +
- 29
- )
- ) {
- $hours = round($timeDifference / $this->secondsPerHour);
- $timeAgo = $this->_translate('hours', $hours);
- }
- // rule 6
- // between 23hours59mins30secs and 47hours59mins29secs
- else if (
- $timeDifference >= (
- ($this->secondsPerHour * 23) +
- ($this->secondsPerMinute * 59) +
- 30
- )
- &&
- $timeDifference <= (
- ($this->secondsPerHour * 47) +
- ($this->secondsPerMinute * 59) +
- 29
- )
- ) {
- $timeAgo = $this->_translate('aboutOneDay');
- }
- // rule 7
- // between 47hours59mins30secs and 29days23hours59mins29secs
- else if (
- $timeDifference >= (
- ($this->secondsPerHour * 47) +
- ($this->secondsPerMinute * 59) +
- 30
- )
- &&
- $timeDifference <= (
- ($this->secondsPerDay * 29) +
- ($this->secondsPerHour * 23) +
- ($this->secondsPerMinute * 59) +
- 29
- )
- ) {
- $days = round($timeDifference / $this->secondsPerDay);
- $timeAgo = $this->_translate('days', $days);
- }
- // rule 8
- // between 29days23hours59mins30secs and 59days23hours59mins29secs
- else if (
- $timeDifference >= (
- ($this->secondsPerDay * 29) +
- ($this->secondsPerHour * 23) +
- ($this->secondsPerMinute * 59) +
- 30
- )
- &&
- $timeDifference <= (
- ($this->secondsPerDay * 59) +
- ($this->secondsPerHour * 23) +
- ($this->secondsPerMinute * 59) +
- 29
- )
- ) {
- $timeAgo = $this->_translate('aboutOneMonth');
- }
- // rule 9
- // between 59days23hours59mins30secs and 1year (minus 1sec)
- else if (
- $timeDifference >= (
- ($this->secondsPerDay * 59) +
- ($this->secondsPerHour * 23) +
- ($this->secondsPerMinute * 59) +
- 30
- )
- &&
- $timeDifference < $this->secondsPerYear
- ) {
- $months = round($timeDifference / $this->secondsPerMonth);
- // if months is 1, then set it to 2, because we are "past" 1 month
- if ($months == 1) {
- $months = 2;
- }
- $timeAgo = $this->_translate('months', $months);
- }
- // rule 10
- // between 1year and 2years (minus 1sec)
- else if (
- $timeDifference >= $this->secondsPerYear
- &&
- $timeDifference < ($this->secondsPerYear * 2)
- ) {
- $timeAgo = $this->_translate('aboutOneYear');
- }
- // rule 11
- // 2years or more
- else {
- $years = floor($timeDifference / $this->secondsPerYear);
- $timeAgo = $this->_translate('years', $years);
- }
- $this->restoreTimezone();
- return $timeAgo;
- }
- /**
- * Fetches the date difference between the two given dates.
- * NOTE: both past and now should be parseable by strtotime
- *
- * @param string $past the "past" time to parse
- * @param string $now the "now" time to parse
- * @return array the difference in dates, using the two dates
- */
- public function dateDifference($past, $now = "now")
- {
- // initializes the placeholders for the different "times"
- $seconds = 0;
- $minutes = 0;
- $hours = 0;
- $days = 0;
- $months = 0;
- $years = 0;
- // sets the default timezone
- $this->changeTimezone();
- // finds the past in datetime
- $past = strtotime($past);
- // finds the current datetime
- $now = strtotime($now);
- // calculates the difference
- $timeDifference = $now - $past;
- // starts determining the time difference
- if ($timeDifference >= 0) {
- switch ($timeDifference) {
- // finds the number of years
- case ($timeDifference >= $this->secondsPerYear):
- // uses floor to remove decimals
- $years = floor($timeDifference / $this->secondsPerYear);
- // saves the amount of seconds left
- $timeDifference = $timeDifference - ($years * $this->secondsPerYear);
- // finds the number of months
- case ($timeDifference >= $this->secondsPerMonth && $timeDifference <= ($this->secondsPerYear - 1)):
- // uses floor to remove decimals
- $months = floor($timeDifference / $this->secondsPerMonth);
- // saves the amount of seconds left
- $timeDifference = $timeDifference - ($months * $this->secondsPerMonth);
- // finds the number of days
- case ($timeDifference >= $this->secondsPerDay && $timeDifference <= ($this->secondsPerYear - 1)):
- // uses floor to remove decimals
- $days = floor($timeDifference / $this->secondsPerDay);
- // saves the amount of seconds left
- $timeDifference = $timeDifference - ($days * $this->secondsPerDay);
- // finds the number of hours
- case ($timeDifference >= $this->secondsPerHour && $timeDifference <= ($this->secondsPerDay - 1)):
- // uses floor to remove decimals
- $hours = floor($timeDifference / $this->secondsPerHour);
- // saves the amount of seconds left
- $timeDifference = $timeDifference - ($hours * $this->secondsPerHour);
- // finds the number of minutes
- case ($timeDifference >= $this->secondsPerMinute && $timeDifference <= ($this->secondsPerHour - 1)):
- // uses floor to remove decimals
- $minutes = floor($timeDifference / $this->secondsPerMinute);
- // saves the amount of seconds left
- $timeDifference = $timeDifference - ($minutes * $this->secondsPerMinute);
- // finds the number of seconds
- case ($timeDifference <= ($this->secondsPerMinute - 1)):
- // seconds is just what there is in the timeDifference variable
- $seconds = $timeDifference;
- }
- }
- $this->restoreTimezone();
- $difference = [
- "years" => $years,
- "months" => $months,
- "days" => $days,
- "hours" => $hours,
- "minutes" => $minutes,
- "seconds" => $seconds,
- ];
- return $difference;
- }
- /**
- * Translates the given $label, and adds the given $time.
- * @param string $label the label to translate
- * @param string $time the time to add to the translated text.
- * @return string the translated label text including the time.
- */
- protected function _translate($label, $time = '')
- {
- // handles a usecase introduced in #18, where a new translation was added.
- // This would cause an array-out-of-bound exception, since the index does not
- // exist in most translations.
- if (!isset(self::$timeAgoStrings[$label])) {
- return '';
- }
- return sprintf(self::$timeAgoStrings[$label], $time);
- }
- /**
- * Loads the translations into the system.
- */
- protected static function _loadTranslations($language, $alternate_path = null)
- {
- // no time strings loaded? load them and store it all in static variables
- if (self::$timeAgoStrings == null || self::$language != $language) {
- include(__DIR__ . '/translations/' . $language . '.php');
- if (!isset($timeAgoStrings) && $alternate_path) {
- include($alternate_path);
- }
- // storing the time strings in the current object
- self::$timeAgoStrings = $timeAgoStrings;
- // loads the language files
- if (self::$timeAgoStrings == null) {
- error_log('Could not load language file for language ' . $language . '. Please ensure that the file exists in ' . __DIR__ . 'translations/' . $language . '.php');
- }
- }
- // storing the language
- self::$language = $language;
- }
- protected function changeTimezone()
- {
- $this->previousTimezone = false;
- if ($this->timezone) {
- $this->previousTimezone = date_default_timezone_get();
- date_default_timezone_set($this->timezone);
- }
- }
- protected function restoreTimezone()
- {
- if ($this->previousTimezone) {
- date_default_timezone_set($this->previousTimezone);
- $this->previousTimezone = false;
- }
- }
- }
|