Skip to content

Instantly share code, notes, and snippets.

@fey
Created July 11, 2025 16:09
Show Gist options
  • Save fey/39cad37efc4a8589d5ccab4d48c156b2 to your computer and use it in GitHub Desktop.
Save fey/39cad37efc4a8589d5ccab4d48c156b2 to your computer and use it in GitHub Desktop.
<?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