# Copyright (C) 2008-2009, Sebastian Riedel. package Mojo::Date; use strict; use warnings; use base 'Mojo::Base'; use overload '""' => sub { shift->to_string }, fallback => 1; require Time::Local; __PACKAGE__->attr(epoch => (chained => 1)); sub new { my $self = shift->SUPER::new(); $self->parse(@_); return $self; } # I suggest you leave immediately. # Or what? You'll release the dogs or the bees? # Or the dogs with bees in their mouths and when they bark they shoot bees at # you? sub parse { my ($self, $date) = @_; $self = $self->new unless ref $self; # Shortcut return unless defined $date; # epoch - 784111777 if ($date =~ /^\d+$/) { $self->epoch($date); return $self; } # Remove spaces, weekdays and timezone $date =~ s/^\s+//; $date =~ s/^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*//i; $date =~ s/GMT\s*$//i; $date =~ s/\s+$//; my ($day, $month, $year, $hour, $minute, $second); my $months = {}; my $i = 0; for my $m (qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/) { $months->{$m} = $i; $i++; } # RFC822/1123 - Sun, 06 Nov 1994 08:49:37 GMT if ($date =~ /^(\d+)\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)$/) { $day = $1; $month = $months->{$2}; $year = $3; $hour = $4; $minute = $5; $second = $6; } # RFC850/1036 - Sunday, 06-Nov-94 08:49:37 GMT elsif ($date =~ /^(\d+)-(\w+)-(\d+)\s+(\d+):(\d+):(\d+)$/) { $day = $1; $month = $months->{$2}; $year = $3; $hour = $4; $minute = $5; $second = $6; } # ANSI C asctime() - Sun Nov 6 08:49:37 1994 elsif ($date =~ /^(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)$/) { $month = $months->{$1}; $day = $2; $hour = $3; $minute = $4; $second = $5; $year = $6; } # Invalid format else { return undef } $self->epoch( Time::Local::timegm($second, $minute, $hour, $day, $month, $year)); return $self; } sub to_string { my $self = shift; my $epoch = shift || $self->{epoch}; $epoch = time unless defined $epoch; my ($second, $minute, $hour, $mday, $month, $year, $wday) = gmtime $epoch; 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/]; # Format return sprintf( "%s, %02d %s %04d %02d:%02d:%02d GMT", $days->[$wday], $mday, $months->[$month], $year + 1900, $hour, $minute, $second ); } 1; __END__ =head1 NAME Mojo::Date - Date =head1 SYNOPSIS use Mojo::Date; my $date = Mojo::Date->new(784111777); my $http_date = $date->to_string; $date->parse('Sun, 06 Nov 1994 08:49:37 GMT'); my $epoch = $date->epoch; =head1 DESCRIPTION L implements HTTP date and time functions according to RFC2616. 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 =head1 ATTRIBUTES =head2 C my $epoch = $date->epoch; $date = $date->epoch(784111777); Returns epoch seconds if called without arguments. Returns the invocant if called with arguments. =head1 METHODS L inherits all methods from L and implements the following new ones. =head2 C my $date = Mojo::Date->new($string); =head2 C $date = $date->parse('Sun Nov 6 08:49:37 1994'); Returns the invocant if the given date could be parsed successfully. Returns false otherwise. Parsable formats include: - Epoch format (784111777) - RFC 822/1123 (Sun, 06 Nov 1994 08:49:37 GMT) - RFC 850/1036 (Sunday, 06-Nov-94 08:49:37 GMT) - ANSI C asctime() (Sun Nov 6 08:49:37 1994) =head2 C my $string = $date->to_string; Returns a valid HTTP date according to RFC 822. =cut