Почти в каждом своем проекте я использую набор функций, которые делают сайт чуточку приятнее для глаза и удобнее для восприятия. Эти функции я частично позаимствовал в разных местах и частично написал сам. Наверняка, многие используют подобные, но я решил все же поделиться — возможно, кому-то они будут полезны.
Они умеют склонять существительные по числовому признаку, выводить дату с нормальными русскими названиями месяцев и выводить дату в удобочитаемом человекопонятном виде (вчера, позавчера, 2 дня 3 часа и 2 минуты назад, через 1 год и 2 месяца и т.д.).
Использовать их можно примерно так:
Это вернет примерно такой результат:
(Хабр обрезает тег <acronym>)
И вот так:
Это вернет:
Собственно, функции:
Надеюсь, кому-нибудь они пригодятся.
Они умеют склонять существительные по числовому признаку, выводить дату с нормальными русскими названиями месяцев и выводить дату в удобочитаемом человекопонятном виде (вчера, позавчера, 2 дня 3 часа и 2 минуты назад, через 1 год и 2 месяца и т.д.).
Использовать их можно примерно так:
<acrnonym title="<?php print r_date($timestamp, 'j M Y в H:i', false); ?>"><?php print human_date($timestamp, 2, false);?></acronym>
<acrnonym title="<?php print r_date($timestamp, 'j M Y в H:i'); ?>"><?php print human_date($timestamp);?></acronym>
Это вернет примерно такой результат:
<acrnonym title="2 января 2009 в 23:39">1 день назад</acronym>
<acrnonym title="2 января в 23:39">Вчера</acronym>
(Хабр обрезает тег <acronym>)
И вот так:
<?php
$count = 10;
printf('%d %s', $count, declension($count, array('комментарий', 'комментария', 'комментариев')));
?>
Это вернет:
10 комментариев
Собственно, функции:
<?php
/**
* Склонение существительных по числовому признаку
*
* @var integer Число, по которому производится склонение
* @var array Массив форм существительного
* @return string Существительное в нужной форме
*
* Например:
* $count = 10;
* sprintf('%d %s', $count, declension($count, array('комментарий', 'комментария', 'комментариев')));
*
* Возвращает:
* 10 комментариев
*/
function declension($number, $words) {
$number = abs($number);
if ($number > 20) $number %= 10;
if ($number == 1) return $words[0];
if ($number >= 2 && $number <= 4) return $words[1];
return $words[2];
}
/**
* Приводит дату к заданному формату с учетом русских названий месяцев
*
* В качестве параметров функция принимает все допустимые значения функции date(),
* но символ F заменяется на русское название месяца (вне зависимости от локали),
* а символ M — на русское название месяца в родительном падеже
*
* @var integer Unix-timestamp времени
* @var string Формат даты согласно спецификации для функции date() с учетом замены значения символов F и M
* @var boolean Флаг отсекания года, если он совпадает с текущим
* @return string Отформатированная дата
*/
function r_date($time = '', $format = 'j M Y', $cut_year = true) {
if(empty($time)) $time = time();
if($cut_year && date('Y') == date('Y', $time)) $format = preg_replace('/o|y|Y/', '', $format);
$month = abs(date('n', $time)-1);
$rus = array('января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря');
$rus2 = array('январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь');
$format = preg_replace(array("'M'", "'F'"), array($rus[$month], $rus2[$month]), $format);
return date($format, $time);
}
/**
* Выводит дату в приблизительном удобочитаемом виде (например, "2 часа и 13 минут назад")
*
* Необходимо наличие функции declension() для корректной работы
*
* @var integer Unix-timestamp времени
* @var integer Степень детализации
* @var boolean Флаг использования упрощенных названий (вчера, позавчера, послезавтра)
* @var string Формат даты с учетом замены значения символов F и M, если объявлена функция r_date()
* @return string Отформатированная дата
*/
function human_date($timestamp, $granularity = 1, $use_terms = true, $default_format = 'j M Y') {
$curtime = time();
$original = $timestamp;
$output = '';
if($curtime >= $original) {
$timestamp = abs($curtime - $original);
$tense = 'past';
} else {
$timestamp = abs($original - $curtime);
$tense = 'future';
}
$units = array('years' => 31536000,
'weeks' => 604800,
'days' => 86400,
'hours' => 3600,
'min' => 60,
'sec' => 1);
$titles = array('years' => array('год', 'года', 'лет'),
'weeks' => array('неделя', 'недели', 'недель'),
'days' => array('день', 'дня', 'дней'),
'hours' => array('час', 'часа', 'часов'),
'min' => array('минута', 'минуты', 'минут'),
'sec' => array('секунда', 'секунды', 'секунд'));
foreach ($units as $key => $value) {
if ($timestamp >= $value) {
$number = floor($timestamp / $value);
$output .= ($output ? ($granularity == 1 ? ' и ' : ' ') : '') . $number .' '. declension($number, $titles[$key]);
$timestamp %= $value;
$granularity--;
}
}
if($tense == 'future') {
$output = 'Через '.$output;
} else {
$output .= ' назад';
}
if($use_terms) {
$terms = array('Через 1 день' => 'Послезавтра',
'1 день назад' => 'Вчера',
'2 дня назад' => 'Позавчера'
);
if(isset($terms[$output])) $output = $terms[$output];
}
return $output ? $output : (function_exists('r_date') ? r_date($original, $default_format) : date($default_format, $original));
}
?>
Надеюсь, кому-нибудь они пригодятся.