File Coverage

blib/lib/DateTime/Format/HTTP.pm
Criterion Covered Total %
statement 45 45 100.0
branch 20 20 100.0
condition n/a
subroutine 9 9 100.0
pod 4 4 100.0
total 78 78 100.0


line stmt bran cond sub pod time code
1             package DateTime::Format::HTTP;
2 3     3   1091288 use strict;
  3         7  
  3         106  
3 3     3   11 use warnings;
  3         20  
  3         198  
4              
5             our $VERSION = '0.43';
6              
7 3     3   2241 use DateTime;
  3         1342951  
  3         127  
8 3     3   1911 use HTTP::Date qw();
  3         17036  
  3         2545  
9              
10             our @MoY = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
11             our %MoY;
12             @MoY{@MoY} = (1..12);
13              
14             sub format_datetime
15             {
16 4     4 1 269019 my ($self, $dt) = @_;
17 4 100       20 $dt = DateTime->now unless defined $dt;
18 4         419 $dt = $dt->clone->set_time_zone( 'GMT' );
19 4         1199 return $dt->strftime( "%a, %d %b %Y %H:%M:%S GMT" );
20             }
21              
22              
23             sub parse_datetime
24             {
25 120     120 1 295626 my ($self, $str, $zone) = @_;
26 120         208 local $_;
27 120 100       294 die "No input string!" unless defined $str;
28              
29             # fast exit for strictly conforming string
30 119 100       544 if ($str =~ /^
31             [SMTWF][a-z][a-z],
32             \ (\d\d)
33             \ ([JFMAJSOND][a-z][a-z])
34             \ (\d\d\d\d)
35             \ (\d\d):(\d\d):(\d\d)
36             \ GMT$/x) {
37             return DateTime->new(
38             day => $1,
39 1         11 month => $MoY{$2},
40             year => $3,
41             hour => $4,
42             minute => $5,
43             second => $6,
44             time_zone => 'GMT'
45             );
46             }
47              
48 118         280 my %d = $self->_parse_date($str);
49              
50 113 100       290 unless (defined $d{time_zone})
51             {
52 60 100       191 $d{time_zone} = defined $zone ? $zone : 'floating';
53             }
54              
55 113         186 my $frac = $d{second}; $frac -= ($d{second} = int($frac));
  113         244  
56 113         154 my $nano = 1_000_000_000 * $frac; $d{nanosecond} = int($nano + 0.5);
  113         268  
57 113         428 return DateTime->new( %d );
58             }
59              
60              
61             sub _parse_date
62             {
63 118     118   217 my ($self, $str) = @_;
64 118         347 my @fields = qw( year month day hour minute second time_zone );
65 118         179 my %d;
66 118         361 my @values = HTTP::Date::parse_date( $str );
67 118 100       5460 die "Could not parse date [$str]\n" unless @values;
68 113         572 @d{@fields} = @values;
69              
70 113 100       267 if (defined $d{time_zone}) {
71 53 100       253 $d{time_zone} = "GMT" if $d{time_zone} =~ /^(Z|GMT|UTC?|[-+]?0+)$/ix;
72             }
73              
74 113         782 return %d;
75             }
76              
77              
78             sub format_iso
79             {
80 12     12 1 4915 my ($self, $dt) = @_;
81 12 100       37 $dt = DateTime->now unless defined $dt;
82 12         308 sprintf("%04d-%02d-%02d %02d:%02d:%02d",
83             $dt->year, $dt->month, $dt->day,
84             $dt->hour, $dt->min, $dt->sec
85             );
86             }
87              
88              
89             sub format_isoz
90             {
91 4     4 1 17824 my ($self, $dt) = @_;
92 4 100       11 $dt = DateTime->now unless defined $dt;
93 4         203 $dt = $dt->clone->set_time_zone( 'UTC' );
94 4         265 sprintf("%04d-%02d-%02d %02d:%02d:%02dZ",
95             $dt->year, $dt->month, $dt->day,
96             $dt->hour, $dt->min, $dt->sec
97             );
98             }
99              
100             1;
101              
102              
103             __END__
104              
105             =head1 NAME
106              
107             DateTime::Format::HTTP - Date conversion routines
108              
109             =head1 SYNOPSIS
110              
111             use DateTime::Format::HTTP;
112              
113             my $class = 'DateTime::Format::HTTP';
114             $string = $class->format_datetime($dt); # Format as GMT ASCII time
115             $time = $class->parse_datetime($string); # convert ASCII date to machine time
116              
117             =head1 DESCRIPTION
118              
119             This module provides functions that deal the date formats used by the
120             HTTP protocol (and then some more).
121              
122             =head1 METHODS
123              
124             =head2 parse_datetime( $str [, $zone] )
125              
126             The parse_datetime() function converts a string to machine time. It throws
127             an error if the format of $str is unrecognized, or the time is outside
128             the representable range. The time formats recognized are listed below.
129              
130             The function also takes an optional second argument that specifies the
131             default time zone to use when converting the date. This parameter is
132             ignored if the zone is found in the date string itself. If this
133             parameter is missing, and the date string format does not contain
134             any zone specification, then the floating time zone is used.
135              
136             The zone should be one that is recognized by L<DateTime::TimeZone>.
137              
138             Actual parsing is done with the L<HTTP::Date> module. At the time of
139             writing it supports the formats listed next. Consult that module's
140             documentation in case the list has been changed.
141              
142             "Wed, 09 Feb 1994 22:23:32 GMT" -- HTTP format
143             "Thu Feb 3 17:03:55 GMT 1994" -- ctime(3) format
144             "Thu Feb 3 00:00:00 1994", -- ANSI C asctime() format
145             "Tuesday, 08-Feb-94 14:15:29 GMT" -- old rfc850 HTTP format
146             "Tuesday, 08-Feb-1994 14:15:29 GMT" -- broken rfc850 HTTP format
147              
148             "03/Feb/1994:17:03:55 -0700" -- common logfile format
149             "09 Feb 1994 22:23:32 GMT" -- HTTP format (no weekday)
150             "08-Feb-94 14:15:29 GMT" -- rfc850 format (no weekday)
151             "08-Feb-1994 14:15:29 GMT" -- broken rfc850 format (no weekday)
152              
153             "1994-02-03 14:15:29 -0100" -- ISO 8601 format
154             "1994-02-03 14:15:29" -- zone is optional
155             "1994-02-03" -- only date
156             "1994-02-03T14:15:29" -- Use T as separator
157             "19940203T141529Z" -- ISO 8601 compact format
158             "19940203" -- only date
159              
160             "08-Feb-94" -- old rfc850 HTTP format (no weekday, no time)
161             "08-Feb-1994" -- broken rfc850 HTTP format (no weekday, no time)
162             "09 Feb 1994" -- proposed new HTTP format (no weekday, no time)
163             "03/Feb/1994" -- common logfile format (no time, no offset)
164              
165             "Feb 3 1994" -- Unix 'ls -l' format
166             "Feb 3 17:03" -- Unix 'ls -l' format
167              
168             "11-15-96 03:52PM" -- Windows 'dir' format
169              
170             The parser ignores leading and trailing whitespace. It also allow the
171             seconds to be missing and the month to be numerical in most formats.
172              
173             If the year is missing, then we assume that the date is the first
174             matching date I<before> current month. If the year is given with only
175             2 digits, then parse_date() will select the century that makes the
176             year closest to the current date.
177              
178             =head2 format_datetime()
179              
180             The C<format_datetime()> method converts a L<DateTime> to a string. If
181             the function is called without an argument, it will use the current
182             time.
183              
184             The string returned is in the format preferred for the HTTP protocol.
185             This is a fixed length subset of the format defined by RFC 1123,
186             represented in Universal Time (GMT). An example of a time stamp
187             in this format is:
188              
189             Sun, 06 Nov 1994 08:49:37 GMT
190              
191             =head2 format_iso( [$time] )
192              
193             Same as format_datetime(), but returns a "YYYY-MM-DD hh:mm:ss"-formatted
194             string representing time in the local time zone. It is B<strongly>
195             recommended that you use C<format_isoz> or C<format_datetime> instead
196             (as these provide time zone indication).
197              
198             =head2 format_isoz( [$dt] )
199              
200             Same as format_iso(), but returns a "YYYY-MM-DD hh:mm:ssZ"-formatted
201             string representing Universal Time.
202              
203             =head1 THANKS
204              
205             Gisle Aas (GAAS) for writing L<HTTP::Date>.
206              
207             Iain, for never quite finishing C<HTTP::Date::XS>.
208              
209             =head1 SUPPORT
210              
211             Support for this module is provided via the datetime@perl.org email
212             list. See http://lists.perl.org/ for more details.
213              
214             Alternatively, log them via the CPAN RT system via the web or email:
215              
216             http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DateTime%3A%3AFormat%3A%3AHTTP
217             bug-datetime-format-http@rt.cpan.org
218              
219             This makes it much easier for me to track things and thus means
220             your problem is less likely to be neglected.
221              
222             =head1 LICENCE AND COPYRIGHT
223              
224             Copyright Iain Truskett, 2003. All rights reserved.
225             Sections of the documentation Gisle Aas, 1995-1999.
226             Changes since version 0.35 copyright David Rolsky, 2004.
227              
228             This library is free software; you can redistribute it and/or modify
229             it under the same terms as Perl itself, either Perl version 5.000 or,
230             at your option, any later version of Perl 5 you may have available.
231              
232             The full text of the licences can be found in the F<Artistic> and
233             F<COPYING> files included with this module, or in L<perlartistic> and
234             L<perlgpl> as supplied with Perl 5.8.1 and later.
235              
236              
237             =head1 AUTHOR
238              
239             Originally written by Iain Truskett <spoon@cpan.org>, who died on
240             December 29, 2003.
241              
242             Maintained by Dave Rolsky <autarch@urth.org> and Christiaan Kras <ckras@cpan.org>
243              
244             =head1 SEE ALSO
245              
246             C<datetime@perl.org> mailing list.
247              
248             http://datetime.perl.org/
249              
250             L<perl>, L<DateTime>, L<HTTP::Date>, L<DateTime::TimeZone>.
251              
252             =cut
253