diff --git a/lib/HTTP/Date.pm b/lib/HTTP/Date.pm index a33a2de..e676311 100644 --- a/lib/HTTP/Date.pm +++ b/lib/HTTP/Date.pm @@ -371,6 +371,12 @@ The function is able to parse the following formats: The parser ignores leading and trailing whitespace. It also allow the seconds to be missing and the month to be numerical in most formats. +Numeric-only dates use day/month/year ordering (the ISO and common +European convention), not the US month/day/year ordering. So +"3/4/2014" is parsed as 4 March 2014, and a US-style date such as +"3/13/2014" returns undef because 13 is not a valid month. To parse +US-style dates, swap the first two fields before calling parse_date(). + If the year is missing, then we assume that the date is the first matching date I current month. If the year is given with only 2 digits, then parse_date() will select the century that makes the diff --git a/t/numeric-date-order.t b/t/numeric-date-order.t new file mode 100644 index 0000000..6edec31 --- /dev/null +++ b/t/numeric-date-order.t @@ -0,0 +1,39 @@ +#!perl + +use strict; +use warnings; + +use Test::More; +use HTTP::Date qw(str2time parse_date); + +# Regression/characterization test for GitHub #10 (rt.cpan.org #94151). +# +# Numeric-only slash dates are parsed in day/month/year order (the ISO and +# common European convention), NOT US month/day/year order. This is a +# deliberate, documented contract: changing it would silently re-interpret +# existing dates for every downstream caller. +# +# So '3/12/2014' is 12 March-style ordering => day 3, month 12 (December), +# and '3/13/2014' is rejected because 13 is not a valid month. + +is( + str2time( '3/12/2014 0:00', 'GMT' ), + str2time( '3 Dec 2014 0:00', 'GMT' ), + 'numeric N/N/YYYY uses day/month order: 3/12 == 3 December' +); + +is( str2time( '3/13/2014 0:00', 'GMT' ), + undef, 'second field is the month: 13 is invalid, so undef' ); + +is( str2time( '13/3/2014 0:00', 'GMT' ), + str2time( '13 Mar 2014 0:00', 'GMT' ), + 'day may exceed 12: 13/3 == 13 March' ); + +# parse_date reports the same day/month ordering. +is_deeply( + [ ( parse_date('3/12/2014') )[ 0, 1, 2 ] ], + [ 2014, 12, 3 ], + 'parse_date(3/12/2014) => year 2014, month 12, day 3' +); + +done_testing;