Newer Older
142 lines | 3.23kb
add files
Yuki Kimoto authored on 2014-03-26
1
package Mojo::Date;
2
use Mojo::Base -base;
3
use overload bool => sub {1}, '""' => sub { shift->to_string }, fallback => 1;
4

            
5
use Time::Local 'timegm';
6

            
7
has 'epoch';
8

            
9
my @DAYS   = qw(Sun Mon Tue Wed Thu Fri Sat);
10
my @MONTHS = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
11
my %MONTHS;
12
@MONTHS{@MONTHS} = (0 .. 11);
13

            
14
sub new { shift->SUPER::new->parse(@_) }
15

            
16
sub parse {
17
  my ($self, $date) = @_;
18

            
19
  # Invalid
20
  return $self unless defined $date;
21

            
22
  # epoch (784111777)
23
  return $self->epoch($date) if $date =~ /^\d+$/;
24

            
25
  # RFC 822/1123 (Sun, 06 Nov 1994 08:49:37 GMT)
26
  my ($day, $month, $year, $h, $m, $s);
27
  if ($date =~ /^\w+\,\s+(\d+)\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+GMT$/) {
28
    ($day, $month, $year, $h, $m, $s) = ($1, $MONTHS{$2}, $3, $4, $5, $6);
29
  }
30

            
31
  # RFC 850/1036 (Sunday, 06-Nov-94 08:49:37 GMT)
32
  elsif ($date =~ /^\w+\,\s+(\d+)-(\w+)-(\d+)\s+(\d+):(\d+):(\d+)\s+GMT$/) {
33
    ($day, $month, $year, $h, $m, $s) = ($1, $MONTHS{$2}, $3, $4, $5, $6);
34
  }
35

            
36
  # ANSI C asctime() (Sun Nov  6 08:49:37 1994)
37
  elsif ($date =~ /^\w+\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)$/) {
38
    ($month, $day, $h, $m, $s, $year) = ($MONTHS{$1}, $2, $3, $4, $5, $6);
39
  }
40

            
41
  # Invalid
42
  else { return $self }
43

            
44
  # Prevent crash
45
  my $epoch;
46
  $epoch = eval { timegm($s, $m, $h, $day, $month, $year) };
47
  $self->epoch($epoch) if !$@ && $epoch >= 0;
48

            
49
  return $self;
50
}
51

            
52
sub to_string {
53
  my $self = shift;
54

            
55
  # RFC 2616 (Sun, 06 Nov 1994 08:49:37 GMT)
56
  my ($s, $m, $h, $mday, $month, $year, $wday) = gmtime($self->epoch // time);
57
  return sprintf '%s, %02d %s %04d %02d:%02d:%02d GMT', $DAYS[$wday], $mday,
58
    $MONTHS[$month], $year + 1900, $h, $m, $s;
59
}
60

            
61
1;
62

            
63
=encoding utf8
64

            
65
=head1 NAME
66

            
67
Mojo::Date - HTTP date
68

            
69
=head1 SYNOPSIS
70

            
71
  use Mojo::Date;
72

            
73
  # Parse
74
  my $date = Mojo::Date->new('Sun, 06 Nov 1994 08:49:37 GMT');
75
  say $date->epoch;
76

            
77
  # Build
78
  my $date = Mojo::Date->new(time);
79
  say "$date";
80

            
81
=head1 DESCRIPTION
82

            
83
L<Mojo::Date> implements HTTP date and time functions as described in RFC
84
2616.
85

            
86
  Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
87
  Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
88
  Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
89

            
90
=head1 ATTRIBUTES
91

            
92
L<Mojo::Date> implements the following attributes.
93

            
94
=head2 epoch
95

            
96
  my $epoch = $date->epoch;
97
  $date     = $date->epoch(784111777);
98

            
99
Epoch seconds.
100

            
101
=head1 METHODS
102

            
103
L<Mojo::Date> inherits all methods from L<Mojo::Base> and implements the
104
following new ones.
105

            
106
=head2 new
107

            
108
  my $date = Mojo::Date->new;
109
  my $date = Mojo::Date->new('Sun Nov  6 08:49:37 1994');
110

            
111
Construct a new L<Mojo::Date> object and L</"parse"> date if necessary.
112

            
113
=head2 parse
114

            
115
  $date = $date->parse('Sun Nov  6 08:49:37 1994');
116

            
117
Parse date.
118

            
119
  # Epoch
120
  say Mojo::Date->new('784111777')->epoch;
121

            
122
  # RFC 822/1123
123
  say Mojo::Date->new('Sun, 06 Nov 1994 08:49:37 GMT')->epoch;
124

            
125
  # RFC 850/1036
126
  say Mojo::Date->new('Sunday, 06-Nov-94 08:49:37 GMT')->epoch;
127

            
128
  # Ansi C asctime()
129
  say Mojo::Date->new('Sun Nov  6 08:49:37 1994')->epoch;
130

            
131
=head2 to_string
132

            
133
  my $str = $date->to_string;
134
  my $str = "$date";
135

            
136
Render date suitable for HTTP messages.
137

            
138
=head1 SEE ALSO
139

            
140
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
141

            
142
=cut