php - Why does Carbon::createFromFormat() not throw an exception when given a UK format and a US date? - Stack Overflow

I have this code:try {Carbon::createFromFormat('dmY', $rawDate)->format('Ymd');

I have this code:

try {
    Carbon::createFromFormat('dmY', $rawDate)->format('Ymd');
} catch (InvalidFormatException $e) {
    echo 'Oops, bad date format.';
}

If I feed in 31012024 as my $rawDate value, I get 20240131 back as the output. This is correct. Carbon has correctly read and then formatted the date as I would expect it to.

If, instead, I feed in 01312024 (the 1st day of the 31st month of the year), I get back 20260701 as the output. This is not what I'd expect, as the 31st month does not exist, and I would have assumed that Carbon would throw an InvalidFormatException exception because the month simply cannot exist.

I could run the string through a script to validate that the first two characters are lower than 31 and the third and fourth characters are lower than 12, but I don't want to account for the different month lengths and leap years.

My question is, is there a different Carbon method I could call before the createFromFormat to validate that the date format is correct first?

I cannot use parse as this would successfully parse the American date format, which I do not want the script to do; it must accept and validate a UK date format.

No other format but ddmmyyyy should be accepted.

For reference, I am using Carbon 2.72.5 and am not in a Laravel environment, so I cannot use Laravel validation tools.

I have this code:

try {
    Carbon::createFromFormat('dmY', $rawDate)->format('Ymd');
} catch (InvalidFormatException $e) {
    echo 'Oops, bad date format.';
}

If I feed in 31012024 as my $rawDate value, I get 20240131 back as the output. This is correct. Carbon has correctly read and then formatted the date as I would expect it to.

If, instead, I feed in 01312024 (the 1st day of the 31st month of the year), I get back 20260701 as the output. This is not what I'd expect, as the 31st month does not exist, and I would have assumed that Carbon would throw an InvalidFormatException exception because the month simply cannot exist.

I could run the string through a script to validate that the first two characters are lower than 31 and the third and fourth characters are lower than 12, but I don't want to account for the different month lengths and leap years.

My question is, is there a different Carbon method I could call before the createFromFormat to validate that the date format is correct first?

I cannot use parse as this would successfully parse the American date format, which I do not want the script to do; it must accept and validate a UK date format.

No other format but ddmmyyyy should be accepted.

For reference, I am using Carbon 2.72.5 and am not in a Laravel environment, so I cannot use Laravel validation tools.

Share Improve this question edited Nov 20, 2024 at 9:56 ADyson 62.1k16 gold badges78 silver badges91 bronze badges Recognized by PHP Collective asked Nov 20, 2024 at 9:46 Ethan FieldEthan Field 4,7384 gold badges24 silver badges43 bronze badges 6
  • July 2026 is 31 months ahead of Jan 2024. So it's simply assumed "the 31st month of 2024" really means "31 months after the beginning of 2024", and worked out what date that is. So the behaviour is explicable, but perhaps not what people would assume it's going to do. – ADyson Commented Nov 20, 2024 at 9:54
  • 1 A solution with PHP's DateTime, I think this should also work for carbon: stackoverflow/questions/72627595/… – shingo Commented Nov 20, 2024 at 9:57
  • 2 As per [the Carbon docs])carbon.nesbot/docs/#api-instantiation), this function is really only a wrapper for PHP's built-in createFromFormat function. So I doubt you can change its behaviour really. The workaround suggested by shingo just above would be applicable, though. Either that or you apply your own additional validation mechanism before feeding the string into createFromFormat – ADyson Commented Nov 20, 2024 at 9:58
  • 1 From the PHP docs, for ease: Letters that are used for parsing numbers allow a wide range of values, outside of what the logical range would be. For example, the d (day of the month) accepts values in the range from 00 to 99. The only constraint is on the amount of digits. The date/time parser's overflow mechanism is used when out-of-range values are given – ADyson Commented Nov 20, 2024 at 9:59
  • 1 Actually, looking a bit lower down that same Carbon documentation, it mentions Carbon::hasFormatWithModifiers() which says you can use it to "test if a date matches a format". The examples then given seem to match your use case: var_dump(Carbon::hasFormatWithModifiers('21/05/1975', 'd#m#Y!')); // bool(true) // As 21 is too high for a month number and day is expected to be formatted "05": var_dump(Carbon::hasFormatWithModifiers('5/21/1975', 'd#m#Y!')); // bool(false) – ADyson Commented Nov 20, 2024 at 10:02
 |  Show 1 more comment

1 Answer 1

Reset to default 4

The createFromFormat function largely does exactly what the base PHP function of the same name does, and will "overflow" any values which don't fit within the normal range of a date. So in your example, July 2026 is 31 months after the start of 2024. It simply assumed you meant "31 months after the beginning of 2024", and worked out what date that is.

To overcome this you can use Carbon's hasFormatWithModifiers function to check the date format more precisely, before passing it to createFromFormat. This will check that the values for days and months are within the normal range of days and months.

Caveat: It still doesn't deal with the different lengths of months - e.g. it will allow things like the 31st of September. So you may want to consider addding additional validation of your own for this.

Example:

if (Carbon::hasFormatWithModifiers($rawDate, 'dmY')) {
  $dt = Carbon::createFromFormat('dmY', $rawDate)->format('Ymd');
  echo ($dt);
}
else echo "Invalid date";

Documentation reference:

  • https://carbon.nesbot/docs/#api-instantiation
  • https://www.php/manual/en/datetime.createfromformat.php

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742367969a4430695.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信