Skip to content

Instantly share code, notes, and snippets.

/3339.diff Secret

Created August 20, 2014 20:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3a56bc0d839d86b1d9af to your computer and use it in GitHub Desktop.
Save anonymous/3a56bc0d839d86b1d9af to your computer and use it in GitHub Desktop.
diff --git a/lib/Mojo/Date.pm b/lib/Mojo/Date.pm
index dc0164c..78abbc6 100644
--- a/lib/Mojo/Date.pm
+++ b/lib/Mojo/Date.pm
@@ -6,6 +6,13 @@ use Time::Local 'timegm';
has 'epoch';
+my $RFC3339_RE = qr/
+ ^
+ (\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:\.\d+)? # Date and time
+ (?:Z|([+-])(\d+):(\d+))? # Offset
+ $
+/xi;
+
my @DAYS = qw(Sun Mon Tue Wed Thu Fri Sat);
my @MONTHS = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my %MONTHS;
@@ -17,7 +24,7 @@ sub parse {
my ($self, $date) = @_;
# RFC 822/1123 (Sun, 06 Nov 1994 08:49:37 GMT)
- my ($day, $month, $year, $h, $m, $s);
+ my ($day, $month, $year, $h, $m, $s, $offset);
if ($date =~ /^\w+\,\s+(\d+)\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+GMT$/) {
($day, $month, $year, $h, $m, $s) = ($1, $MONTHS{$2}, $3, $4, $5, $6);
}
@@ -25,6 +32,12 @@ sub parse {
# epoch (784111777)
elsif ($date =~ /^\d+$/) { return $self->epoch($date) }
+ # RFC 3339
+ elsif ($date =~ $RFC3339_RE) {
+ ($year, $month, $day, $h, $m, $s) = ($1, $2 - 1, $3, $4, $5, $6);
+ $offset = (($8 * 60 * 60) + ($9 * 60)) * ($7 eq '-' ? -1 : 1) if $7;
+ }
+
# RFC 850/1036 (Sunday, 06-Nov-94 08:49:37 GMT)
elsif ($date =~ /^\w+\,\s+(\d+)-(\w+)-(\d+)\s+(\d+):(\d+):(\d+)\s+GMT$/) {
($day, $month, $year, $h, $m, $s) = ($1, $MONTHS{$2}, $3, $4, $5, $6);
@@ -40,6 +53,7 @@ sub parse {
# Prevent crash
my $epoch = eval { timegm($s, $m, $h, $day, $month, $year) };
+ $epoch += $offset if $offset;
return defined $epoch && $epoch >= 0 ? $self->epoch($epoch) : $self;
}
@@ -75,12 +89,14 @@ Mojo::Date - HTTP date
=head1 DESCRIPTION
L<Mojo::Date> implements HTTP date and time functions based on
-L<RFC 7230|http://tools.ietf.org/html/rfc7230> and
-L<RFC 7231|http://tools.ietf.org/html/rfc7231>.
+L<RFC 7230|http://tools.ietf.org/html/rfc7230>,
+L<RFC 7231|http://tools.ietf.org/html/rfc7231> and
+L<RFC 3339|http://tools.ietf.org/html/rfc3339>.
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ 1985-04-12T23:20:50Z ; RFC 3339
=head1 ATTRIBUTES
@@ -123,6 +139,9 @@ Parse date.
# Ansi C asctime()
say Mojo::Date->new('Sun Nov 6 08:49:37 1994')->epoch;
+ # RFC 3339
+ say Mojo::Date->new('1985-04-12T23:20:50Z')->epoch;
+
=head2 to_string
my $str = $date->to_string;
diff --git a/t/mojo/date.t b/t/mojo/date.t
index 6a7fd7e..84a88e8 100644
--- a/t/mojo/date.t
+++ b/t/mojo/date.t
@@ -9,6 +9,22 @@ is $date->epoch, 784111777, 'right epoch value';
$date = Mojo::Date->new('Fri, 13 May 2011 10:00:24 GMT');
is $date->epoch, 1305280824, 'right epoch value';
+# RFC 3339
+is(Mojo::Date->new('2014-08-20T20:45:00')->epoch,
+ 1408567500, 'right epoch value');
+is(Mojo::Date->new('2014-08-20T20:45:00.01')->epoch,
+ 1408567500, 'right epoch value');
+is(Mojo::Date->new('2014-08-20T20:45:00-00:46')->epoch,
+ 1408564740, 'right epoch value');
+is(Mojo::Date->new('2014-08-20t20:45:00-01:46')->epoch,
+ 1408561140, 'right epoch value');
+is(Mojo::Date->new('2014-08-20t20:45:00+01:46')->epoch,
+ 1408573860, 'right epoch value');
+is(Mojo::Date->new('1994-11-06T08:49:37Z')->epoch,
+ 784111777, 'right epoch value');
+is(Mojo::Date->new('1994-11-06T08:49:37.33Z')->epoch,
+ 784111777, 'right epoch value');
+
# RFC 850/1036
is(Mojo::Date->new('Sunday, 06-Nov-94 08:49:37 GMT')->epoch,
784111777, 'right epoch value');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment