Skip to content

Instantly share code, notes, and snippets.

@dimd13
Forked from Aleksandr-ru/DateTimeRu.php
Created October 22, 2020 15:38
Show Gist options
  • Select an option

  • Save dimd13/fc29d693d9165d97479dda144b942f45 to your computer and use it in GitHub Desktop.

Select an option

Save dimd13/fc29d693d9165d97479dda144b942f45 to your computer and use it in GitHub Desktop.

Revisions

  1. @Aleksandr-ru Aleksandr-ru created this gist Jan 24, 2017.
    108 changes: 108 additions & 0 deletions DateTimeRu.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    <?php
    /**
    * Русскоязычный DateTime с дополнениями
    *
    * @author Aleksandr <aleksandr@aleksandr.ru>
    * @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);
    }
    }