1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
# Copyright (C) 2008-2010, 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');
# Days and months
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/;
# Reverse months
my %MONTHS;
{
my $i = 0;
for my $month (@MONTHS) {
$MONTHS{$month} = $i;
$i++;
}
}
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) = @_;
# Shortcut
return $self unless defined $date;
# epoch - 784111777
if ($date =~ /^\d+$/) {
$self->epoch($date);
return $self;
}
# Remove spaces, weekdays and timezone
$date =~ s/^\s+//;
my $re = join '|', @DAYS;
$date =~ s/^(?:$re)[a-z]*,?\s*//i;
$date =~ s/GMT\s*$//i;
$date =~ s/\s+$//;
my ($day, $month, $year, $hour, $minute, $second);
# 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 $self }
my $epoch;
# Prevent crash
eval {
$epoch =
Time::Local::timegm($second, $minute, $hour, $day, $month, $year);
};
return $self if $@ || $epoch < 0;
$self->epoch($epoch);
return $self;
}
sub to_string {
my $self = shift;
my $epoch = $self->epoch;
$epoch = time unless defined $epoch;
my ($second, $minute, $hour, $mday, $month, $year, $wday) = gmtime $epoch;
# 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 - HTTP 1.1 Date Container
=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<Mojo::Date> implements HTTP 1.1 date and time functions according to
RFC 2616.
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
L<Mojo::Date> implements the following attributes.
=head2 C<epoch>
my $epoch = $date->epoch;
$date = $date->epoch(784111777);
Epoch seconds.
=head1 METHODS
L<Mojo::Date> inherits all methods from L<Mojo::Base> and implements the
following new ones.
=head2 C<new>
my $date = Mojo::Date->new;
my $date = Mojo::Date->new($string);
Construct a new L<Mojo::Date> object.
=head2 C<parse>
$date = $date->parse('Sun Nov 6 08:49:37 1994');
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<to_string>
my $string = $date->to_string;
Render date suitable for HTTP 1.1 messages.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicious.org>.
=cut
|