JezK
Edit File: Date.php
<?php namespace GeminiLabs\SiteReviews\Modules; use GeminiLabs\SiteReviews\Helpers\Cast; use GeminiLabs\SiteReviews\Helpers\Str; class Date { protected array $timePeriods; public function __construct() { $this->timePeriods = [ [ /* translators: %s: number of years */ 'future' => _nx_noop('in %s year', 'in %s years', '%s: amount of time', 'site-reviews'), /* translators: %s: number of years */ 'name' => _nx_noop('%s year', '%s years', '%s: amount of time', 'site-reviews'), /* translators: %s: number of years */ 'past' => _nx_noop('%s year ago', '%s years ago', '%s: amount of time', 'site-reviews'), 'seconds' => \YEAR_IN_SECONDS, ], [ /* translators: %s: number of months */ 'future' => _nx_noop('in %s month', 'in %s months', '%s: amount of time', 'site-reviews'), /* translators: %s: number of months */ 'name' => _nx_noop('%s month', '%s months', '%s: amount of time', 'site-reviews'), /* translators: %s: number of months */ 'past' => _nx_noop('%s month ago', '%s months ago', '%s: amount of time', 'site-reviews'), 'seconds' => \MONTH_IN_SECONDS, ], [ /* translators: %s: number of weeks */ 'future' => _nx_noop('in %s week', 'in %s weeks', '%s: amount of time', 'site-reviews'), /* translators: %s: number of weeks */ 'name' => _nx_noop('%s week', '%s weeks', '%s: amount of time', 'site-reviews'), /* translators: %s: number of weeks */ 'past' => _nx_noop('%s week ago', '%s weeks ago', '%s: amount of time', 'site-reviews'), 'seconds' => \WEEK_IN_SECONDS, ], [ /* translators: %s: number of days */ 'future' => _nx_noop('in %s day', 'in %s days', '%s: amount of time', 'site-reviews'), /* translators: %s: number of days */ 'name' => _nx_noop('%s day', '%s days', '%s: amount of time', 'site-reviews'), /* translators: %s: number of days */ 'past' => _nx_noop('%s day ago', '%s days ago', '%s: amount of time', 'site-reviews'), 'seconds' => \DAY_IN_SECONDS, ], [ /* translators: %s: number of hours */ 'future' => _nx_noop('in %s hour', 'in %s hours', '%s: amount of time', 'site-reviews'), /* translators: %s: number of hours */ 'name' => _nx_noop('%s hour', '%s hours', '%s: amount of time', 'site-reviews'), /* translators: %s: number of hours */ 'past' => _nx_noop('%s hour ago', '%s hours ago', '%s: amount of time', 'site-reviews'), 'seconds' => \HOUR_IN_SECONDS, ], [ /* translators: %s: number of minutes */ 'future' => _nx_noop('in %s minute', 'in %s minutes', '%s: amount of time', 'site-reviews'), /* translators: %s: number of minutes */ 'name' => _nx_noop('%s minute', '%s minutes', '%s: amount of time', 'site-reviews'), /* translators: %s: number of minutes */ 'past' => _nx_noop('%s minute ago', '%s minutes ago', '%s: amount of time', 'site-reviews'), 'seconds' => \MINUTE_IN_SECONDS, ], [ /* translators: %s: number of seconds */ 'future' => _nx_noop('in %s second', 'in %s seconds', '%s: amount of time', 'site-reviews'), /* translators: %s: number of seconds */ 'name' => _nx_noop('%s second', '%s seconds', '%s: amount of time', 'site-reviews'), /* translators: %s: number of seconds */ 'past' => _nx_noop('%s second ago', '%s seconds ago', '%s: amount of time', 'site-reviews'), 'seconds' => 1, ], ]; } public function interval(int $seconds, string $tense = '', int $levels = 2): string { $tense = Str::restrictTo(['future', 'past'], $tense, ''); if ($seconds <= 0) { // make-pot cannot parse a parenthesized expression argument; the // number is hoisted so the call stays extractable. $number = (int) ('past' === $tense); return _nx('A moment ago', 'Now', $number, 'The past and present/future tense of now', 'site-reviews'); } $output = []; for ( $index = 0, $level = 0; $index < count($this->timePeriods) && $seconds > 0 && $level < $levels; ++$index ) { $unit = intval(floor($seconds / $this->timePeriods[$index]['seconds'])); if ($unit > 0) { ++$level; $seconds -= $unit * $this->timePeriods[$index]['seconds']; $output[] = $this->intervalLevel(compact('index', 'level', 'levels', 'seconds', 'tense', 'unit')); } } return implode(', ', $output); } /** * @param mixed $date */ public function isDate($date, string $format = 'Y-m-d H:i:s'): bool { $datetime = \DateTime::createFromFormat($format, Cast::toString($date)); return $datetime && $date === $datetime->format($format); } /** * @param mixed $date */ public function isThisMonth($date): bool { return $this->isValid($date) ? date('Y', $this->toTimestamp($date)) === date('Y') : false; } /** * @param mixed $date */ public function isThisYear($date): bool { return $this->isValid($date) ? date('m', $this->toTimestamp($date)) === date('m') : false; } /** * @param mixed $timestamp */ public function isTimestamp($timestamp): bool { $timestamp = Cast::toString($timestamp); if (!ctype_digit($timestamp) || 10 !== strlen($timestamp)) { return false; } $datetime = \DateTime::createFromFormat('U', $timestamp); if (false === $datetime) { return false; } return $timestamp === $datetime->format('U'); } /** * @param mixed $date */ public function isValid($date, string $format = 'Y-m-d H:i:s'): bool { return $this->isDate($date, $format) || $this->isTimestamp($date); } /** * @param mixed $date */ public function localized($date, string $fallback = ''): string { return $this->isValid($date) ? date_i18n('Y-m-d H:i:s', $date) : $fallback; } /** * @param mixed $date */ public function relative($date): string { $seconds = time() - $this->toTimestamp($date); return $this->interval($seconds, 'past', 1); } /** * @param mixed $date */ public function toTimestamp($date): int { if ($this->isTimestamp($date)) { return (int) $date; } if ($this->isDate($date)) { return strtotime($date); } return time(); // fallback to the current time } protected function intervalLevel(array $args): string { $keys = ['index', 'level', 'levels', 'seconds', 'tense', 'unit']; $args = shortcode_atts(array_fill_keys($keys, 0), $args); extract($args); if (1 === $level && 'future' === $tense) { // @phpstan-ignore-line $string = $this->timePeriods[$index]['future']; } elseif (($level === $levels || $seconds <= 0) && 'past' === $tense) { $string = $this->timePeriods[$index]['past']; } else { $string = $this->timePeriods[$index]['name']; } return sprintf(translate_nooped_plural($string, $unit, 'site-reviews'), $unit); } }