While using the nesbot/carbon library I've noticed that it accepts single letters as valid dates and parses them in a way that maps to a relative time range. Specifically, single letters are parsed (case-insensitively) into time offsets, ranging from -12 hours to +12 hours relative to the current time. However, it does not accept single digits as strings or more than one letter in the string.
You can test it here: https://play.phpsandbox.io/embed/nesbot/carbon
<?php
echo "a: ";
echo Carbon::parse("a")->getTimestamp(); // now -1 hour
echo "\r\n b: ";
echo Carbon::parse("b")->getTimestamp(); // now -2 hours
echo "\r\n c: ";
echo Carbon::parse("c")->getTimestamp(); // now -3 hours
echo "\r\n C: ";
echo Carbon::parse("C")->getTimestamp(); // now -3 hours (case-insensitive)
echo "\r\n d: ";
echo Carbon::parse("d")->getTimestamp(); // now -4 hours
echo "\r\n m: ";
echo Carbon::parse("m")->getTimestamp(); // now -12 hours
echo "\r\n n: ";
echo Carbon::parse("n")->getTimestamp(); // now +1 hour
echo "\r\n x: ";
echo Carbon::parse("x")->getTimestamp(); // now +11 hours
echo "\r\n Y: ";
echo Carbon::parse("Y")->getTimestamp(); // now +12 hours
echo "\r\n z: ";
echo Carbon::parse("z")->getTimestamp(); // now
echo "\r\n 1: ";
echo Carbon::parse("1")->getTimestamp(); // error
echo "\r\n aa: ";
echo Carbon::parse("aa")->getTimestamp(); // error
Error message: Carbon\Exceptions\InvalidFormatException with message 'Could not parse 'aa': Failed to parse time string (aa) at position 0 (a): The timezone could not be found in the database'
I also checked how the standard php DateTime object reacts and it always returns UTC now for a single letter but throws an error when trying to parse more than a single letter.
You can test it here: https://onlinephp.io/
<?php
$date = new DateTime('a'); // UTC now
echo $date->format('Y-m-d H:i:s');
echo "\n";
$date = new DateTime('b'); // UTC now
echo $date->format('Y-m-d H:i:s');
echo "\n";
$date = new DateTime('B'); // UTC now
echo $date->format('Y-m-d H:i:s');
echo "\n";
$date = new DateTime('m'); // UTC now
echo $date->format('Y-m-d H:i:s');
echo "\n";
$date = new DateTime('n'); // UTC now
echo $date->format('Y-m-d H:i:s');
echo "\n";
$date = new DateTime('z'); // UTC now
echo $date->format('Y-m-d H:i:s');
echo "\n";
$date = new DateTime('aa'); // error
echo $date->format('Y-m-d H:i:s');
echo "\n";
Error message:
Fatal error: Uncaught Exception: Failed to parse time string (aa) at position 0 (a): The timezone could not be found in the database in /home/user/scripts/code.php:21
This behavior is a bit unexpected, as one might assume parsing single letters would throw an error. Is it a bug? or is it common for datetime libraries to work like that?
No, It's not bug.
Characters we get Military Time Zones
Military time zones use single-letter identifiers to represent time zones relative to Coordinated Universal Time (UTC).
A
' to 'M
' (excluding 'J
'): UTC+1
to UTC+12
N
' to 'Y
': UTC−1
to UTC−12
Z
': UTC+0
When you pass multi-character strings like 'aa
' or digits like '1
', Carbon interprets them as time zone identifiers. Since these are not valid time zones, it throws an InvalidFormatException