[Rt-commit] rt branch, 4.4/parse-date-with-datetime-format-natural, created. rt-4.2.11-136-ge527517
? sunnavy
sunnavy at bestpractical.com
Thu Aug 13 15:09:37 EDT 2015
The branch, 4.4/parse-date-with-datetime-format-natural has been created
at e52751759019724d8f77c1bd48d8b8e78d61b6db (commit)
- Log -----------------------------------------------------------------
commit f446755b4e2363d067d9924904aa0579776dff14
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Aug 13 02:10:44 2015 +0800
abstract date parse by Time::ParseDate into ParseByTimeParseDate
no functions changed.
we are going to add more date parse methods, this makes things more clear
diff --git a/lib/RT/Date.pm b/lib/RT/Date.pm
index 4344865..282a050 100644
--- a/lib/RT/Date.pm
+++ b/lib/RT/Date.pm
@@ -213,35 +213,7 @@ sub Set {
}
}
elsif ( $format eq 'unknown' ) {
- require Time::ParseDate;
- # the module supports only legacy timezones like PDT or EST...
- # so we parse date as GMT and later apply offset, this only
- # should be applied to absolute times, so compensate shift in NOW
- my $now = time;
- $now += ($self->Localtime( $args{Timezone}, $now ))[9];
- my ($date, $error) = Time::ParseDate::parsedate(
- $args{'Value'},
- GMT => 1,
- NOW => $now,
- UK => RT->Config->Get('DateDayBeforeMonth'),
- PREFER_PAST => RT->Config->Get('AmbiguousDayInPast'),
- PREFER_FUTURE => RT->Config->Get('AmbiguousDayInFuture'),
- );
- unless ( defined $date ) {
- $RT::Logger->warning(
- "Couldn't parse date '$args{'Value'}' by Time::ParseDate"
- );
- return $self->Unix(0);
- }
-
- # apply timezone offset
- $date -= ($self->Localtime( $args{Timezone}, $date ))[9];
-
- $RT::Logger->debug(
- "RT::Date used Time::ParseDate to make '$args{'Value'}' $date\n"
- );
-
- return $self->Unix($date || 0);
+ return $self->Unix($self->ParseByTimeParseDate(%args) || 0);
}
else {
$RT::Logger->error(
@@ -253,6 +225,46 @@ sub Set {
return $self->Unix;
}
+=head2 ParseByTimeParseDate
+
+Parse date using Time::ParseDate.
+return undef if it fails to parse, otherwise return epoch time.
+
+=cut
+
+sub ParseByTimeParseDate {
+ my $self = shift;
+ my %args = @_;
+ require Time::ParseDate;
+ # the module supports only legacy timezones like PDT or EST...
+ # so we parse date as GMT and later apply offset, this only
+ # should be applied to absolute times, so compensate shift in NOW
+ my $now = time;
+ $now += ($self->Localtime( $args{Timezone}, $now ))[9];
+ my ($date, $error) = Time::ParseDate::parsedate(
+ $args{'Value'},
+ GMT => 1,
+ NOW => $now,
+ UK => RT->Config->Get('DateDayBeforeMonth'),
+ PREFER_PAST => RT->Config->Get('AmbiguousDayInPast'),
+ PREFER_FUTURE => RT->Config->Get('AmbiguousDayInFuture'),
+ );
+ unless ( defined $date ) {
+ $RT::Logger->warning(
+ "Couldn't parse date '$args{'Value'}' by Time::ParseDate"
+ );
+ return undef;
+ }
+
+ # apply timezone offset
+ $date -= ($self->Localtime( $args{Timezone}, $date ))[9];
+
+ $RT::Logger->debug(
+ "RT::Date used Time::ParseDate to make '$args{'Value'}' $date\n"
+ );
+ return $date;
+}
+
=head2 SetToNow
Set the object's time to the current time. Takes no arguments
commit e52751759019724d8f77c1bd48d8b8e78d61b6db
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Aug 13 09:16:09 2015 +0800
enhance date parse with DateTime::Format::Natural
if Time::ParseDate fails to parse, then we will try DateTime::Format::Natural
thanks to DateTime::Format::Natural, Month names are also supported now
diff --git a/lib/RT/Date.pm b/lib/RT/Date.pm
index 282a050..d09411c 100644
--- a/lib/RT/Date.pm
+++ b/lib/RT/Date.pm
@@ -213,7 +213,7 @@ sub Set {
}
}
elsif ( $format eq 'unknown' ) {
- return $self->Unix($self->ParseByTimeParseDate(%args) || 0);
+ return $self->Unix($self->ParseByTimeParseDate(%args) || $self->ParseByDateTimeFormatNatural(%args) || 0);
}
else {
$RT::Logger->error(
@@ -265,6 +265,38 @@ sub ParseByTimeParseDate {
return $date;
}
+=head2 ParseByDateTimeFormatNatural
+
+Parse date using DateTime::Format::Natural.
+return undef if it fails to parse, otherwise return epoch time.
+
+=cut
+
+sub ParseByDateTimeFormatNatural {
+ my $self = shift;
+ my %args = @_;
+ require DateTime::Format::Natural;
+
+ my $parser = DateTime::Format::Natural->new(
+ prefer_future => RT->Config->Get('AmbiguousDayInPast') ? 0 : RT->Config->Get('AmbiguousDayInFuture'),
+ time_zone => $self->Timezone($args{Timezone}),
+ );
+ my ($dt) = eval { $parser->parse_datetime($args{Value}) };
+ if ( !$@ && $parser->success && $dt ) {
+ my $date = $dt->epoch;
+ $RT::Logger->debug(
+ "RT::Date used DateTime::Format::Natural to make '$args{'Value'}' $date\n"
+ );
+ return $date;
+ }
+ else {
+ $RT::Logger->warning(
+ "Couldn't parse date '$args{'Value'}' by DateTime::Format::Natural"
+ );
+ return undef;
+ }
+}
+
=head2 SetToNow
Set the object's time to the current time. Takes no arguments
diff --git a/t/api/date.t b/t/api/date.t
index dd22943..fd8fce2 100644
--- a/t/api/date.t
+++ b/t/api/date.t
@@ -344,7 +344,9 @@ my $year = (localtime(time))[5] + 1900;
my $date = RT::Date->new(RT->SystemUser);
warnings_like {
$date->Set(Format => 'unknown', Value => 'weird date');
- } qr{Couldn't parse date 'weird date' by Time::ParseDate};
+ } [ qr{Couldn't parse date 'weird date' by Time::ParseDate},
+ qr{Couldn't parse date 'weird date' by DateTime::Format::Natural}
+ ];
ok(!$date->IsSet, "date was wrong");
RT->Config->Set( Timezone => 'Europe/Moscow' );
@@ -606,6 +608,36 @@ my $year = (localtime(time))[5] + 1900;
ok( !$date->IsSet, "unix is 0 with Value => ' ', Format => 'unknown'" );
}
+{
+ # set+unknown format(DateTime::Format::Natural)
+ my $date = RT::Date->new(RT->SystemUser);
+ warnings_like {
+ $date->Set(Format => 'unknown', Value => 'another weird date');
+ } [ qr{Couldn't parse date 'another weird date' by Time::ParseDate},
+ qr{Couldn't parse date 'another weird date' by DateTime::Format::Natural}
+ ], 'warning for "another weird date"';
+ ok(!$date->IsSet, "date was wrong");
+ RT->Config->Set( AmbiguousDayInPast => 0 );
+ RT->Config->Set( AmbiguousDayInFuture => 0 );
+ RT->Config->Set( Timezone => 'Asia/Shanghai' );
+ set_fixed_time("2015-11-28T15:10:00Z");
+ warnings_like {
+ $date->Set(Format => 'unknown', Value => 'Apr');
+ } qr{Couldn't parse date 'Apr' by Time::ParseDate}, "warning by Time::ParseDate";
+ is($date->ISO, '2015-03-31 16:00:00', "April in the past");
+
+ warnings_like {
+ $date->Set(Format => 'unknown', Value => 'Monday');
+ } qr{Couldn't parse date 'Monday' by Time::ParseDate}, "warning by Time::ParseDate";
+ is($date->ISO, '2015-11-22 16:00:00', "Monday in the past");
+
+ RT->Config->Set( AmbiguousDayInFuture => 1 );
+ warnings_like {
+ $date->Set(Format => 'unknown', Value => 'Apr');
+ } qr{Couldn't parse date 'Apr' by Time::ParseDate}, "warning by Time::ParseDate";
+ is($date->ISO, '2016-03-31 16:00:00', "April in the future");
+}
+
#TODO: AsString
#TODO: RFC2822, W3CDTF with Timezones
diff --git a/t/web/cf_date.t b/t/web/cf_date.t
index 4783484..0b1fe8b 100644
--- a/t/web/cf_date.t
+++ b/t/web/cf_date.t
@@ -187,7 +187,15 @@ diag 'check invalid inputs';
my @warnings = $m->get_warnings;
chomp @warnings;
- is_deeply( [@warnings], [(q{Couldn't parse date 'foodate' by Time::ParseDate})x2] );
+ is_deeply(
+ [ @warnings ],
+ [
+ (
+ q{Couldn't parse date 'foodate' by Time::ParseDate},
+ q{Couldn't parse date 'foodate' by DateTime::Format::Natural}
+ ) x 2
+ ]
+ );
}
diag 'retain values when adding attachments';
diff --git a/t/web/cf_datetime.t b/t/web/cf_datetime.t
index a370ce4..5ec2885 100644
--- a/t/web/cf_datetime.t
+++ b/t/web/cf_datetime.t
@@ -213,7 +213,15 @@ diag 'check invalid inputs';
my @warnings = $m->get_warnings;
chomp @warnings;
- is_deeply( [@warnings], [(q{Couldn't parse date 'foodate' by Time::ParseDate})x2] );
+ is_deeply(
+ [ @warnings ],
+ [
+ (
+ q{Couldn't parse date 'foodate' by Time::ParseDate},
+ q{Couldn't parse date 'foodate' by DateTime::Format::Natural}
+ ) x 2
+ ]
+ );
}
diag 'retain values when adding attachments';
diff --git a/t/web/ticket_modify_all.t b/t/web/ticket_modify_all.t
index 6b85d98..3563048 100644
--- a/t/web/ticket_modify_all.t
+++ b/t/web/ticket_modify_all.t
@@ -63,7 +63,20 @@ for my $unset ("0", "-", " ") {
$m->field('Due_Date' => $unset);
$m->click('SubmitTicket');
$m->text_contains("Due: (Not set)", "due date successfully cleared with '$unset'");
- $m->warning_like(qr/Couldn't parse date '-'/) if $unset eq "-";
+
+ if ( $unset eq '-' ) {
+ my @warnings = $m->get_warnings;
+ chomp @warnings;
+ is_deeply(
+ [ @warnings ],
+ [
+ (
+ q{Couldn't parse date '-' by Time::ParseDate},
+ q{Couldn't parse date '-' by DateTime::Format::Natural}
+ )
+ ]
+ );
+ }
}
$m->get( $url . '/Ticket/ModifyAll.html?id=' . $ticket->id );
-----------------------------------------------------------------------
More information about the rt-commit
mailing list