DateTime
* recreate date functions from javascript in new class DateTime * move date and time functions from Util to new class * fixes various cooldown messages for account recovery
This commit is contained in:
parent
1fe3690244
commit
f5654ae21f
36 changed files with 409 additions and 188 deletions
218
localization/datetime.class.php
Normal file
218
localization/datetime.class.php
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class DateTime extends \DateTimeImmutable
|
||||
{
|
||||
// in msec yr mo w d h m s ms
|
||||
private const /* array */ RANGE = [31557600000, 2629800000, 604800000, 86400000, 3600000, 60000, 1000, 1];
|
||||
private const /* string */ NBSP = "\u{00A0}"; // \u00A0 is usable by js
|
||||
|
||||
public function __construct(int $seconds = 0)
|
||||
{
|
||||
$datetime = $seconds ? date(DATE_ATOM, $seconds) : 'now';
|
||||
parent::__construct($datetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adaptive, human-readable format of a date
|
||||
* exact date if larger than 1 month
|
||||
* relative days/time if smaller than 1 month
|
||||
*
|
||||
* @param int $timestamp unix timestamp to display
|
||||
* @param bool $withTime [optional] append time on exact dates
|
||||
* @return string adaptive date/time string
|
||||
*/
|
||||
public function formatDate(int $timestamp, bool $withTime = false) : string
|
||||
{
|
||||
$txt = '';
|
||||
$elapsed = abs($this->getTimestamp() - $timestamp);
|
||||
|
||||
$today = new DateTime();
|
||||
$eventDay = new DateTime(time() - $elapsed);
|
||||
|
||||
$todayMidnight = $today->setTime(0, 0);
|
||||
$eventDayMidnight = $eventDay->setTime(0, 0);
|
||||
|
||||
$delta = $todayMidnight->diff($eventDayMidnight, true)->days;
|
||||
|
||||
if ($elapsed >= 2592000) /* More than a month ago */
|
||||
$txt = Lang::main('date_on') . $eventDay->formatDateSimple($withTime);
|
||||
else if ($delta > 1)
|
||||
$txt = Lang::main('ddaysago', [$delta]);
|
||||
else if ($elapsed >= 43200)
|
||||
{
|
||||
if ($today->format('j') == $eventDay->format('j'))
|
||||
$txt = Lang::main('today');
|
||||
else
|
||||
$txt = Lang::main('yesterday');
|
||||
|
||||
$txt = $eventDay->formatTimeSimple($txt);
|
||||
}
|
||||
else /* Less than 12 hours ago */
|
||||
$txt = Lang::main('date_ago', [self::formatTimeElapsed($elapsed * 1000)]);
|
||||
|
||||
return $txt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable format of a date. Optionally append time of day.
|
||||
*
|
||||
* @param bool $withTime [optional] affixes day time
|
||||
* @return string a formatted date string.
|
||||
*/
|
||||
public function formatDateSimple(bool $withTime = false) : string
|
||||
{
|
||||
$txt = '';
|
||||
$day = $this->format('d');
|
||||
$month = $this->format('m');
|
||||
$year = $this->format('Y');
|
||||
|
||||
if ($year <= 1970)
|
||||
$txt .= Lang::main('unknowndate_stc');
|
||||
else
|
||||
$txt .= Lang::main('date_simple', [$day, $month, $year]);
|
||||
|
||||
if ($withTime)
|
||||
$txt = $this->formatTimeSimple($txt);
|
||||
|
||||
return $txt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable format of the time of day.
|
||||
*
|
||||
* @param string $txt [optional] text to affeix the day time to
|
||||
* @param bool $noPrefix [optional] don't use " at " to affix time of day to $txt
|
||||
* @return string a formatted time of day string.
|
||||
*/
|
||||
public function formatTimeSimple(string $txt = '', bool $noPrefix = false) : string
|
||||
{
|
||||
$hours = $this->format('G');
|
||||
$minutes = $this->format('i');
|
||||
|
||||
$txt .= ($noPrefix ? ' ' : Lang::main('date_at'));
|
||||
|
||||
if ($hours == 12)
|
||||
$txt .= Lang::main('noon');
|
||||
else if ($hours == 0)
|
||||
$txt .= Lang::main('midnight');
|
||||
else if ($hours > 12)
|
||||
$txt .= ($hours - 12) . ':' . $minutes . ' ' . Lang::main('pm');
|
||||
else
|
||||
$txt .= $hours . ':' . $minutes . ' ' . Lang::main('am');
|
||||
|
||||
return $txt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate component values from timestamp
|
||||
*
|
||||
* @param int $msec time in milliseconds to parse
|
||||
* @return int[] [msec, sec, min, hr, day]
|
||||
*/
|
||||
public static function parse(int $msec) : array
|
||||
{
|
||||
$time = [0, 0, 0, 0, 0];
|
||||
$msec = abs($msec);
|
||||
|
||||
for ($i = 3; $i < count(self::RANGE); ++$i)
|
||||
{
|
||||
if ($msec < self::RANGE[$i])
|
||||
continue;
|
||||
|
||||
$time[7 - $i] = intVal($msec / self::RANGE[$i]);
|
||||
$msec %= self::RANGE[$i];
|
||||
}
|
||||
|
||||
return $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable longform format of a timespan.
|
||||
*
|
||||
* @param int $delay time in milliseconds to format
|
||||
* @return string a formatted time string. If an error occured "n/a" (localized) is returned
|
||||
*/
|
||||
public static function formatTimeElapsedFloat(int $delay) : string
|
||||
{
|
||||
$delay = max($delay, 1);
|
||||
|
||||
for ($i = 0; $i < count(self::RANGE); ++$i)
|
||||
{
|
||||
if ($delay < self::RANGE[$i])
|
||||
continue;
|
||||
|
||||
$v = round($delay / self::RANGE[$i], 2);
|
||||
return $v . self::NBSP . Lang::timeUnits($v === 1.0 ? 'sg' : 'pl', $i);
|
||||
}
|
||||
|
||||
return Lang::main('n_a');
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable format of a timespan.
|
||||
*
|
||||
* @param int $delay time in milliseconds to format
|
||||
* @param int $maxRange [optional] time unit index - 0 (year) ... 7 (milliseconds)
|
||||
* @return string a formatted time string. If an error occured "n/a" (localized) is returned
|
||||
*/
|
||||
public static function formatTimeElapsed(int $delay, int $maxRange = 3) : string
|
||||
{
|
||||
if ($maxRange > 7 || $maxRange < 0)
|
||||
$maxRange = 3; // default: days
|
||||
|
||||
$subunit = [1, 3, 3, -1, 5, -1, 7, -1];
|
||||
$delay = max($delay, 1);
|
||||
|
||||
for ($i = $maxRange; $i < count(self::RANGE); ++$i)
|
||||
{
|
||||
if ($delay >= self::RANGE[$i])
|
||||
{
|
||||
$i1 = $i;
|
||||
$v1 = floor($delay / self::RANGE[$i1]);
|
||||
|
||||
if ($subunit[$i1] != -1)
|
||||
{
|
||||
$i2 = $subunit[$i1];
|
||||
$delay %= self::RANGE[$i1];
|
||||
$v2 = floor($delay / self::RANGE[$i2]);
|
||||
|
||||
if ($v2 > 0)
|
||||
return self::OMG($v1, $i1, true) . self::NBSP . self::OMG($v2, $i2, true);
|
||||
}
|
||||
|
||||
return self::OMG($v1, $i1, false);
|
||||
}
|
||||
}
|
||||
|
||||
return Lang::main('n_a');
|
||||
}
|
||||
|
||||
/**
|
||||
* internal number formatter
|
||||
*
|
||||
* @param int $value unit value
|
||||
* @param int $unit time unit index 0 (year) ... 7 (milliseconds)
|
||||
* @param bool $abbrv use abbreviation
|
||||
* @return string value + unit
|
||||
*/
|
||||
private static function OMG(int $value, int $unit, bool $abbrv) : string
|
||||
{
|
||||
if ($abbrv && !Lang::timeUnits('ab', $unit))
|
||||
$abbrv = false;
|
||||
|
||||
return $value .= self::NBSP . match(true)
|
||||
{
|
||||
$abbrv => Lang::timeUnits('ab', $unit),
|
||||
$value == 1 => Lang::timeUnits('sg', $unit),
|
||||
default => Lang::timeUnits('pl', $unit)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -535,7 +535,7 @@ class Lang
|
|||
if ($msec < 0)
|
||||
$msec = 0;
|
||||
|
||||
$time = Util::parseTime($msec); // [$ms, $s, $m, $h, $d]
|
||||
$time = DateTime::parse($msec); // [$ms, $s, $m, $h, $d]
|
||||
$mult = [0, 1000, 60, 60, 24];
|
||||
$total = 0;
|
||||
$ref = [];
|
||||
|
|
@ -552,33 +552,22 @@ class Lang
|
|||
if (!$msec)
|
||||
return self::vspf($ref[0], [0]);
|
||||
|
||||
if ($concat)
|
||||
{
|
||||
for ($i = 4; $i > 0; $i--)
|
||||
{
|
||||
$total += $time[$i];
|
||||
if (isset($ref[$i]) && ($total || ($i == 1 && !$result)))
|
||||
{
|
||||
$result[] = self::vspf($ref[$i], [$total]);
|
||||
$total = 0;
|
||||
}
|
||||
else
|
||||
$total *= $mult[$i];
|
||||
}
|
||||
|
||||
return implode(', ', $result);
|
||||
}
|
||||
|
||||
for ($i = 4; $i > 0; $i--)
|
||||
{
|
||||
$total += $time[$i];
|
||||
if (isset($ref[$i]) && ($total || $i == 1))
|
||||
return self::vspf($ref[$i], [$total + ($time[$i-1] ?? 0) / $mult[$i]]);
|
||||
if (isset($ref[$i]) && ($total || ($i == 1 && !$result)))
|
||||
{
|
||||
if (!$concat)
|
||||
return self::vspf($ref[$i], [$total + ($time[$i-1] ?? 0) / $mult[$i]]);
|
||||
|
||||
$result[] = self::vspf($ref[$i], [$total]);
|
||||
$total = 0;
|
||||
}
|
||||
else
|
||||
$total *= $mult[$i];
|
||||
}
|
||||
|
||||
return '';
|
||||
return implode(', ', $result);
|
||||
}
|
||||
|
||||
private static function vspf(null|array|string $var, array $args = []) : null|array|string
|
||||
|
|
|
|||
|
|
@ -134,8 +134,25 @@ $lang = array(
|
|||
'dateFmtShort' => "d.m.Y",
|
||||
'dateFmtLong' => "d.m.Y \u\m H:i",
|
||||
'dateFmtIntl' => "d. MMMM y",
|
||||
'timeAgo' => 'vor %s',
|
||||
'nfSeparators' => ['.', ','],
|
||||
'n_a' => "n. v.",
|
||||
|
||||
// date time
|
||||
'date' => "Datum",
|
||||
'date_colon' => "Datum: ",
|
||||
'date_on' => "am ",
|
||||
'date_ago' => "vor %s",
|
||||
'date_at' => " um ",
|
||||
'date_to' => " bis ",
|
||||
'date_simple' => '%1$d.%2$d.%3$d',
|
||||
'unknowndate' => "Unbekanntes Datum",
|
||||
'ddaysago' => "vor %d Tagen",
|
||||
'today' => "heute",
|
||||
'yesterday' => "gestern",
|
||||
'noon' => "Mittag",
|
||||
'midnight' => "Mitternacht",
|
||||
'am' => "vormittags",
|
||||
'pm' => "nachmittags",
|
||||
|
||||
// error
|
||||
'intError' => "Ein interner Fehler ist aufgetreten.",
|
||||
|
|
@ -1656,7 +1673,6 @@ $lang = array(
|
|||
'_rankRange' => "Rang: %d - %d",
|
||||
'_showXmore' => "Zeige %d weitere",
|
||||
|
||||
'n_a' => "n. v.",
|
||||
'normal' => "Normal",
|
||||
'special' => "Besonders",
|
||||
|
||||
|
|
|
|||
|
|
@ -134,8 +134,25 @@ $lang = array(
|
|||
'dateFmtShort' => "Y/m/d",
|
||||
'dateFmtLong' => "Y/m/d \a\\t g:i A",
|
||||
'dateFmtIntl' => "MMMM d, y",
|
||||
'timeAgo' => "%s ago",
|
||||
'nfSeparators' => [',', '.'],
|
||||
'n_a' => "n/a",
|
||||
|
||||
// date time
|
||||
'date' => "Date",
|
||||
'date_colon' => "Date: ",
|
||||
'date_on' => "on ",
|
||||
'date_ago' => "%s ago",
|
||||
'date_at' => " at ",
|
||||
'date_to' => " to ",
|
||||
'date_simple' => '%2$d/%1$d/%3$d',
|
||||
'unknowndate' => "Unknown date",
|
||||
'ddaysago' => "%d days ago",
|
||||
'today' => "today",
|
||||
'yesterday' => "yesterday",
|
||||
'noon' => "noon",
|
||||
'midnight' => "midnight",
|
||||
'am' => "AM",
|
||||
'pm' => "PM",
|
||||
|
||||
// error
|
||||
'intError' => "An internal error has occurred.",
|
||||
|
|
@ -1656,7 +1673,6 @@ $lang = array(
|
|||
'_rankRange' => "Rank: %d - %d",
|
||||
'_showXmore' => "Show %d More",
|
||||
|
||||
'n_a' => "n/a",
|
||||
'normal' => "Normal",
|
||||
'special' => "Special",
|
||||
|
||||
|
|
|
|||
|
|
@ -134,8 +134,25 @@ $lang = array(
|
|||
'dateFmtShort' => "d/m/Y",
|
||||
'dateFmtLong' => "d/m/Y \a \l\a\s g:i A",
|
||||
'dateFmtIntl' => "d 'de' MMMM 'de' y",
|
||||
'timeAgo' => 'hace %s',
|
||||
'nfSeparators' => ['.', ','],
|
||||
'n_a' => "n/d",
|
||||
|
||||
// date time
|
||||
'date' => "Fecha",
|
||||
'date_colon' => "Fecha: ",
|
||||
'date_on' => "el ",
|
||||
'date_ago' => "hace %s",
|
||||
'date_at' => " a las ",
|
||||
'date_to' => " al ",
|
||||
'date_simple' => '%1$d/%2$d/%3$d',
|
||||
'unknowndate' => "Fecha desconocida",
|
||||
'ddaysago' => "Hace %d días",
|
||||
'today' => "hoy",
|
||||
'yesterday' => "ayer",
|
||||
'noon' => "medio día",
|
||||
'midnight' => "medianoche",
|
||||
'am' => "a.m.",
|
||||
'pm' => "p.m.",
|
||||
|
||||
// error
|
||||
'intError' => "Un error interno ha ocurrido.",
|
||||
|
|
@ -1656,7 +1673,6 @@ $lang = array(
|
|||
'_rankRange' => "Rango: %d - %d",
|
||||
'_showXmore' => "Mostrar %d más",
|
||||
|
||||
'n_a' => "n/d",
|
||||
'normal' => "Normal",
|
||||
'special' => "Especial",
|
||||
|
||||
|
|
|
|||
|
|
@ -134,8 +134,25 @@ $lang = array(
|
|||
'dateFmtShort' => "Y-m-d",
|
||||
'dateFmtLong' => "Y-m-d à g:i A",
|
||||
'dateFmtIntl' => "d MMMM y",
|
||||
'timeAgo' => 'il y a %s',
|
||||
'nfSeparators' => [' ', ','],
|
||||
'n_a' => "n/d",
|
||||
|
||||
// date time
|
||||
'date' => "Date",
|
||||
'date_colon' => "Date : ",
|
||||
'date_on' => "le ",
|
||||
'date_ago' => "il y a %s",
|
||||
'date_at' => " à ",
|
||||
'date_to' => " à ",
|
||||
'date_simple' => '%1$d-%2$d-%3$d',
|
||||
'unknowndate' => "Date inconnue",
|
||||
'ddaysago' => "%d jours avant",
|
||||
'today' => "aujourd'hui",
|
||||
'yesterday' => "hier",
|
||||
'noon' => "midi",
|
||||
'midnight' => "minuit",
|
||||
'am' => "AM",
|
||||
'pm' => "PM",
|
||||
|
||||
// error
|
||||
'intError' => "[An internal error occured.]",
|
||||
|
|
@ -1656,7 +1673,6 @@ $lang = array(
|
|||
'_rankRange' => "Rang : %d - %d",
|
||||
'_showXmore' => "En afficher %d de plus",
|
||||
|
||||
'n_a' => "n/d",
|
||||
'normal' => "Standard",
|
||||
'special' => "Spécial",
|
||||
|
||||
|
|
|
|||
|
|
@ -134,8 +134,25 @@ $lang = array(
|
|||
'dateFmtShort' => "Y-m-d",
|
||||
'dateFmtLong' => "Y-m-d в g:i A",
|
||||
'dateFmtIntl' => "d MMMM y г.",
|
||||
'timeAgo' => '%s назад',
|
||||
'nfSeparators' => [' ', ','],
|
||||
'n_a' => "нет",
|
||||
|
||||
// date time
|
||||
'date' => "По дате",
|
||||
'date_colon' => "Дата: ",
|
||||
'date_on' => "на ",
|
||||
'date_ago' => "%s назад",
|
||||
'date_at' => " в ",
|
||||
'date_to' => " в ",
|
||||
'date_simple' => '%1$d.%2$d.%3$d',
|
||||
'unknowndate' => "Неизвестная дата",
|
||||
'ddaysago' => "%d дней назад",
|
||||
'today' => "сегодня",
|
||||
'yesterday' => "вчера",
|
||||
'noon' => "полдень",
|
||||
'midnight' => "полночь",
|
||||
'am' => "a.m.",
|
||||
'pm' => "p.m.",
|
||||
|
||||
// error
|
||||
'intError' => "[An internal error occured.]",
|
||||
|
|
@ -1656,7 +1673,6 @@ $lang = array(
|
|||
'_rankRange' => "Ранг: %d - %d",
|
||||
'_showXmore' => "Показать на %d больше",
|
||||
|
||||
'n_a' => "нет",
|
||||
'normal' => "Обычный",
|
||||
'special' => "Особый",
|
||||
|
||||
|
|
|
|||
|
|
@ -134,8 +134,25 @@ $lang = array(
|
|||
'dateFmtShort' => "Y/m/d",
|
||||
'dateFmtLong' => "Y/m/d \a\\t g:i A",
|
||||
'dateFmtIntl' => "y年M月d日",
|
||||
'timeAgo' => '%s之前',
|
||||
'nfSeparators' => [',', '.'],
|
||||
'n_a' => "n/a",
|
||||
|
||||
// date time
|
||||
'date' => "日期",
|
||||
'date_colon' => "日期:",
|
||||
'date_on' => "在 ",
|
||||
'date_ago' => "%s前",
|
||||
'date_at' => "于",
|
||||
'date_to' => "至",
|
||||
'date_simple' => '%3$d/%2$d/%1$d',
|
||||
'unknowndate' => "未知日期",
|
||||
'ddaysago' => "%d天前",
|
||||
'today' => "今日",
|
||||
'yesterday' => "昨天",
|
||||
'noon' => "正午",
|
||||
'midnight' => "午夜",
|
||||
'am' => "AM",
|
||||
'pm' => "PM",
|
||||
|
||||
// error
|
||||
'intError' => "发生内部错误。",
|
||||
|
|
@ -1656,7 +1673,6 @@ $lang = array(
|
|||
'_rankRange' => "排名: %d - %d",
|
||||
'_showXmore' => "[Show %d More]",
|
||||
|
||||
'n_a' => "n/a",
|
||||
'normal' => "普通",
|
||||
'special' => "特殊",
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue