Last active
December 2, 2016 10:38
-
-
Save mikemadisonweb/1e97c9026c0c9dcb8dac3547cdc31f49 to your computer and use it in GitHub Desktop.
Class DateIntervals - helper class to compute and format human readable date intervals , e.g. 1 hour 5 minutes 24 seconds
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Helper class to compute human readable date intervals , e.g. 1 hour 5 minutes 24 seconds | |
*/ | |
class DateIntervals | |
{ | |
private $forms = [ | |
'eng' => [ | |
'years' => ['year', 'years'], | |
'months' => ['month', 'months'], | |
'days' => ['day', 'days'], | |
'hours' => ['hour', 'hours'], | |
'minutes' => ['minute', 'minutes'], | |
'seconds' => ['second', 'seconds'], | |
], | |
'rus' => [ | |
'years' => ['год', 'года', 'лет'], | |
'months' => ['месяц', 'месяца', 'месяцев'], | |
'days' => ['день', 'дня', 'дней'], | |
'hours' => ['час', 'часа', 'часов'], | |
'minutes' => ['минута', 'минуты', 'минут'], | |
'seconds' => ['секунда', 'секунды', 'секунд'], | |
], | |
]; | |
private $supported = ['eng' => true, 'rus' => true]; | |
/** | |
* Get string interval | |
* | |
* @param string|\DateTime $date | |
* @param string $lang | |
* @param int $max Max number of units (e.g., 2 units is 6 month 1 week) starting from largest | |
* @param string $separator | |
* | |
* @return string | |
* | |
* @throws \Exception | |
*/ | |
public function getInterval($date, $lang = 'eng', $max = 3, $separator = ' ') | |
{ | |
if (!$date instanceof \DateTime) { | |
if (!is_string($date)) { | |
throw new \Exception('Expected formatted string of \DateTime object.'); | |
} | |
$timestamp = $this->getTimestamp($date); | |
$date = new \DateTime(); | |
$date->setTimestamp($timestamp); | |
} | |
return $this->getIntervalString($date, $lang, $max, $separator); | |
} | |
/** | |
* Plural forms of date strings | |
* | |
* @param $lang | |
* @param int $number Number of days, weeks or etc | |
* @param $wordForms | |
* | |
* @return string | |
* | |
* @throws \Exception | |
*/ | |
private function pluralRules($lang, $number, $wordForms) | |
{ | |
switch ($lang) { | |
case 'eng': | |
return $number.' '.(($number === 1) ? $wordForms[0] : $wordForms[1]); | |
case 'rus': | |
$cases = array(2, 0, 1, 1, 1, 2); | |
return $number.' '.$wordForms[($number % 100 > 4 && $number % 100 < 20) ? 2 : $cases[min($number % 10, 5)]]; | |
default: | |
$supported = implode(', ', array_keys($this->supported)); | |
throw new \Exception("Wrong language argument passed. Supported languages are ({$supported})"); | |
} | |
} | |
/** | |
* Get string representation of Datetime object | |
* | |
* @param \DateTime $date | |
* @param string $lang | |
* @param int $max | |
* @param string $separator | |
* | |
* @return string | |
* | |
* @throws \Exception | |
*/ | |
private function getIntervalString(\DateTime $date, $lang, $max, $separator) | |
{ | |
$timeComponents = (array) $date->diff(new \DateTime()); | |
$notNullTimeComponents = array_values(array_filter(array_slice($timeComponents, 0, 6))); | |
if (($max > 6) && ($max < 1) && !is_numeric($max)) { | |
throw new \Exception('Max number of units should be a number between 1 and 6.'); | |
} | |
$interval = []; | |
for ($i = 0; $i < $max; ++$i) { | |
// Если diff вернёт 0 лет мы должны исключить ненужные элементы из списка форм | |
if (isset($notNullTimeComponents[$i])) { | |
$formForNotNullComponent = array_values(array_slice($this->forms[$lang], -count($notNullTimeComponents))); | |
$interval[] = $this->getFormattedTime($lang, $notNullTimeComponents[$i], $formForNotNullComponent[$i]); | |
} | |
} | |
return implode($separator, $interval); | |
} | |
/** | |
* Format date string | |
* | |
* @param string $lang | |
* @param $number | |
* @param $wordForms | |
* | |
* @return string | |
*/ | |
private function getFormattedTime($lang, $number, $wordForms) | |
{ | |
return $this->pluralRules($lang, $number, $wordForms); | |
} | |
/** | |
* @param $timestamp | |
* | |
* @return bool | |
*/ | |
private function isValidTimeStamp($timestamp) | |
{ | |
if (ctype_digit($timestamp) && strtotime(date('Y-m-d H:i:s', $timestamp)) === (int) $timestamp) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @param $dateString | |
* | |
* @return int | |
* | |
* @throws \Exception | |
*/ | |
private function getTimestamp($dateString) | |
{ | |
if (!$this->isValidTimeStamp(strtotime($dateString))) { | |
throw new \Exception('Not valid date string.'); | |
} | |
return strtotime($dateString); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment