File Coverage

blib/lib/WDDX/Datetime.pm
Criterion Covered Total %
statement 12 87 13.7
branch 0 30 0.0
condition n/a
subroutine 4 19 21.0
pod n/a
total 16 136 11.7


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             #
3             # $Id: Datetime.pm,v 1.1.1.1 2003/10/28 16:04:37 andy Exp $
4             #
5             # This code is copyright 1999-2000 by Scott Guelich
6             # and is distributed according to the same conditions as Perl itself
7             # Please visit http://www.scripted.com/wddx/ for more information
8             #
9              
10             package WDDX::Datetime;
11              
12             # Auto-inserted by build scripts
13             $VERSION = "1.01";
14              
15 1     1   1659 use strict;
  1         2  
  1         32  
16 1     1   6 use Carp;
  1         1  
  1         56  
17 1     1   1549 use Time::Local;
  1         2242  
  1         653  
18              
19             require WDDX;
20              
21             { my $i_hate_the_w_flag_sometimes = [
22             $WDDX::PACKET_HEADER,
23             $WDDX::PACKET_FOOTER,
24             $WDDX::Datetime::VERSION
25             ] }
26              
27             1;
28              
29              
30             #/-----------------------------------------------------------------------
31             # Public Methods
32             #
33              
34             sub new {
35 0     0     my( $class, $value ) = @_;
36            
37 0 0         croak "You must supply the date in (integer) seconds when creating " .
38             "Datetime objects\n" if $value =~ /\D/;
39            
40 0           my $self = {
41             value => $value,
42             tz_info => 1,
43             };
44            
45 0           bless $self, $class;
46 0           return $self;
47             }
48              
49              
50             sub type {
51 0     0     return "datetime";
52             }
53              
54              
55             sub as_packet {
56 0     0     my( $self ) = @_;
57 0           my $output = $WDDX::PACKET_HEADER .
58             $self->_serialize .
59             $WDDX::PACKET_FOOTER;
60             }
61              
62              
63             sub as_scalar {
64 0     0     my( $self ) = @_;
65 0           return $self->_deserialize;
66             }
67              
68              
69             sub as_javascript {
70 0     0     my( $self, $js_var ) = @_;
71 0           my $time_in_secs = $self->{value};
72            
73 0           my( $sec, $min, $hour, $day, $mon, $year ) = localtime( $time_in_secs );
74 0           return "$js_var=new Date($year,$mon,$day,$hour,$min,$sec);";
75             }
76              
77              
78             # Timezone info is included in new packets by default
79             sub use_timezone_info {
80 0     0     my( $self, $arg ) = @_;
81 0 0         $self->{tz_info} = ( $arg ? 1 : 0 ) if defined $arg;
    0          
82 0           return $self->{tz_info}
83             }
84              
85             #/-----------------------------------------------------------------------
86             # Private Methods
87             #
88              
89             sub is_parser {
90 0     0     return 0;
91             }
92              
93              
94             sub _serialize {
95 0     0     my( $self ) = @_;
96 0           my $time_in_secs = $self->{value};
97            
98 0           my( $sec, $min, $hour, $day, $mon, $year ) = localtime( $time_in_secs );
99 0           my $output = sprintf "%02d-%02d-%02dT%02d:%02d:%02d",
100             $year + 1900, $mon + 1, $day, $hour, $min, $sec;
101 0 0         $output .= tz_info() if $self->use_timezone_info;
102 0           $output .= "";
103 0           return $output;
104             }
105              
106              
107             sub _deserialize {
108 0     0     my( $self ) = @_;
109 0           return $self->{value};
110             }
111              
112              
113             # This generates the timezone info by looking at the difference between
114             # gmtime and localtime; uses functions from standard Time::Local module
115             sub tz_info {
116 0     0     my $local = timelocal( localtime );
117 0           my $gmt = timegm ( localtime );
118            
119 0           my $diff = abs( $gmt - $local );
120 0           my $hrs = int( $diff / ( 60 * 60 ) );
121 0           my $mins = int( $diff / 60 ) - $hrs * 60;
122 0 0         my $dir = $gmt - $local >= 0 ? '+' : '-';
123            
124 0           return sprintf "$dir%0.2d:%0.2d", $hrs, $mins;
125             }
126              
127              
128             #/-----------------------------------------------------------------------
129             # Parsing Code
130             #
131              
132             package WDDX::Datetime::Parser;
133              
134 1     1   7 use Time::Local;
  1         2  
  1         626  
135              
136              
137             sub new {
138 0     0     my $class = shift;
139            
140 0           my $self = {
141             value => "",
142             tz_info => undef
143             };
144 0           return bless $self, $class;
145             }
146              
147              
148             sub start_tag {
149 0     0     my( $self, $element, $attribs ) = @_;
150            
151 0 0         unless ( $element eq "datetime" ) {
152 0           die "<$element> not allowed within element\n";
153             }
154            
155 0           return $self;
156             }
157              
158              
159             sub end_tag {
160 0     0     my( $self, $element ) = @_;
161 0           my $value = $self->{value};
162 0           my $time_in_secs;
163            
164 0 0         unless ( $element eq "datetime" ) {
165 0           die " not allowed within element\n";
166             }
167            
168 0 0         my( $yr, $mon, $day, $hr, $min, $sec, $tz_dir, $tz_hr, $tz_min ) =
169             $value =~ /^(\d{4})-(\d+)-(\d+)T(\d+):(\d+):(\d+)(?:([+-])(\d+):(\d+))?$/i
170             or die "Invalid dateTime value: '$value'\n";
171            
172             # Note: this isn't a Y2K bug; years >= 2000 represented w/ 3 digits
173 0           $yr -= 1900;
174 0 0         die "DateTime values prior to 1900-01-01 are not supported\n" if $yr < 0;
175 0           $mon--;
176            
177 0           eval {
178 0           $time_in_secs = timelocal( $sec, $min, $hr, $day, $mon, $yr );
179             };
180 0 0         if ( $@ ) {
181 0           die "Invalid dateTime value. $@\n";
182             }
183 0 0         if ( $time_in_secs < 0 ) {
184 0           die "DateTime value exceeds the integer limit for this machine\n";
185             }
186            
187 0 0         if ( $tz_dir ) {
188             # Adjust according to timezone info in packet
189 0 0         if ( $tz_dir eq '+' ) {
190 0           $time_in_secs += $tz_min * 60;
191 0           $time_in_secs += $tz_hr * 60 * 60;
192             }
193             else {
194 0           $time_in_secs -= $tz_min * 60;
195 0           $time_in_secs -= $tz_hr * 60 * 60;
196             }
197            
198             # Readjust to compensate for our own timezone diff relative to UTC/GMT
199 0           my $tz_info = WDDX::Datetime::tz_info();
200 0           my( $loc_dir, $loc_hr, $loc_min ) = $tz_info =~ /([+-])(\d+):(\d+)/;
201            
202 0 0         if ( $loc_dir eq '-' ) {
203 0           $time_in_secs += $loc_min * 60;
204 0           $time_in_secs += $loc_hr * 60 * 60;
205             }
206             else {
207 0           $time_in_secs -= $loc_min * 60;
208 0           $time_in_secs -= $loc_hr * 60 * 60;
209             }
210             }
211            
212 0           $self = new WDDX::Datetime( $time_in_secs );
213 0 0         $self->use_timezone_info( 0 ) unless $tz_dir;
214            
215 0           return $self;
216             }
217              
218              
219             sub append_data {
220 0     0     my( $self, $data ) = @_;
221 0           $self->{value} .= $data;
222             }
223              
224              
225             sub is_parser {
226 0     0     return 1;
227             }
228