line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# |
2
|
|
|
|
|
|
|
# Copyright (c) 2001,2002 Flavio Soibelmann Glock. |
3
|
|
|
|
|
|
|
# All rights reserved. |
4
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or |
5
|
|
|
|
|
|
|
# modify it under the same terms as Perl itself. |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
package Date::Tie; |
8
|
5
|
|
|
5
|
|
3364
|
use strict; |
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
185
|
|
9
|
5
|
|
|
5
|
|
4835
|
use Tie::Hash; |
|
5
|
|
|
|
|
5116
|
|
|
5
|
|
|
|
|
132
|
|
10
|
5
|
|
|
5
|
|
64
|
use Exporter; |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
181
|
|
11
|
5
|
|
|
5
|
|
4856
|
use POSIX; # floor() |
|
5
|
|
|
|
|
38134
|
|
|
5
|
|
|
|
|
36
|
|
12
|
5
|
|
|
5
|
|
24023
|
use Time::Local qw( timegm ); |
|
5
|
|
|
|
|
24787
|
|
|
5
|
|
|
|
|
623
|
|
13
|
5
|
|
|
5
|
|
38
|
use vars qw( @ISA %Frac %Max %Min %Mult $Infinity $VERSION $Resolution ); |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
16515
|
|
14
|
|
|
|
|
|
|
@ISA = qw( Tie::StdHash ); |
15
|
|
|
|
|
|
|
$VERSION = '0.20'; |
16
|
|
|
|
|
|
|
$Infinity = 999_999_999_999; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
%Frac = ( frac_hour => 60 * 60, frac_minute => 60, |
19
|
|
|
|
|
|
|
frac_second => 1, frac_epoch => 1 ); |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
%Mult = ( day => 24 * 60 * 60, hour => 60 * 60, minute => 60, |
22
|
|
|
|
|
|
|
second => 1, epoch => 1, |
23
|
|
|
|
|
|
|
monthday => 24 * 60 * 60, weekday => 24 * 60 * 60, yearday => 24 * 60 * 60, |
24
|
|
|
|
|
|
|
week => 7 * 24 * 60 * 60, tzhour => 60 * 60, tzminute => 60 ); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
%Max = ( year => $Infinity, yearday => 365, month => 12, |
27
|
|
|
|
|
|
|
monthday => 28, day => 28, week => 52, |
28
|
|
|
|
|
|
|
weekday => 7, hour => 23, minute => 59, |
29
|
|
|
|
|
|
|
second => 59, weekyear => $Infinity, epoch => $Infinity ); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
%Min = ( year => -$Infinity, yearday => 1, month => 1, |
32
|
|
|
|
|
|
|
monthday => 1, day => 1, week => 1, |
33
|
|
|
|
|
|
|
weekday => 1, hour => 0, minute => 0, |
34
|
|
|
|
|
|
|
second => 0, weekyear => -$Infinity, epoch => -$Infinity ); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub STORE { |
37
|
218
|
|
|
218
|
|
557
|
my ($self, $key, $value) = @_; |
38
|
218
|
|
|
|
|
223
|
my ($delta); |
39
|
218
|
50
|
|
|
|
470
|
$key = 'day' if $key eq 'monthday'; |
40
|
218
|
|
|
|
|
528
|
$value =~ tr/\,/\./; # translate comma to dot |
41
|
218
|
|
|
|
|
364
|
$value += 0; |
42
|
|
|
|
|
|
|
|
43
|
218
|
|
|
|
|
504
|
my $i_value = POSIX::floor($value); # get integer part |
44
|
|
|
|
|
|
|
|
45
|
218
|
100
|
|
|
|
687
|
if ($value =~ /e/i) { |
46
|
|
|
|
|
|
|
# SCIENTIFIC NOTATION! |
47
|
2
|
|
|
|
|
26
|
($value) = sprintf("%0.20f", $value) =~ /(.*?)0*$/; # without trailing zeroes |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# TODO: make 3 separate 'if's |
51
|
218
|
100
|
100
|
|
|
1292
|
if (($i_value != $value) or ($key eq 'frac') or (exists $Frac{$key})) { |
|
|
|
100
|
|
|
|
|
52
|
|
|
|
|
|
|
# has fractional part |
53
|
|
|
|
|
|
|
|
54
|
48
|
|
|
|
|
230
|
my ($frac) = $value =~ /\.(.*)/; # get fractional part as an 'integer' |
55
|
48
|
100
|
|
|
|
107
|
$frac = 0 unless defined $frac; # or get zero |
56
|
|
|
|
|
|
|
|
57
|
48
|
100
|
|
|
|
96
|
if ($key eq 'frac') { |
58
|
31
|
100
|
100
|
|
|
149
|
if (($value < 0) or ($value >= 1)) { |
59
|
|
|
|
|
|
|
# fractional overflow |
60
|
15
|
|
|
|
|
32
|
$self->STORE('second', $self->FETCH('second') + $i_value); |
61
|
|
|
|
|
|
|
# make sure frac is a positive number |
62
|
15
|
|
|
|
|
28
|
my $len_frac = length($frac); |
63
|
15
|
100
|
100
|
|
|
44
|
$frac = ('1' . '0' x $len_frac ) - $frac if ($value < 0) and ($frac != 0); |
64
|
15
|
|
|
|
|
38
|
$frac = '0' x ($len_frac - length($frac)) . $frac; |
65
|
|
|
|
|
|
|
} |
66
|
31
|
|
|
|
|
66
|
$self->{frac} = '.' . $frac; |
67
|
31
|
|
|
|
|
74
|
return; |
68
|
|
|
|
|
|
|
} |
69
|
17
|
100
|
|
|
|
39
|
if (exists $Frac{$key}) { |
70
|
|
|
|
|
|
|
|
71
|
16
|
|
|
|
|
60
|
my ($not_frac_key) = $key =~ /frac_(.*)/; |
72
|
16
|
|
|
|
|
37
|
$self->STORE($not_frac_key, $i_value); |
73
|
16
|
|
|
|
|
32
|
my $mult = $Frac{$key}; |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# make sure frac is a positive number |
76
|
16
|
|
|
|
|
21
|
my $len_frac = length($frac); |
77
|
16
|
100
|
66
|
|
|
57
|
$frac = ('1' . '0' x $len_frac ) - $frac if ($value < 0) and ($frac != 0); |
78
|
16
|
|
|
|
|
39
|
$frac = '0' x ($len_frac - length($frac)) . $frac; |
79
|
16
|
|
|
|
|
27
|
$frac = '.' . $frac; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# round last digit if the number is a fraction of '3': 1/3 1/9 ... |
82
|
|
|
|
|
|
|
# 9 digits is enough for nano-second resolution... |
83
|
16
|
100
|
|
|
|
39
|
if (length($frac) > 9) { |
84
|
2
|
|
|
|
|
7
|
my ($last_frac, $last_mult) = ($frac, $mult); |
85
|
|
|
|
|
|
|
|
86
|
2
|
|
|
|
|
7
|
foreach(0..3) { |
87
|
|
|
|
|
|
|
|
88
|
5
|
50
|
|
|
|
11
|
if ( $_ == 3 ) { |
89
|
|
|
|
|
|
|
# give-up rounding --- go back to original values ??? |
90
|
0
|
|
|
|
|
0
|
($frac, $mult) = ($last_frac, $last_mult); |
91
|
0
|
|
|
|
|
0
|
last; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# 000.$ |
95
|
5
|
100
|
|
|
|
34
|
if ($frac =~ /000.$/) { |
|
|
100
|
|
|
|
|
|
96
|
1
|
|
|
|
|
8
|
$frac =~ s/.$//; |
97
|
1
|
|
|
|
|
3
|
last; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
elsif ($frac =~ /999.$/) { |
100
|
1
|
|
|
|
|
6
|
my ($zeroes, $digit) = $frac =~ /\.(.*)(.)$/; |
101
|
1
|
|
|
|
|
6
|
$digit = '0.' . '0' x (length($zeroes)-1) . sprintf("%02d", 10 - $digit); |
102
|
1
|
|
|
|
|
3
|
$frac += $digit; |
103
|
1
|
|
|
|
|
2
|
last; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
else { |
106
|
3
|
|
|
|
|
10
|
$frac *= 3; |
107
|
3
|
|
|
|
|
6
|
$mult /= 3; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
} # foreach |
111
|
|
|
|
|
|
|
} # round 1/3 1/9 ... |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# zero units below this |
114
|
16
|
100
|
|
|
|
35
|
if ($not_frac_key eq 'hour') { |
115
|
4
|
|
|
|
|
17
|
$self->STORE('minute', 0); |
116
|
4
|
|
|
|
|
9
|
$self->STORE('second', 0); |
117
|
|
|
|
|
|
|
} |
118
|
16
|
100
|
|
|
|
31
|
if ($not_frac_key eq 'minute') { |
119
|
6
|
|
|
|
|
13
|
$self->STORE('second', 0); |
120
|
|
|
|
|
|
|
} |
121
|
16
|
|
|
|
|
63
|
$self->STORE('frac', $mult * $frac); |
122
|
|
|
|
|
|
|
|
123
|
16
|
|
|
|
|
53
|
return; |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# error - this unit does not allow a fractional part |
127
|
1
|
|
|
|
|
2
|
$key =~ s/frac_//; |
128
|
1
|
|
|
|
|
5
|
$value = POSIX::floor($value + 0.5); # round to integer |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
} # end: has fractional part |
131
|
|
|
|
|
|
|
|
132
|
171
|
100
|
|
|
|
324
|
if ($key eq 'tz') { |
133
|
|
|
|
|
|
|
# note: this must be "int", not "floor" !! |
134
|
12
|
|
|
|
|
73
|
STORE($self, 'tzminute', $value - 40 * int($value / 100)); # 60 - 100 ! |
135
|
12
|
|
|
|
|
33
|
return; |
136
|
|
|
|
|
|
|
} |
137
|
159
|
100
|
100
|
|
|
662
|
if (($key eq 'tzhour') or ($key eq 'tzminute')) { |
138
|
16
|
100
|
|
|
|
40
|
$self->{tz100} = 0 unless exists $self->{tz100}; |
139
|
16
|
100
|
|
|
|
31
|
if ($key eq 'tzhour') { |
140
|
3
|
|
|
|
|
6
|
$delta = $value * 3600 - $self->{tz100}; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
else { |
143
|
13
|
|
|
|
|
35
|
$delta = $value * 60 - $self->{tz100}; |
144
|
|
|
|
|
|
|
} |
145
|
16
|
|
|
|
|
29
|
$self->{tz100} += $delta; |
146
|
|
|
|
|
|
|
|
147
|
16
|
|
|
|
|
34
|
$self->STORE('epoch', FETCH($self, 'epoch') + $delta); |
148
|
16
|
|
|
|
|
31
|
return; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
143
|
100
|
|
|
|
271
|
if ($key eq 'utc_epoch') { |
152
|
1
|
|
50
|
|
|
7
|
%{$self} = ( utc_epoch => $value, epoch => $value + ($self->{tz100} || 0), |
|
1
|
|
|
|
|
6
|
|
153
|
|
|
|
|
|
|
tz100 => $self->{tz100}, frac => $self->{frac} ); |
154
|
1
|
|
|
|
|
5
|
return; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
142
|
100
|
|
|
|
246
|
if ($key eq 'epoch') { |
158
|
27
|
|
|
|
|
61
|
$self->{epoch} = $value; |
159
|
|
|
|
|
|
|
# remove all other keys (now invalid) |
160
|
27
|
|
|
|
|
53
|
%{$self} = ( epoch => $self->{epoch}, tz100 => $self->{tz100}, frac => $self->{frac} ); |
|
27
|
|
|
|
|
161
|
|
161
|
27
|
|
|
|
|
69
|
return; |
162
|
|
|
|
|
|
|
} |
163
|
115
|
100
|
|
|
|
215
|
if ($key eq 'month') { |
164
|
21
|
50
|
66
|
|
|
119
|
return if (exists $self->{month}) and ($self->{month} == $value); |
165
|
21
|
100
|
|
|
|
57
|
$self->FETCH('day') unless exists $self->{day}; # save 'day' before deleting epoch! |
166
|
|
|
|
|
|
|
|
167
|
21
|
|
|
|
|
47
|
delete $self->{epoch}; |
168
|
21
|
|
|
|
|
29
|
delete $self->{utc_epoch}; |
169
|
21
|
|
|
|
|
33
|
delete $self->{weekday}; |
170
|
21
|
|
|
|
|
31
|
delete $self->{yearday}; |
171
|
21
|
|
|
|
|
25
|
delete $self->{week}; |
172
|
21
|
|
|
|
|
25
|
delete $self->{weekyear}; |
173
|
|
|
|
|
|
|
|
174
|
21
|
100
|
100
|
|
|
175
|
if (($value >= $Min{$key}) and ($value <= $Max{$key})) { |
175
|
17
|
|
|
|
|
51
|
$self->{$key} = $value; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
else { |
178
|
4
|
|
|
|
|
47
|
$value -= 1; |
179
|
4
|
|
|
|
|
13
|
$self->{year} += POSIX::floor( $value / 12); |
180
|
4
|
|
|
|
|
7
|
$self->{month} = 1 + $value % 12; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
21
|
100
|
|
|
|
60
|
if ($self->{day} >= 29) { |
184
|
5
|
|
|
|
|
16
|
my ($tmp_month) = $self->FETCH('month'); |
185
|
|
|
|
|
|
|
# check for day overflow |
186
|
5
|
|
|
|
|
31
|
$self->STORE('day',$self->{day}); |
187
|
5
|
|
|
|
|
12
|
$self->FETCH('month'); |
188
|
5
|
50
|
|
|
|
18
|
if ($tmp_month != $self->{month}) { |
189
|
0
|
|
|
|
|
0
|
$self->STORE('day', 0); |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
21
|
|
|
|
|
60
|
return; |
194
|
|
|
|
|
|
|
} |
195
|
94
|
100
|
|
|
|
184
|
if ($key eq 'year') { |
196
|
13
|
50
|
66
|
|
|
69
|
return if (exists $self->{year}) and ($self->{year} == $value); |
197
|
13
|
100
|
|
|
|
41
|
$self->FETCH('day') unless exists $self->{day}; # save 'day' before deleting epoch! |
198
|
|
|
|
|
|
|
|
199
|
13
|
|
|
|
|
26
|
delete $self->{epoch}; |
200
|
13
|
|
|
|
|
23
|
delete $self->{utc_epoch}; |
201
|
13
|
|
|
|
|
26
|
delete $self->{weekday}; |
202
|
13
|
|
|
|
|
29
|
delete $self->{yearday}; |
203
|
13
|
|
|
|
|
19
|
delete $self->{week}; |
204
|
13
|
|
|
|
|
62
|
delete $self->{weekyear}; |
205
|
|
|
|
|
|
|
|
206
|
13
|
|
|
|
|
30
|
$self->{year} = $value; |
207
|
|
|
|
|
|
|
|
208
|
13
|
100
|
|
|
|
35
|
if ($self->{day} >= 29) { |
209
|
2
|
|
|
|
|
6
|
my ($tmp_month) = $self->FETCH('month'); |
210
|
|
|
|
|
|
|
# check for day overflow |
211
|
2
|
|
|
|
|
8
|
$self->STORE('day',$self->{day}); |
212
|
2
|
|
|
|
|
9
|
$self->FETCH('month'); |
213
|
2
|
50
|
|
|
|
9
|
if ($tmp_month != $self->{month}) { |
214
|
0
|
|
|
|
|
0
|
$self->STORE('day', 0); |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
13
|
|
|
|
|
39
|
return; |
219
|
|
|
|
|
|
|
} |
220
|
81
|
100
|
|
|
|
159
|
if ($key eq 'weekyear') { |
221
|
1
|
50
|
|
|
|
5
|
my $week = exists $self->{week} ? $self->{week} : FETCH($self, 'week'); |
222
|
1
|
50
|
|
|
|
5
|
my $weekyear = exists $self->{weekyear} ? $self->{weekyear} : FETCH($self, 'weekyear'); |
223
|
1
|
50
|
|
|
|
4
|
FETCH($self, 'epoch') unless exists $self->{epoch}; |
224
|
1
|
|
|
|
|
4
|
$self->{epoch} += 52 * $Mult{week} * ($value - $weekyear); |
225
|
1
|
|
|
|
|
3
|
%{$self} = ( epoch => $self->{epoch}, tz100 => $self->{tz100}, frac => $self->{frac} ); |
|
1
|
|
|
|
|
7
|
|
226
|
1
|
|
|
|
|
3
|
my $week2 = FETCH($self, 'week'); |
227
|
1
|
|
|
|
|
5
|
while ($week2 != $week) { |
228
|
0
|
|
|
|
|
0
|
STORE($self, 'week', $week2 + ($value <=> $weekyear) ); |
229
|
0
|
|
|
|
|
0
|
$week2 = FETCH($self, 'week'); |
230
|
|
|
|
|
|
|
} |
231
|
1
|
|
|
|
|
4
|
return; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
# all other keys |
234
|
|
|
|
|
|
|
|
235
|
80
|
100
|
|
|
|
180
|
unless ( exists $self->{$key} ) { |
236
|
5
|
|
|
|
|
12
|
FETCH($self, $key); |
237
|
|
|
|
|
|
|
} |
238
|
80
|
|
|
|
|
125
|
$delta = $value - $self->{$key}; |
239
|
|
|
|
|
|
|
|
240
|
80
|
100
|
100
|
|
|
763
|
if (($value >= $Min{$key}) and ($value <= $Max{$key}) and |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
241
|
|
|
|
|
|
|
($key ne 'weekday') and ($key ne 'yearday') and ($key ne 'week')) { |
242
|
55
|
100
|
|
|
|
123
|
if (exists $self->{epoch}) { |
243
|
33
|
|
|
|
|
68
|
$self->{epoch} += $delta * $Mult{$key}; |
244
|
33
|
|
|
|
|
72
|
delete $self->{utc_epoch}; |
245
|
|
|
|
|
|
|
} |
246
|
55
|
|
|
|
|
108
|
$self->{$key} = $value; |
247
|
|
|
|
|
|
|
# update dependencies |
248
|
55
|
100
|
|
|
|
115
|
if ($key eq 'day') { |
249
|
10
|
|
|
|
|
15
|
delete $self->{weekday}; |
250
|
10
|
|
|
|
|
16
|
delete $self->{yearday}; |
251
|
10
|
|
|
|
|
20
|
delete $self->{weekyear}; |
252
|
10
|
|
|
|
|
21
|
delete $self->{week}; |
253
|
|
|
|
|
|
|
} |
254
|
55
|
|
|
|
|
123
|
return; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
# handle overflow |
257
|
|
|
|
|
|
|
# init epoch key |
258
|
25
|
100
|
|
|
|
66
|
unless ( exists $self->{epoch} ) { |
259
|
11
|
|
|
|
|
25
|
FETCH($self, 'epoch'); |
260
|
|
|
|
|
|
|
} |
261
|
25
|
|
|
|
|
55
|
$self->{epoch} += $delta * $Mult{$key}; |
262
|
|
|
|
|
|
|
# remove all other keys (now invalid) |
263
|
25
|
|
|
|
|
49
|
%{$self} = ( epoch => $self->{epoch}, tz100 => $self->{tz100}, frac => $self->{frac} ); |
|
25
|
|
|
|
|
141
|
|
264
|
25
|
|
|
|
|
64
|
return; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub FETCH { |
268
|
600
|
|
|
600
|
|
1332
|
my ($self, $key) = @_; |
269
|
600
|
|
|
|
|
599
|
my ($value); |
270
|
600
|
50
|
|
|
|
1109
|
$key = 'day' if $key eq 'monthday'; |
271
|
|
|
|
|
|
|
|
272
|
600
|
100
|
|
|
|
998
|
if ($key eq 'frac') { |
273
|
50
|
|
|
|
|
253
|
return $self->{frac}; |
274
|
|
|
|
|
|
|
} |
275
|
550
|
100
|
|
|
|
1210
|
if (exists $Frac{$key}) { |
276
|
18
|
|
|
|
|
83
|
my ($not_frac_key) = $key =~ /frac_(.*)/; |
277
|
18
|
|
|
|
|
55
|
$value = $self->FETCH($not_frac_key); |
278
|
18
|
100
|
|
|
|
66
|
return $value . $self->{frac} if ($Frac{$key} == 1); # no rounding |
279
|
|
|
|
|
|
|
# units below this |
280
|
15
|
100
|
|
|
|
32
|
if ($not_frac_key eq 'hour') { |
281
|
10
|
|
|
|
|
21
|
$value += $self->FETCH('minute') / 60.0; |
282
|
10
|
|
|
|
|
24
|
$value += $self->FETCH('second') / 3600.0; |
283
|
|
|
|
|
|
|
} |
284
|
15
|
100
|
|
|
|
34
|
if ($not_frac_key eq 'minute') { |
285
|
5
|
|
|
|
|
10
|
$value += $self->FETCH('second') / 60.0; |
286
|
|
|
|
|
|
|
} |
287
|
15
|
|
|
|
|
32
|
$value += $self->FETCH('frac') / $Frac{$key}; |
288
|
15
|
100
|
66
|
|
|
84
|
$value = '0' . $value if ($value >= 0) and ($value < 10); # format output |
289
|
15
|
100
|
|
|
|
82
|
$value = $value . '.0' unless ($value =~ /\./); # format output |
290
|
15
|
|
|
|
|
128
|
return $value; |
291
|
|
|
|
|
|
|
} |
292
|
532
|
100
|
|
|
|
913
|
if ($key eq 'tz') { |
293
|
13
|
|
|
|
|
24
|
my ($h, $m) = (FETCH($self, 'tzhour'), FETCH($self, 'tzminute')); |
294
|
13
|
100
|
|
|
|
35
|
my $s = $self->{tz100} < 0 ? '-' : '+'; |
295
|
13
|
|
|
|
|
79
|
return $s . substr($h,1,2) . sprintf("%02d", abs($m)); |
296
|
|
|
|
|
|
|
} |
297
|
519
|
100
|
|
|
|
891
|
if ($key eq 'tzhour') { |
298
|
19
|
100
|
|
|
|
48
|
my $s = $self->{tz100} < 0 ? '-' : '+'; |
299
|
|
|
|
|
|
|
# note: this must be "int", not "floor" !! |
300
|
19
|
|
|
|
|
32
|
$value = int($self->{tz100} / 3600); |
301
|
19
|
|
|
|
|
278
|
return $s . sprintf("%02d", abs($value)); |
302
|
|
|
|
|
|
|
} |
303
|
500
|
100
|
|
|
|
829
|
if ($key eq 'tzminute') { |
304
|
17
|
100
|
|
|
|
39
|
my $s = $self->{tz100} < 0 ? '-' : '+'; |
305
|
|
|
|
|
|
|
# note: this must be "int", not "floor" !! |
306
|
17
|
|
|
|
|
33
|
$value = int( ( $self->{tz100} - 3600 * int($self->{tz100} / 3600) ) / 60 ); |
307
|
17
|
|
|
|
|
69
|
return $s . sprintf("%02d", abs($value)); |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
483
|
100
|
|
|
|
1002
|
unless (exists($self->{$key}) ) { |
311
|
|
|
|
|
|
|
# create key if possible |
312
|
78
|
100
|
100
|
|
|
328
|
if (( $key eq 'epoch') or not exists $self->{epoch} ) { |
313
|
26
|
|
|
|
|
31
|
my ($year, $month, $day, $hour, $minute, $second); |
314
|
26
|
100
|
|
|
|
79
|
$day = exists $self->{day} ? $self->{day} : 1; |
315
|
26
|
100
|
|
|
|
80
|
$month = exists $self->{month} ? $self->{month} - 1 : 0; |
316
|
26
|
100
|
|
|
|
63
|
$year = exists $self->{year} ? $self->{year} - 1900 : 0; |
317
|
26
|
100
|
|
|
|
63
|
$hour = exists $self->{hour} ? $self->{hour} : 0; |
318
|
26
|
100
|
|
|
|
67
|
$minute = exists $self->{minute} ? $self->{minute} : 0; |
319
|
26
|
100
|
|
|
|
74
|
$second = exists $self->{second} ? $self->{second} : 0; |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# TODO: test for month overflow (error when using perl 5.8.0) |
322
|
|
|
|
|
|
|
# Day '31' out of range 1..30 at lib/Date/Tie.pm line 383 |
323
|
26
|
|
|
|
|
44
|
eval { $self->{epoch} = timegm( $second, $minute, $hour, $day, $month, $year ); }; |
|
26
|
|
|
|
|
94
|
|
324
|
|
|
|
|
|
|
# warn $@ if $@; |
325
|
26
|
|
|
|
|
1488
|
while ($@ =~ /Day \'\d+\' out of range/ ) { |
326
|
6
|
|
|
|
|
555
|
$day = $self->{day}--; |
327
|
6
|
|
|
|
|
12
|
eval { $self->{epoch} = timegm( $second, $minute, $hour, $day, $month, $year ); }; |
|
6
|
|
|
|
|
19
|
|
328
|
|
|
|
|
|
|
# warn $@ if $@; |
329
|
|
|
|
|
|
|
} |
330
|
26
|
100
|
|
|
|
224
|
return $self->{epoch} if $key eq 'epoch'; # ??? |
331
|
|
|
|
|
|
|
} |
332
|
56
|
|
|
|
|
427
|
( $self->{second}, $self->{minute}, $self->{hour}, |
333
|
|
|
|
|
|
|
$self->{day}, $self->{month}, $self->{year}, |
334
|
|
|
|
|
|
|
$self->{weekday}, $self->{yearday} ) = gmtime($self->{epoch}); |
335
|
56
|
|
|
|
|
132
|
$self->{year} += 1900; |
336
|
56
|
|
|
|
|
71
|
$self->{month}++; |
337
|
56
|
100
|
|
|
|
129
|
$self->{weekday} = 7 unless $self->{weekday}; |
338
|
56
|
|
|
|
|
82
|
$self->{yearday}++; |
339
|
56
|
|
100
|
|
|
228
|
$self->{utc_epoch} = $self->{epoch} - ( $self->{tz100} || 0 ); |
340
|
|
|
|
|
|
|
|
341
|
56
|
100
|
100
|
|
|
271
|
if ( $key eq 'week' || $key eq 'weekyear' ) { |
342
|
6
|
|
|
|
|
25
|
$self->{week} = POSIX::floor( ($self->{yearday} - $self->{weekday} + 10) / 7 ); |
343
|
6
|
100
|
|
|
|
20
|
if ($self->{yearday} > 361) { |
344
|
|
|
|
|
|
|
# find out next year's jan-04 weekday |
345
|
2
|
|
|
|
|
10
|
tie my %tmp, 'Date::Tie', year => ($self->{year} + 1), month => '01', day => '04'; |
346
|
|
|
|
|
|
|
# jan-04 weekday: 1 2 3 4 5 6 7 |
347
|
2
|
|
|
|
|
7
|
my @wk1 = qw( 29 32 32 32 32 31 30 29 ); |
348
|
2
|
|
|
|
|
12
|
my $last_day = $wk1[$tmp{weekday}]; |
349
|
2
|
50
|
|
|
|
25
|
$self->{week} = 1 if ($self->{day} >= $last_day); |
350
|
|
|
|
|
|
|
} |
351
|
6
|
50
|
|
|
|
16
|
if ( $self->{week} == 0 ) { |
352
|
0
|
|
|
|
|
0
|
my @t = gmtime( timegm( 0,0,0, 31,11,($self->{year} - 1) ) ); |
353
|
0
|
|
|
|
|
0
|
$self->{week} = POSIX::floor( ($t[7] - $t[6] + 11) / 7 ); |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
6
|
|
|
|
|
14
|
$self->{weekyear} = $self->{year}; |
357
|
6
|
100
|
66
|
|
|
30
|
$self->{weekyear}++ if ($self->{week} < 2) and ($self->{month} > 10); |
358
|
6
|
50
|
33
|
|
|
25
|
$self->{weekyear}-- if ($self->{week} > 50) and ($self->{month} < 2); |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
} # create keys |
361
|
|
|
|
|
|
|
|
362
|
461
|
|
|
|
|
664
|
$value = $self->{$key}; |
363
|
461
|
100
|
|
|
|
837
|
return $value if $key eq 'weekday'; |
364
|
454
|
100
|
|
|
|
777
|
return $value if $key eq 'utc_epoch'; |
365
|
449
|
50
|
|
|
|
2778
|
return sprintf("%02d", $value) if $key ne 'yearday'; |
366
|
0
|
|
|
|
|
0
|
return sprintf("%03d", $value); |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub TIEHASH { |
370
|
18
|
|
|
18
|
|
140
|
my $self = bless {}, shift; |
371
|
18
|
|
|
|
|
25
|
my ($tmp1, $tmp2); |
372
|
18
|
|
|
|
|
161
|
$self->{frac} = '.0'; |
373
|
18
|
|
|
|
|
37
|
$self->{tz100} = 0; |
374
|
18
|
|
|
|
|
136
|
( $self->{second}, $self->{minute}, $self->{hour}, |
375
|
|
|
|
|
|
|
$self->{day}, $self->{month}, $self->{year}, |
376
|
|
|
|
|
|
|
$self->{weekday}, $self->{yearday} ) = gmtime(); |
377
|
18
|
|
|
|
|
48
|
$self->{year} += 1900; |
378
|
18
|
|
|
|
|
28
|
$self->{month}++; |
379
|
18
|
50
|
|
|
|
50
|
$self->{weekday} = 7 unless $self->{weekday}; |
380
|
18
|
|
|
|
|
25
|
$self->{yearday}++; |
381
|
18
|
|
|
|
|
70
|
while ($#_ > -1) { |
382
|
34
|
|
|
|
|
69
|
($tmp1, $tmp2) = (shift, shift); |
383
|
34
|
|
|
|
|
63
|
STORE ($self, $tmp1, $tmp2); |
384
|
|
|
|
|
|
|
} |
385
|
18
|
|
|
|
|
73
|
return $self; |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub new { |
389
|
6
|
|
|
6
|
0
|
21
|
my $class = shift; |
390
|
6
|
|
|
|
|
8
|
my @parent; |
391
|
6
|
100
|
|
|
|
29
|
@parent = %$class if ref $class; |
392
|
6
|
|
|
|
|
16
|
push @parent, @_; |
393
|
6
|
|
66
|
|
|
31
|
my $self = bless {}, ref $class || $class; |
394
|
6
|
|
|
|
|
19
|
tie %$self, 'Date::Tie', @parent; |
395
|
6
|
|
|
|
|
21
|
return $self; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
# FIRSTKEY added to support recommended assignment order: set timezone, then epoch and fractional seconds |
399
|
|
|
|
|
|
|
# tie my %b, 'Date::Tie', tz => $d{tz}, epoch => $d{epoch}, frac => $d{frac}; |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
sub FIRSTKEY { |
402
|
4
|
|
|
4
|
|
12
|
my ($self) = @_; |
403
|
4
|
|
|
|
|
17
|
return 'tz'; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
sub NEXTKEY { |
407
|
12
|
|
|
12
|
|
15
|
my ($self, $lastkey) = @_; |
408
|
12
|
100
|
|
|
|
33
|
return 'epoch' if $lastkey eq 'tz'; |
409
|
8
|
100
|
|
|
|
25
|
return 'frac' if $lastkey eq 'epoch'; |
410
|
4
|
|
|
|
|
24
|
return undef; |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
# This is for debugging only ! |
414
|
|
|
|
|
|
|
# sub iso { my $self = shift; return $self->{year} . '-' . $self->{month} . '-' . $self->{day} . " $self->{weekyear}-W$self->{week}-$self->{weekday}"; } |
415
|
|
|
|
|
|
|
# sub debug { return; my $self = shift; return join(':',%{$self}); } |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
1; |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
__END__ |