DatesRole: Adding support for partial time format (#4187)

* DatesRole: Failing tests for new relative date + time format

* DatesRole: Adding support for queries like "03 may 07:00"
master
Rob Emery 2017-05-25 03:36:46 +01:00 committed by Zaahir Moolla
parent 07a5ba3e85
commit e3cb2380e9
2 changed files with 27 additions and 6 deletions

View File

@ -40,6 +40,10 @@ my $full_month = qr#January|February|March|April|May|June|July|August|S
my $month_regex = qr#$full_month|$short_month#;
my $time_24h = qr#(?:(?:[0-1][0-9])|(?:2[0-3]))[:]?[0-5][0-9][:]?[0-5][0-9]#i;
my $time_12h = qr#(?:(?:0[1-9])|(?:1[012])):[0-5][0-9]:[0-5][0-9]\s?(?:am|pm)#i;
my $time_with_optional_seconds = qr#
(?:(?:[0-1][0-9])|(?:2[0-3]))[:]?[0-5][0-9](?:[:]?[0-5][0-9])? |
(?:(?:0[1-9])|(?:1[012])):[0-5][0-9](?::[0-5][0-9])?\s?(?:am|pm)
#ix;
my $date_number = qr#[0-3]?[0-9]#;
my $full_year = qr#[0-9]{4}#;
my $relative_dates = qr#
@ -255,7 +259,9 @@ my $descriptive_datestring = qr{
(?:(?:$date_number)\s?$number_suffixes?\s(?:$month_regex)) | # 18th Jan, 01 October
(?:(?:$month_regex)\s(?:$date_number)\s?$number_suffixes?) | # Dec 25, July 4th
(?:$month_regex) | # February, Aug
(?:$relative_dates) # next week, last month, this year
(?:$relative_dates) | # next week, last month, this year
(?:(?:$date_number)\s?$number_suffixes?\s(?:$month_regex)\s(?:$time_with_optional_seconds)) | # 22 may 08:00
(?:(?:$time_with_optional_seconds)\s(?:$date_number)\s?$number_suffixes?\s(?:$month_regex)) # 08:00 22 may
}ix;
# Used for parse_descriptive_datestring_to_date
@ -265,7 +271,9 @@ my $descriptive_datestring_matches = qr#
(?:(?<d>$date_number)\s?$number_suffixes?\s(?<m>$month_regex)) |
(?:(?<m>$month_regex)\s(?<d>$date_number)\s?$number_suffixes?) |
(?<m>$month_regex) |
(?<r>$relative_dates)
(?<r>$relative_dates) |
(?:(?<d>$date_number)\s?$number_suffixes?\s(?<m>$month_regex)\s(?<t>$time_with_optional_seconds)) |
(?:(?<t>$time_with_optional_seconds)\s(?<d>$date_number)\s?$number_suffixes?\s(?<m>$month_regex))
#ix;
my $formatted_datestring = build_datestring_regex();
@ -345,8 +353,10 @@ sub build_datestring_regex {
push @regexes, $date_standard;
# month-first date formats
push @regexes, qr#$date_number$date_delim$short_month$date_delim$full_year#i;
push @regexes, qr#$date_number$date_delim$full_month$date_delim$full_year#i;
push @regexes, qr#$date_number (?:$full_month|$short_month) $full_year $time_24h#i;
push @regexes, qr#$date_number$date_delim$short_month$date_delim$full_year(?: $time_24h)?#i;
push @regexes, qr#$date_number$date_delim$full_month$date_delim$full_year(?: $time_24h)?#i;
push @regexes, qr#(?:$short_month|$full_month) (?:the )?$date_number(?: ?$number_suffixes)?[,]? $full_year#i;
# day-first date formats
@ -374,6 +384,7 @@ sub parse_formatted_datestring_to_date {
my ($d) = @_;
return unless (defined $d && $d =~ qr/^$formatted_datestring$/); # Only handle white-listed strings, even if they might otherwise work.
if ($d =~ $ambiguous_dates_matches) {
# guesswork for ambigous DMY/MDY and switch to ISO
my ($month, $day, $year) = ($+{'m'}, $+{'d'}, $+{'y'}); # Assume MDY, even though it's crazy, for backward compatibility
@ -391,7 +402,7 @@ sub parse_formatted_datestring_to_date {
}
$d =~ s/(\d+)\s?$number_suffixes/$1/i; # Strip ordinal text.
$d =~ s/(\sof\s)|(\sthe\s)/ /i; # Strip "of" for "4th of march" and "the" for "march the 4th"
$d =~ s/(\sof\s)|(\sthe\s)/ /i; # Strip "of" for "4th of march" and "the" for "march the 4th"
$d =~ s/,//i; # Strip any random commas.
$d =~ s/($full_month)/$full_month_to_short{lc $1}/i; # Parser deals better with the shorter month names.
$d =~ s/^($short_month)$date_delim(\d{1,2})/$2-$short_month_fix{lc $1}/i; # Switching Jun-01-2012 to 01 Jun 2012
@ -476,7 +487,11 @@ sub parse_descriptive_datestring_to_date {
my $month = $+{'m'}; # Set in each alternative match.
if (my $day = $+{'d'}) {
return parse_datestring_to_date("$day $month " . $base_time->year());
my $timecomponent = "00:00:00";
$timecomponent = $+{'t'} if($+{'t'});
$timecomponent .= ":00" if($timecomponent =~ qr/^[0-9]{2}:[0-9]{2}$/); #Seconds are optional; default to 0 if unspecified
return parse_datestring_to_date("$day $month " . $base_time->year() . " $timecomponent");
} elsif (my $relative_dir = $+{'q'}) {
my $tmp_date = parse_datestring_to_date("01 $month " . $base_time->year());

View File

@ -141,6 +141,7 @@ subtest 'Dates' => sub {
'5th of january 1993' => 726192000,
'5 of jan 1993' => 726192000,
'june the 1st 2012' => 1338508800,
"11 march 2000 00:00:00" => 952732800
);
foreach my $test_date (sort keys %dates_to_match) {
@ -475,9 +476,14 @@ subtest 'Dates' => sub {
'jun 21' => 961545600,
'next january' => 978307200,
'december' => 975628800,
'22 may 2000 08:00:00' => 958982400,
'22 may 08:00:00' => 958982400,
'22 may 08:00' => 958982400,
'08:00 22 may' => 958982400,
);
foreach my $test_mixed_date (sort keys %mixed_dates_to_test) {
like($test_mixed_date, qr/^$test_datestring_regex$/, "$test_mixed_date matches the datestring_regex");
my $parsed_date_object = DatesRoleTester::parse_datestring_to_date($test_mixed_date);
isa_ok($parsed_date_object, 'DateTime', $test_mixed_date);
is($parsed_date_object->epoch, $mixed_dates_to_test{$test_mixed_date}, ' ... represents the correct time.');