File Coverage

blib/lib/XML/Loy/Date/RFC822.pm
Criterion Covered Total %
statement 42 47 89.3
branch 21 28 75.0
condition 4 9 44.4
subroutine 7 8 87.5
pod 4 4 100.0
total 78 96 81.2


line stmt bran cond sub pod time code
1             package XML::Loy::Date::RFC822;
2 1     1   689 use strict;
  1         2  
  1         25  
3 1     1   4 use warnings;
  1         1  
  1         55  
4              
5 1     1   6 use overload '""' => sub { shift->to_string }, fallback => 1;
  1     0   2  
  1         8  
  0         0  
6              
7             require Time::Local;
8              
9             # Days
10             my @DAYS = qw/Sun Mon Tue Wed Thu Fri Sat/;
11             my $DAYS = qr/(?:(?:Su|Mo)n|Wed|T(?:hu|ue)|Fri|Sat)/;
12              
13             # Months
14             my %MONTHS;
15             my @MONTHS = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
16             @MONTHS{@MONTHS} = (0 .. 11);
17              
18             # Zones
19             my %ZONE;
20             my $ZONE = qr/(?:(?:GM|U)|(?:([ECMP])([SD])))T/;
21             @ZONE{qw/E C M P/} = (4..7);
22              
23             my $RFC822_RE = qr/^\s*(?:$DAYS[a-z]*,)?\s*(\d+)\s+(\w+)\s+
24             (\d+)\s+(\d+):(\d+):(\d+)\s*(?:$ZONE|([-+]\d{4}))?\s*$/x;
25              
26             # Constructor
27             sub new {
28 11 100   11 1 492 my $self = bless {}, (ref $_[0] ? ref shift : shift);
29              
30             # Parse string
31 11         24 $self->parse(@_);
32              
33 11         22 return $self;
34             };
35              
36             # Parse date value
37             sub parse {
38 11     11 1 19 my ($self, $date) = @_;
39              
40 11 50       22 return $self unless defined $date;
41              
42 11 50       146 if ($date =~ /^\d+$/) {
    50          
43 0         0 $self->epoch($date);
44             }
45              
46             elsif (my ($mday, $month, $year,
47             $hour, $min, $sec,
48             $zone_1, $zone_2, $zone_o) = ($date =~ $RFC822_RE)) {
49              
50 11         15 my $epoch;
51 11         17 $month = $MONTHS{$month};
52              
53             # Set timezone offset
54 11         14 my $offset = 0;
55 11         10 my $offset_min = 0;
56              
57 11 100 66     33 if ($zone_1) {
    100          
58 5         9 $offset = $ZONE{$zone_1};
59 5 100       9 $offset++ if $zone_2 eq 'S';
60             }
61             elsif ($zone_o && $zone_o =~ /^([-+])\s*(\d\d)(\d\d)$/) {
62 3 50       7 if ($1 eq '-') {
63 0         0 $offset += $2;
64 0         0 $offset_min += $3;
65             }
66             else {
67 3         7 $offset -= $2;
68 3         7 $offset_min -= $3;
69             };
70             };
71              
72 11         14 eval {
73 11         21 $epoch = Time::Local::timegm($sec, $min, $hour,
74             $mday, $month, $year);
75             };
76              
77 11 100       271 $epoch += ($offset * 60 * 60) if $offset;
78 11 100       18 $epoch += ($offset_min * 60) if $offset_min;
79              
80 11 50 33     37 if (!$@ && $epoch > 0) {
81 11         18 $self->epoch($epoch);
82             };
83             };
84              
85 11         20 return $self;
86             };
87              
88             # return string
89             sub to_string {
90 5     5 1 7 my $self = shift;
91              
92 5         7 my $epoch = $self->epoch;
93 5 50       11 $epoch = time unless defined $epoch;
94 5         22 my ($sec, $min, $hour,
95             $mday, $month, $year, $wday) = gmtime $epoch;
96              
97             # Format
98 5         39 return sprintf(
99             "%s, %02d %s %04d %02d:%02d:%02d GMT",
100             $DAYS[$wday],
101             $mday,
102             $MONTHS[$month],
103             $year + 1900,
104             $hour,
105             $min,
106             $sec
107             );
108             };
109              
110              
111             # Epoch datetime
112             sub epoch {
113 22     22 1 36 my $self = shift;
114              
115             # Get epoch
116 22 100       58 return $self->{epoch} unless @_;
117              
118             # Set epoch if valid
119 11 50 33     51 if ($_[0] && $_[0] =~ /^[_\d]+$/) {
120              
121             # Fine to set
122 11         43 $self->{epoch} = shift;
123 11         19 return 1;
124             };
125              
126             # Fail to set
127 0           return;
128             };
129              
130              
131             1;
132              
133              
134             __END__