Created
July 11, 2025 16:09
-
-
Save fey/39cad37efc4a8589d5ccab4d48c156b2 to your computer and use it in GitHub Desktop.
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); | |
<?php | |
declare(strict_types=1); | |
function dateFormat(DateTimeInterface $dt, string $format): string | |
{ | |
$len = strlen($format); | |
$result = ''; | |
$escape = false; | |
// Вспомогательные функции для форматирования отдельных паттернов | |
$formatters = [ | |
'yy' => fn() => substr($dt->format('Y'), -2), | |
'y' => fn() => $dt->format('Y'), | |
'MM' => fn() => $dt->format('m'), | |
'M' => fn() => (string)(int)$dt->format('m'), // без ведущего нуля | |
'dd' => fn() => $dt->format('d'), | |
'd' => fn() => (string)(int)$dt->format('d'), | |
'hh' => fn() => $dt->format('h'), | |
'h' => fn() => (string)(int)$dt->format('h'), | |
'HH' => fn() => $dt->format('H'), | |
'H' => fn() => (string)(int)$dt->format('H'), | |
'mm' => fn() => $dt->format('i'), | |
'm' => fn() => (string)(int)$dt->format('i'), | |
'ss' => fn() => $dt->format('s'), | |
's' => fn() => (string)(int)$dt->format('s'), | |
]; | |
for ($i = 0; $i < $len; $i++) { | |
$char = $format[$i]; | |
if ($escape) { | |
// Текущий символ — экранированный, просто добавляем и сбрасываем флаг | |
$result .= $char; | |
$escape = false; | |
continue; | |
} | |
if ($char === '\\') { | |
// Следующий символ экранированный | |
$escape = true; | |
continue; | |
} | |
// Попробуем проверить двухсимвольные паттерны (yy, MM, dd, hh, HH, mm, ss) | |
if ($i + 1 < $len) { | |
$pair = $char . $format[$i + 1]; | |
if (isset($formatters[$pair])) { | |
$result .= $formatters[$pair](); | |
$i++; // пропускаем следующий символ, т.к. он уже учтен | |
continue; | |
} | |
} | |
// Односимвольные паттерны | |
if (isset($formatters[$char])) { | |
$result .= $formatters[$char](); | |
} else { | |
// Просто символ без замены | |
$result .= $char; | |
} | |
} | |
return $result; | |
} | |
// Тесты | |
$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 | |
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"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment