Skip to content

Instantly share code, notes, and snippets.

@Aleksandr-ru
Created January 24, 2017 13:49
Show Gist options
  • Save Aleksandr-ru/49c3eccfd7e559276f19b93dfc29320d to your computer and use it in GitHub Desktop.
Save Aleksandr-ru/49c3eccfd7e559276f19b93dfc29320d to your computer and use it in GitHub Desktop.
Русскоязычный DateTime с дополнениями
<?php
/**
* Русскоязычный DateTime с дополнениями
*
* @author Aleksandr <[email protected]>
* @link http://www.aleksandr.ru author's website
*/
class DateTimeRu extends DateTime
{
protected static $FN = array(1=>"Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь");
protected static $F = array(1=>"Января", "Февраля", "Марта", "Апреля", "Мая", "Июня", "Июля", "Августа", "Сентября", "Октября", "Ноября", "Декабря");
protected static $M = array(1=>"Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек");
protected static $l = array("Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота");
protected static $D = array("Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб");
protected static $timeStrFormat = array(
// будущее
0 => array(
'y' => array('Более чем через год', 'Более чем через год', 'Более чем через год'),
'm' => array('Через месяц', 'Через %m месяца', 'Через %m месяцев'),
'd' => array('Завтра', 'Через %d дня', 'Через %d дней'),
'h' => array('Через час', 'Через %h часа', 'Через %h часов'),
'i' => array('Через минуту', 'Через %i минуты', 'Через %i минут'),
's' => array('Через секунду', 'Через %s секунды', 'Через %s секунд'),
),
// прошлое
1 => array(
'y' => array('Более года назад', 'Более года назад', 'Более года назад'),
'm' => array('Месяц назад', '%m месяца назад', '%m месяцев назад'),
'd' => array('Вчера', '%d дня назад', '%d дней назад'),
'h' => array('Час назад', '%h часа назад', '%h часов назад'),
'i' => array('Минуту назад', '%h минуты назад', '%h минут назад'),
's' => array('Секунду назад', '%s секунды назад', '%s секунд назад'),
),
// сейчас
'now' => 'Сейчас'
);
/**
* Форматировать дату/время
* @param string $format
* @param bool $nominativeMonth месяц в именительном падеже
* @return string
*/
function format($format, $nominativeMonth = FALSE)
{
$t = $this->getTimestamp();
$n = date('n', $t); // Порядковый номер месяца без ведущего нуля от 1 до 12
$w = date('w', $t); // Порядковый номер дня недели от 0 (воскресенье) до 6 (суббота)
$format = str_replace('F', $nominativeMonth ? static::$FN[$n] : static::$F[$n], $format);
$format = str_replace('M', static::$M[$n], $format);
$format = str_replace('l', static::$l[$w], $format);
$format = str_replace('D', static::$D[$w], $format);
return parent::format($format);
}
/**
* Получить красивую строку раницы во времени от текущего
* @param int $skipSeconds количество секунд, менее которого приравнивается к 'сейчас'
* @return string например '15 минут назад'
*/
function getTimeDiffStr($skipSeconds = 60)
{
$dt = new DateTime();
$diff = $dt->diff($this);
// $diff->invert
// Принимает 1, если интервал представляет отрицательный период времени и 0 в противном случае.
if(static::DateIntervalToSeconds($diff) > $skipSeconds) {
if($diff->y) return $diff->format(static::morphEnding($diff->y, static::$timeStrFormat[$diff->invert]['y']));
if($diff->m) return $diff->format(static::morphEnding($diff->m, static::$timeStrFormat[$diff->invert]['m']));
if($diff->d) return $diff->format(static::morphEnding($diff->d, static::$timeStrFormat[$diff->invert]['d']));
if($diff->h) return $diff->format(static::morphEnding($diff->h, static::$timeStrFormat[$diff->invert]['h']));
if($diff->i) return $diff->format(static::morphEnding($diff->i, static::$timeStrFormat[$diff->invert]['i']));
if($diff->s) return $diff->format(static::morphEnding($diff->s, static::$timeStrFormat[$diff->invert]['s']));
}
return $diff->format(static::$timeStrFormat['now']);
}
/**
* морфологическое окончание
* @param int $n количество
* @param array $titles = ['1 яблоко', '2 яблока', '5 яблок']
* @return string
*/
static function morphEnding($n, $titles)
{
$cases = array(2, 0, 1, 1, 1, 2);
return $titles[($n % 100 > 4 && $n % 100 < 20) ? 2 : $cases[min($n % 10, 5)]];
}
/**
* Keep in mind that a year is seen in this class as 365 days, and a month is seen as 30 days.
* It is not possible to calculate how many days are in a given year or month without a point of reference in time.
* @see http://php.net/manual/ru/dateinterval.format.php#102271
* @param DateInterval $di
* @return int
*/
static function DateIntervalToSeconds($di)
{
return ($di->y * 365 * 24 * 60 * 60) +
($di->m * 30 * 24 * 60 * 60) +
($di->d * 24 * 60 * 60) +
($di->h * 60 * 60) +
($di->i * 60) +
($di->s);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment