| 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__ |