Created
July 11, 2025 16:02
-
-
Save fey/cf87a900d8c192ace66d19afb8904784 to your computer and use it in GitHub Desktop.
Custom date time format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
// Написать функцию с сигнатурой | |
// function dateFormat(DateTimeInterface $dt, string $format): string | |
// $date = new DateTime('2025-06-03 15:07:09'); | |
// echo dateFormat($date, 'y-M-d H:mm:ss') . PHP_EOL; // 2025-6-3 15:07:09 | |
// echo dateFormat($date, 'yy \yy\y') . PHP_EOL; // 25 y2025y | |
// echo dateFormat($date, 'H\H:mm\m:ss hh\:m:s') . PHP_EOL; // 15H:07m:09 03\:7:9 | |
// где $format это формат даты включающий следующие спецсимволы: | |
// y - Полное числовое представление года, не менее 4 цифр: 2000, 2025 и т.д. | |
// yy - Две последние цифры года с дополнением нулями, если необходимо: 99, 05 и т.д. | |
// M - Порядковый номер месяца без ведущего нуля: от 1 до 12. | |
// MM - Порядковый номер месяца с ведущим нулём: от 01 до 12. | |
// d - День месяца без ведущего нуля: от 1 до 31. | |
// dd - День месяца, 2 цифры с ведущим нулём: от 01 до 31. | |
// h - Часы в 12-часовом формате без ведущего нуля: от 1 до 12. | |
// hh - Часы в 12-часовом формате с ведущим нулём: от 01 до 12. | |
// H - Часы в 24-часовом формате без ведущего нуля: от 0 до 23. | |
// HH - Часы в 24-часовом формате с ведущим нулём: от 00 до 23. | |
// m - Минуты без ведущего нуля: от 0 до 59. | |
// mm - Минуты с ведущим нулём от 00 до 59. | |
// s - Секунды без ведущего нуля: от 0 до 59. | |
// ss - Секунды с ведущим нулём: от 00 до 59. | |
// Примечание: если строка формата содержит символы, совпадающие с вышеперечисленными, | |
// но не являющиеся параметрами форматирования, | |
// то их следует экранировать с помощью символа обратного слэша "\". | |
function dateFormat(DateTimeInterface $dt, string $format): string | |
{ | |
// Сопоставление ключ-формат => ключ-формат DateTime | |
// Порядок важен | |
$formatCharsMap = [ | |
// yy - Две последние цифры года с дополнением нулями, если необходимо: 99, 05 и т.д. | |
'yy' => 'y', | |
// y - Полное числовое представление года, не менее 4 цифр: 2000, 2025 и т.д. | |
'y' => 'o', | |
// MM - Порядковый номер месяца с ведущим нулём: от 01 до 12. | |
'MM' => 'm', | |
// M - Порядковый номер месяца без ведущего нуля: от 1 до 12. | |
'M' => 'n', | |
// dd - День месяца, 2 цифры с ведущим нулём: от 01 до 31. | |
'dd' => 'd', | |
// d - День месяца без ведущего нуля: от 1 до 31. | |
'd' => 'j', | |
// hh - Часы в 12-часовом формате с ведущим нулём: от 01 до 12. | |
'hh' => 'h', | |
// h - Часы в 12-часовом формате без ведущего нуля: от 1 до 12. | |
'h' => 'g', | |
// H - Часы в 24-часовом формате без ведущего нуля: от 0 до 23. | |
'H' => 'G', | |
// HH - Часы в 24-часовом формате с ведущим нулём: от 00 до 23. | |
'HH' => 'H', | |
// mm - Минуты с ведущим нулём от 00 до 59. | |
'mm' => 'i', | |
// m - Минуты без ведущего нуля: от 0 до 59. | |
'm' => fn (DateTime $dt) => (string) intval($dt->format('i')), | |
// ss - Секунды с ведущим нулём: от 00 до 59. | |
'ss' => 's', | |
// s - Секунды без ведущего нуля: от 0 до 59. в Datetime нет для этого формата | |
's' => fn (DateTime $dt) => (string) intval($dt->format('s')), | |
]; | |
$customDtTemplates = array_keys($formatCharsMap); | |
$regexCharsTemplate = implode('|', $customDtTemplates); | |
$dtFormatRegex = "/(?<!\\\)({$regexCharsTemplate})/"; | |
$resultFormat = preg_replace_callback_array([ | |
$dtFormatRegex => static function (array $matches) use ($formatCharsMap, $dt): string { | |
$key = $matches[0]; | |
$dtTemplate = $formatCharsMap[$key]; | |
if (is_string($dtTemplate )) { | |
return $dtTemplate; | |
} | |
if (is_callable($dtTemplate)) { | |
return $dtTemplate($dt); | |
} | |
throw new RuntimeException("Unhandled dt temlate key. Given key: {$key}"); | |
}, | |
"/\\\(?![yMdHhms])/" => static fn() => '\\\\\\', | |
], $format); | |
return $dt->format($resultFormat); | |
} | |
$date = new DateTime('2025-06-03 15:07:09'); | |
test('2025-6-3 15:07:09', dateFormat($date, 'y-M-d H:mm:ss')); | |
test('15H:07m:09 03\:7:9', dateFormat($date, 'H\H:mm\m:ss hh\:m:s')); | |
test('25 y2025y', dateFormat($date, 'yy \yy\y')); | |
echo dateFormat($date, 'y-M-d H:mm:ss') . PHP_EOL; // 2025-6-3 15:07:09 | |
echo dateFormat($date, 'yy \yy\y') . PHP_EOL; // 25 y2025y | |
echo dateFormat($date, 'H\H:mm\m:ss hh\:m:s') . PHP_EOL; // 15H:07m:09 03\:7:9 | |
function test($expected, $actual): void | |
{ | |
try { | |
assert($expected === $actual); | |
} catch (\AssertionError) { | |
echo "failed tests. Expected === actual. {$expected} === {$actual}\n"; | |
exit(1); | |
} | |
echo "Ok!\n"; | |
} |
Comments are disabled for this gist.