| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
package DateTimeX::Lite; |
|
3
|
18
|
|
|
18
|
|
114
|
use strict; |
|
|
18
|
|
|
|
|
40
|
|
|
|
18
|
|
|
|
|
861
|
|
|
4
|
18
|
|
|
18
|
|
109
|
use warnings; |
|
|
18
|
|
|
|
|
46
|
|
|
|
18
|
|
|
|
|
746
|
|
|
5
|
18
|
|
|
18
|
|
134
|
use Carp (); |
|
|
18
|
|
|
|
|
51
|
|
|
|
18
|
|
|
|
|
519
|
|
|
6
|
18
|
|
|
18
|
|
120
|
use Scalar::Util qw(blessed); |
|
|
18
|
|
|
|
|
43
|
|
|
|
18
|
|
|
|
|
1694
|
|
|
7
|
18
|
|
|
|
|
268
|
use overload ( 'fallback' => 1, |
|
8
|
|
|
|
|
|
|
'-' => '_subtract_overload', |
|
9
|
|
|
|
|
|
|
'+' => '_add_overload', |
|
10
|
18
|
|
|
18
|
|
212
|
); |
|
|
18
|
|
|
|
|
53
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
sub subtract_datetime |
|
14
|
|
|
|
|
|
|
{ |
|
15
|
51
|
|
|
51
|
0
|
5527
|
my $dt1 = shift; |
|
16
|
51
|
|
|
|
|
87
|
my $dt2 = shift; |
|
17
|
|
|
|
|
|
|
|
|
18
|
51
|
100
|
|
|
|
198
|
$dt2 = $dt2->clone->set_time_zone( $dt1->time_zone ) |
|
19
|
|
|
|
|
|
|
unless $dt1->time_zone->name eq $dt2->time_zone->name; |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# We only want a negative duration if $dt2 > $dt1 ($self) |
|
22
|
51
|
100
|
|
|
|
312
|
my ( $bigger, $smaller, $negative ) = |
|
23
|
|
|
|
|
|
|
( $dt1 >= $dt2 ? |
|
24
|
|
|
|
|
|
|
( $dt1, $dt2, 0 ) : |
|
25
|
|
|
|
|
|
|
( $dt2, $dt1, 1 ) |
|
26
|
|
|
|
|
|
|
); |
|
27
|
|
|
|
|
|
|
|
|
28
|
51
|
|
66
|
|
|
162
|
my $is_floating = $dt1->time_zone->is_floating && |
|
29
|
|
|
|
|
|
|
$dt2->time_zone->is_floating; |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
|
32
|
51
|
|
|
|
|
114
|
my $minute_length = 60; |
|
33
|
51
|
100
|
|
|
|
125
|
unless ($is_floating) |
|
34
|
|
|
|
|
|
|
{ |
|
35
|
39
|
|
|
|
|
115
|
my ( $utc_rd_days, $utc_rd_secs ) = $smaller->utc_rd_values; |
|
36
|
|
|
|
|
|
|
|
|
37
|
39
|
100
|
66
|
|
|
174
|
if ( $utc_rd_secs >= 86340 && ! $is_floating ) |
|
38
|
|
|
|
|
|
|
{ |
|
39
|
|
|
|
|
|
|
# If the smaller of the two datetimes occurs in the last |
|
40
|
|
|
|
|
|
|
# UTC minute of the UTC day, then that minute may not be |
|
41
|
|
|
|
|
|
|
# 60 seconds long. If we need to subtract a minute from |
|
42
|
|
|
|
|
|
|
# the larger datetime's minutes count in order to adjust |
|
43
|
|
|
|
|
|
|
# the seconds difference to be positive, we need to know |
|
44
|
|
|
|
|
|
|
# how long that minute was. If one of the datetimes is |
|
45
|
|
|
|
|
|
|
# floating, we just assume a minute is 60 seconds. |
|
46
|
|
|
|
|
|
|
|
|
47
|
5
|
|
|
|
|
27
|
$minute_length = DateTimeX::Lite::LeapSecond::day_length($utc_rd_days) - 86340; |
|
48
|
|
|
|
|
|
|
} |
|
49
|
|
|
|
|
|
|
} |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# This is a gross hack that basically figures out if the bigger of |
|
52
|
|
|
|
|
|
|
# the two datetimes is the day of a DST change. If it's a 23 hour |
|
53
|
|
|
|
|
|
|
# day (switching _to_ DST) then we subtract 60 minutes from the |
|
54
|
|
|
|
|
|
|
# local time. If it's a 25 hour day then we add 60 minutes to the |
|
55
|
|
|
|
|
|
|
# local time. |
|
56
|
|
|
|
|
|
|
# |
|
57
|
|
|
|
|
|
|
# This produces the most "intuitive" results, though there are |
|
58
|
|
|
|
|
|
|
# still reversibility problems with the resultant duration. |
|
59
|
|
|
|
|
|
|
# |
|
60
|
|
|
|
|
|
|
# However, if the two objects are on the same (local) date, and we |
|
61
|
|
|
|
|
|
|
# are not crossing a DST change, we don't want to invoke the hack |
|
62
|
|
|
|
|
|
|
# - see 38local-subtract.t |
|
63
|
51
|
|
|
|
|
197
|
my $bigger_min = $bigger->hour * 60 + $bigger->minute; |
|
64
|
51
|
100
|
100
|
|
|
183
|
if ( $bigger->time_zone->has_dst_changes |
|
|
|
|
66
|
|
|
|
|
|
65
|
|
|
|
|
|
|
&& ( $bigger->ymd ne $smaller->ymd |
|
66
|
|
|
|
|
|
|
|| $bigger->is_dst != $smaller->is_dst ) |
|
67
|
|
|
|
|
|
|
) |
|
68
|
|
|
|
|
|
|
{ |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
$bigger_min -= 60 |
|
71
|
|
|
|
|
|
|
# it's a 23 hour (local) day |
|
72
|
|
|
|
|
|
|
if ( $bigger->is_dst |
|
73
|
|
|
|
|
|
|
&& |
|
74
|
13
|
100
|
66
|
|
|
47
|
do { local $@; |
|
|
7
|
|
|
|
|
13
|
|
|
75
|
7
|
|
|
|
|
13
|
my $prev_day = eval { $bigger->clone->subtract( days => 1 ) }; |
|
|
7
|
|
|
|
|
29
|
|
|
76
|
7
|
100
|
100
|
|
|
62
|
$prev_day && ! $prev_day->is_dst ? 1 : 0 } |
|
77
|
|
|
|
|
|
|
); |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
$bigger_min += 60 |
|
80
|
|
|
|
|
|
|
# it's a 25 hour (local) day |
|
81
|
|
|
|
|
|
|
if ( ! $bigger->is_dst |
|
82
|
|
|
|
|
|
|
&& |
|
83
|
13
|
100
|
66
|
|
|
50
|
do { local $@; |
|
|
6
|
|
|
|
|
11
|
|
|
84
|
6
|
|
|
|
|
12
|
my $prev_day = eval { $bigger->clone->subtract( days => 1 ) }; |
|
|
6
|
|
|
|
|
27
|
|
|
85
|
6
|
100
|
66
|
|
|
59
|
$prev_day && $prev_day->is_dst ? 1 : 0 } |
|
86
|
|
|
|
|
|
|
); |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
51
|
|
|
|
|
235
|
my ( $months, $days, $minutes, $seconds, $nanoseconds ) = |
|
90
|
|
|
|
|
|
|
$dt1->_adjust_for_positive_difference |
|
91
|
|
|
|
|
|
|
( $bigger->year * 12 + $bigger->month, $smaller->year * 12 + $smaller->month, |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
$bigger->day, $smaller->day, |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
$bigger_min, $smaller->hour * 60 + $smaller->minute, |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
$bigger->second, $smaller->second, |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
$bigger->nanosecond, $smaller->nanosecond, |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
$minute_length, |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# XXX - using the smaller as the month length is |
|
104
|
|
|
|
|
|
|
# somewhat arbitrary, we could also use the bigger - |
|
105
|
|
|
|
|
|
|
# either way we have reversibility problems |
|
106
|
|
|
|
|
|
|
DateTimeX::Lite::Util::month_length( $smaller->year, $smaller->month ), |
|
107
|
|
|
|
|
|
|
); |
|
108
|
|
|
|
|
|
|
|
|
109
|
51
|
100
|
|
|
|
179
|
if ($negative) |
|
110
|
|
|
|
|
|
|
{ |
|
111
|
16
|
|
|
|
|
46
|
for ( $months, $days, $minutes, $seconds, $nanoseconds ) |
|
112
|
|
|
|
|
|
|
{ |
|
113
|
|
|
|
|
|
|
# Some versions of Perl can end up with -0 if we do "0 * -1"!! |
|
114
|
80
|
100
|
|
|
|
231
|
$_ *= -1 if $_; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
return |
|
119
|
51
|
|
|
|
|
288
|
DateTimeX::Lite::Duration->new |
|
120
|
|
|
|
|
|
|
( months => $months, |
|
121
|
|
|
|
|
|
|
days => $days, |
|
122
|
|
|
|
|
|
|
minutes => $minutes, |
|
123
|
|
|
|
|
|
|
seconds => $seconds, |
|
124
|
|
|
|
|
|
|
nanoseconds => $nanoseconds, |
|
125
|
|
|
|
|
|
|
); |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub _adjust_for_positive_difference |
|
129
|
|
|
|
|
|
|
{ |
|
130
|
55
|
|
|
55
|
|
160
|
my ( $self, |
|
131
|
|
|
|
|
|
|
$month1, $month2, |
|
132
|
|
|
|
|
|
|
$day1, $day2, |
|
133
|
|
|
|
|
|
|
$min1, $min2, |
|
134
|
|
|
|
|
|
|
$sec1, $sec2, |
|
135
|
|
|
|
|
|
|
$nano1, $nano2, |
|
136
|
|
|
|
|
|
|
$minute_length, |
|
137
|
|
|
|
|
|
|
$month_length, |
|
138
|
|
|
|
|
|
|
) = @_; |
|
139
|
|
|
|
|
|
|
|
|
140
|
55
|
100
|
|
|
|
154
|
if ( $nano1 < $nano2 ) |
|
141
|
|
|
|
|
|
|
{ |
|
142
|
7
|
|
|
|
|
13
|
$sec1--; |
|
143
|
7
|
|
|
|
|
29
|
$nano1 += &DateTimeX::Lite::MAX_NANOSECONDS; |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
|
|
146
|
55
|
100
|
|
|
|
148
|
if ( $sec1 < $sec2 ) |
|
147
|
|
|
|
|
|
|
{ |
|
148
|
8
|
|
|
|
|
10
|
$min1--; |
|
149
|
8
|
|
|
|
|
12
|
$sec1 += $minute_length; |
|
150
|
|
|
|
|
|
|
} |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# A day always has 24 * 60 minutes, though the minutes may vary in |
|
153
|
|
|
|
|
|
|
# length. |
|
154
|
55
|
100
|
|
|
|
140
|
if ( $min1 < $min2 ) |
|
155
|
|
|
|
|
|
|
{ |
|
156
|
8
|
|
|
|
|
13
|
$day1--; |
|
157
|
8
|
|
|
|
|
16
|
$min1 += 24 * 60; |
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
|
|
160
|
55
|
100
|
|
|
|
153
|
if ( $day1 < $day2 ) |
|
161
|
|
|
|
|
|
|
{ |
|
162
|
12
|
|
|
|
|
15
|
$month1--; |
|
163
|
12
|
|
|
|
|
32
|
$day1 += $month_length; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
|
|
166
|
55
|
|
|
|
|
223
|
return ( $month1 - $month2, |
|
167
|
|
|
|
|
|
|
$day1 - $day2, |
|
168
|
|
|
|
|
|
|
$min1 - $min2, |
|
169
|
|
|
|
|
|
|
$sec1 - $sec2, |
|
170
|
|
|
|
|
|
|
$nano1 - $nano2, |
|
171
|
|
|
|
|
|
|
); |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub subtract_datetime_absolute |
|
175
|
|
|
|
|
|
|
{ |
|
176
|
8
|
|
|
8
|
0
|
48
|
my $self = shift; |
|
177
|
8
|
|
|
|
|
15
|
my $dt = shift; |
|
178
|
|
|
|
|
|
|
|
|
179
|
8
|
|
|
|
|
35
|
my $utc_rd_secs1 = $self->utc_rd_as_seconds; |
|
180
|
8
|
100
|
|
|
|
30
|
$utc_rd_secs1 += DateTimeX::Lite::LeapSecond::leap_seconds( $self->{utc_rd_days} ) |
|
181
|
|
|
|
|
|
|
if ! $self->time_zone->is_floating; |
|
182
|
|
|
|
|
|
|
|
|
183
|
8
|
|
|
|
|
33
|
my $utc_rd_secs2 = $dt->utc_rd_as_seconds; |
|
184
|
8
|
100
|
|
|
|
27
|
$utc_rd_secs2 += DateTimeX::Lite::LeapSecond::leap_seconds( $dt->{utc_rd_days} ) |
|
185
|
|
|
|
|
|
|
if ! $dt->time_zone->is_floating; |
|
186
|
|
|
|
|
|
|
|
|
187
|
8
|
|
|
|
|
18
|
my $seconds = $utc_rd_secs1 - $utc_rd_secs2; |
|
188
|
8
|
|
|
|
|
29
|
my $nanoseconds = $self->nanosecond - $dt->nanosecond; |
|
189
|
|
|
|
|
|
|
|
|
190
|
8
|
100
|
|
|
|
31
|
if ( $nanoseconds < 0 ) |
|
191
|
|
|
|
|
|
|
{ |
|
192
|
1
|
|
|
|
|
2
|
$seconds--; |
|
193
|
1
|
|
|
|
|
4
|
$nanoseconds += &DateTimeX::Lite::MAX_NANOSECONDS; |
|
194
|
|
|
|
|
|
|
} |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
return |
|
197
|
8
|
|
|
|
|
40
|
DateTimeX::Lite::Duration->new |
|
198
|
|
|
|
|
|
|
( seconds => $seconds, |
|
199
|
|
|
|
|
|
|
nanoseconds => $nanoseconds, |
|
200
|
|
|
|
|
|
|
); |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub delta_md |
|
204
|
|
|
|
|
|
|
{ |
|
205
|
4
|
|
|
4
|
0
|
3445
|
my $self = shift; |
|
206
|
4
|
|
|
|
|
9
|
my $dt = shift; |
|
207
|
|
|
|
|
|
|
|
|
208
|
4
|
|
|
|
|
37
|
my ( $smaller, $bigger ) = sort $self, $dt; |
|
209
|
|
|
|
|
|
|
|
|
210
|
4
|
|
|
|
|
23
|
my ( $months, $days, undef, undef, undef ) = |
|
211
|
|
|
|
|
|
|
$dt->_adjust_for_positive_difference |
|
212
|
|
|
|
|
|
|
( $bigger->year * 12 + $bigger->month, $smaller->year * 12 + $smaller->month, |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
$bigger->day, $smaller->day, |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
0, 0, |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
0, 0, |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
0, 0, |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
60, |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
DateTimeX::Lite::Util::month_length( $smaller->year, $smaller->month ), |
|
225
|
|
|
|
|
|
|
); |
|
226
|
|
|
|
|
|
|
|
|
227
|
4
|
|
|
|
|
33
|
return DateTimeX::Lite::Duration->new( months => $months, |
|
228
|
|
|
|
|
|
|
days => $days ); |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub delta_days |
|
232
|
|
|
|
|
|
|
{ |
|
233
|
5
|
|
|
5
|
0
|
2435
|
my $self = shift; |
|
234
|
5
|
|
|
|
|
14
|
my $dt = shift; |
|
235
|
|
|
|
|
|
|
|
|
236
|
5
|
|
|
|
|
33
|
my ( $smaller, $bigger ) = sort( ($self->local_rd_values)[0], ($dt->local_rd_values)[0] ); |
|
237
|
|
|
|
|
|
|
|
|
238
|
5
|
|
|
|
|
39
|
DateTimeX::Lite::Duration->new( days => $bigger - $smaller ); |
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub delta_ms |
|
242
|
|
|
|
|
|
|
{ |
|
243
|
3
|
|
|
3
|
0
|
11
|
my $self = shift; |
|
244
|
3
|
|
|
|
|
6
|
my $dt = shift; |
|
245
|
|
|
|
|
|
|
|
|
246
|
3
|
|
|
|
|
27
|
my ( $smaller, $greater ) = sort $self, $dt; |
|
247
|
|
|
|
|
|
|
|
|
248
|
3
|
|
|
|
|
13
|
my $days = int( $greater->jd - $smaller->jd ); |
|
249
|
|
|
|
|
|
|
|
|
250
|
3
|
|
|
|
|
16
|
my $dur = $greater->subtract_datetime($smaller); |
|
251
|
|
|
|
|
|
|
|
|
252
|
3
|
|
|
|
|
8
|
my %p; |
|
253
|
3
|
|
|
|
|
11
|
$p{hours} = $dur->hours + ( $days * 24 ); |
|
254
|
3
|
|
|
|
|
12
|
$p{minutes} = $dur->minutes; |
|
255
|
3
|
|
|
|
|
12
|
$p{seconds} = $dur->seconds; |
|
256
|
|
|
|
|
|
|
|
|
257
|
3
|
|
|
|
|
13
|
return DateTimeX::Lite::Duration->new(%p); |
|
258
|
|
|
|
|
|
|
} |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub _add_overload |
|
261
|
|
|
|
|
|
|
{ |
|
262
|
4358
|
|
|
4358
|
|
8246
|
my ( $dt, $dur, $reversed ) = @_; |
|
263
|
|
|
|
|
|
|
|
|
264
|
4358
|
50
|
|
|
|
9867
|
if ($reversed) |
|
265
|
|
|
|
|
|
|
{ |
|
266
|
0
|
|
|
|
|
0
|
( $dur, $dt ) = ( $dt, $dur ); |
|
267
|
|
|
|
|
|
|
} |
|
268
|
|
|
|
|
|
|
|
|
269
|
4358
|
100
|
100
|
|
|
36549
|
unless ( blessed $dur && $dur->isa( 'DateTimeX::Lite::Duration' ) ) |
|
270
|
|
|
|
|
|
|
{ |
|
271
|
2
|
|
|
|
|
3
|
my $class = ref $dt; |
|
272
|
2
|
|
|
|
|
8
|
my $dt_string = overload::StrVal($dt); |
|
273
|
|
|
|
|
|
|
|
|
274
|
2
|
|
|
|
|
297
|
Carp::croak( "Cannot add $dur to a $class object ($dt_string).\n" |
|
275
|
|
|
|
|
|
|
. " Only a DateTimeX::Lite::Duration object can " |
|
276
|
|
|
|
|
|
|
. " be added to a $class object." ); |
|
277
|
|
|
|
|
|
|
} |
|
278
|
|
|
|
|
|
|
|
|
279
|
4356
|
|
|
|
|
15007
|
return $dt->clone->add_duration($dur); |
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
sub _subtract_overload |
|
283
|
|
|
|
|
|
|
{ |
|
284
|
1229
|
|
|
1229
|
|
3829
|
my ( $date1, $date2, $reversed ) = @_; |
|
285
|
|
|
|
|
|
|
|
|
286
|
1229
|
50
|
|
|
|
2732
|
if ($reversed) |
|
287
|
|
|
|
|
|
|
{ |
|
288
|
0
|
|
|
|
|
0
|
( $date2, $date1 ) = ( $date1, $date2 ); |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
|
|
291
|
1229
|
100
|
100
|
|
|
11576
|
if ( blessed $date2 && $date2->isa( 'DateTimeX::Lite::Duration' ) ) |
|
|
|
100
|
100
|
|
|
|
|
|
292
|
|
|
|
|
|
|
{ |
|
293
|
1208
|
|
|
|
|
4656
|
my $new = $date1->clone; |
|
294
|
1208
|
|
|
|
|
6794
|
$new->add_duration( $date2->inverse ); |
|
295
|
1208
|
|
|
|
|
11503
|
return $new; |
|
296
|
|
|
|
|
|
|
} |
|
297
|
|
|
|
|
|
|
elsif ( blessed $date2 && $date2->isa( 'DateTimeX::Lite' ) ) |
|
298
|
|
|
|
|
|
|
{ |
|
299
|
19
|
|
|
|
|
71
|
return $date1->subtract_datetime($date2); |
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
else |
|
302
|
|
|
|
|
|
|
{ |
|
303
|
2
|
|
|
|
|
5
|
my $class = ref $date1; |
|
304
|
2
|
|
|
|
|
6
|
my $dt_string = overload::StrVal($date1); |
|
305
|
|
|
|
|
|
|
|
|
306
|
2
|
|
|
|
|
275
|
Carp::croak( "Cannot subtract $date2 from a $class object ($dt_string).\n" |
|
307
|
|
|
|
|
|
|
. " Only a DateTimeX::Lite::Duration or DateTimeX::Lite object can " |
|
308
|
|
|
|
|
|
|
. " be subtracted from a $class object." ); |
|
309
|
|
|
|
|
|
|
} |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
|
|
312
|
620
|
|
|
620
|
0
|
7721
|
sub add { return shift->add_duration( DateTimeX::Lite::Duration->new(@_) ) } |
|
313
|
|
|
|
|
|
|
|
|
314
|
54
|
|
|
54
|
0
|
387
|
sub subtract { return shift->subtract_duration( DateTimeX::Lite::Duration->new(@_) ) } |
|
315
|
|
|
|
|
|
|
|
|
316
|
71
|
|
|
71
|
0
|
367
|
sub subtract_duration { return $_[0]->add_duration( $_[1]->inverse ) } |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub add_duration |
|
319
|
|
|
|
|
|
|
{ |
|
320
|
6324
|
|
|
6324
|
0
|
10233
|
my ($self, $dur) = @_; |
|
321
|
6324
|
50
|
33
|
|
|
42972
|
if (! blessed $dur || !$dur->isa('DateTimeX::Lite::Duration')) { |
|
322
|
0
|
|
|
|
|
0
|
Carp::croak("Duration is not a DateTimeX::Lite::Duration object"); |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# simple optimization |
|
326
|
6324
|
50
|
|
|
|
23692
|
return $self if $dur->is_zero; |
|
327
|
|
|
|
|
|
|
|
|
328
|
6324
|
|
|
|
|
23986
|
my %deltas = $dur->deltas; |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# This bit isn't quite right since DateTimeX::Lite::Infinite::Future - |
|
331
|
|
|
|
|
|
|
# infinite duration should NaN |
|
332
|
6324
|
|
|
|
|
20519
|
foreach my $val ( values %deltas ) |
|
333
|
|
|
|
|
|
|
{ |
|
334
|
31612
|
|
|
|
|
31528
|
my $inf; |
|
335
|
31612
|
100
|
|
|
|
142024
|
if ( $val == &DateTimeX::Lite::INFINITY ) |
|
|
|
100
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
{ |
|
337
|
1
|
|
|
|
|
9
|
$inf = DateTimeX::Lite::Infinite::Future->new; |
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
elsif ( $val == &DateTimeX::Lite::NEG_INFINITY ) |
|
340
|
|
|
|
|
|
|
{ |
|
341
|
1
|
|
|
|
|
9
|
$inf = DateTimeX::Lite::Infinite::Past->new; |
|
342
|
|
|
|
|
|
|
} |
|
343
|
|
|
|
|
|
|
|
|
344
|
31612
|
100
|
|
|
|
76475
|
if ($inf) |
|
345
|
|
|
|
|
|
|
{ |
|
346
|
2
|
|
|
|
|
25
|
%$self = %$inf; |
|
347
|
2
|
|
|
|
|
14
|
bless $self, blessed $inf; |
|
348
|
|
|
|
|
|
|
|
|
349
|
2
|
|
|
|
|
11
|
return $self; |
|
350
|
|
|
|
|
|
|
} |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
|
|
353
|
6322
|
100
|
|
|
|
22679
|
return $self if $self->is_infinite; |
|
354
|
|
|
|
|
|
|
|
|
355
|
6318
|
100
|
|
|
|
16608
|
if ( $deltas{days} ) |
|
356
|
|
|
|
|
|
|
{ |
|
357
|
3483
|
|
|
|
|
7121
|
$self->{local_rd_days} += $deltas{days}; |
|
358
|
|
|
|
|
|
|
|
|
359
|
3483
|
|
|
|
|
8729
|
$self->{utc_year} += int( $deltas{days} / 365 ) + 1; |
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
|
|
362
|
6318
|
100
|
|
|
|
14632
|
if ( $deltas{months} ) |
|
363
|
|
|
|
|
|
|
{ |
|
364
|
|
|
|
|
|
|
# For preserve mode, if it is the last day of the month, make |
|
365
|
|
|
|
|
|
|
# it the 0th day of the following month (which then will |
|
366
|
|
|
|
|
|
|
# normalize back to the last day of the new month). |
|
367
|
575
|
100
|
|
|
|
2323
|
my ($y, $m, $d) = ( $dur->is_preserve_mode ? |
|
368
|
|
|
|
|
|
|
DateTimeX::Lite::Util::rd2ymd( $self->{local_rd_days} + 1 ) : |
|
369
|
|
|
|
|
|
|
DateTimeX::Lite::Util::rd2ymd( $self->{local_rd_days} ) |
|
370
|
|
|
|
|
|
|
); |
|
371
|
|
|
|
|
|
|
|
|
372
|
575
|
100
|
|
|
|
1950
|
$d -= 1 if $dur->is_preserve_mode; |
|
373
|
|
|
|
|
|
|
|
|
374
|
575
|
100
|
100
|
|
|
2223
|
if ( ! $dur->is_wrap_mode && $d > 28 ) |
|
375
|
|
|
|
|
|
|
{ |
|
376
|
|
|
|
|
|
|
# find the rd for the last day of our target month |
|
377
|
1
|
|
|
|
|
7
|
$self->{local_rd_days} = DateTimeX::Lite::Util::ymd2rd( $y, $m + $deltas{months} + 1, 0 ); |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# what day of the month is it? (discard year and month) |
|
380
|
1
|
|
|
|
|
6
|
my $last_day = (DateTimeX::Lite::Util::rd2ymd( $self->{local_rd_days} ))[2]; |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# if our original day was less than the last day, |
|
383
|
|
|
|
|
|
|
# use that instead |
|
384
|
1
|
50
|
|
|
|
6
|
$self->{local_rd_days} -= $last_day - $d if $last_day > $d; |
|
385
|
|
|
|
|
|
|
} |
|
386
|
|
|
|
|
|
|
else |
|
387
|
|
|
|
|
|
|
{ |
|
388
|
574
|
|
|
|
|
3824
|
$self->{local_rd_days} = DateTimeX::Lite::Util::ymd2rd( $y, $m + $deltas{months}, $d ); |
|
389
|
|
|
|
|
|
|
} |
|
390
|
|
|
|
|
|
|
|
|
391
|
575
|
|
|
|
|
2136
|
$self->{utc_year} += int( $deltas{months} / 12 ) + 1; |
|
392
|
|
|
|
|
|
|
} |
|
393
|
|
|
|
|
|
|
|
|
394
|
6318
|
100
|
100
|
|
|
23617
|
if ( $deltas{days} || $deltas{months} ) |
|
395
|
|
|
|
|
|
|
{ |
|
396
|
4056
|
|
|
|
|
12009
|
$self->_calc_utc_rd; |
|
397
|
|
|
|
|
|
|
|
|
398
|
4053
|
|
|
|
|
12701
|
$self->_handle_offset_modifier( $self->second ); |
|
399
|
|
|
|
|
|
|
} |
|
400
|
|
|
|
|
|
|
|
|
401
|
6315
|
100
|
|
|
|
20426
|
if ( $deltas{minutes} ) |
|
402
|
|
|
|
|
|
|
{ |
|
403
|
85
|
|
|
|
|
220
|
$self->{utc_rd_secs} += $deltas{minutes} * 60; |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# This intentionally ignores leap seconds |
|
406
|
85
|
|
|
|
|
332
|
DateTimeX::Lite::Util::normalize_tai_seconds( $self->{utc_rd_days}, $self->{utc_rd_secs} ); |
|
407
|
|
|
|
|
|
|
} |
|
408
|
|
|
|
|
|
|
|
|
409
|
6315
|
100
|
100
|
|
|
25386
|
if ( $deltas{seconds} || $deltas{nanoseconds} ) |
|
410
|
|
|
|
|
|
|
{ |
|
411
|
2200
|
|
|
|
|
4418
|
$self->{utc_rd_secs} += $deltas{seconds}; |
|
412
|
|
|
|
|
|
|
|
|
413
|
2200
|
100
|
|
|
|
5385
|
if ( $deltas{nanoseconds} ) |
|
414
|
|
|
|
|
|
|
{ |
|
415
|
3
|
|
|
|
|
9
|
$self->{rd_nanosecs} += $deltas{nanoseconds}; |
|
416
|
3
|
|
|
|
|
15
|
DateTimeX::Lite::Util::normalize_nanoseconds( $self->{utc_rd_secs}, $self->{rd_nanosecs} ); |
|
417
|
|
|
|
|
|
|
} |
|
418
|
|
|
|
|
|
|
|
|
419
|
2200
|
|
|
|
|
7517
|
DateTimeX::Lite::Util::normalize_seconds($self); |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
# This might be some big number much bigger than 60, but |
|
422
|
|
|
|
|
|
|
# that's ok (there are tests in 19leap_second.t to confirm |
|
423
|
|
|
|
|
|
|
# that) |
|
424
|
2200
|
|
|
|
|
7213
|
$self->_handle_offset_modifier( $self->second + $deltas{seconds} ); |
|
425
|
|
|
|
|
|
|
} |
|
426
|
|
|
|
|
|
|
|
|
427
|
6315
|
50
|
|
|
|
37049
|
my $new = |
|
428
|
|
|
|
|
|
|
(ref $self)->from_object |
|
429
|
|
|
|
|
|
|
( object => $self, |
|
430
|
|
|
|
|
|
|
locale => $self->{locale}, |
|
431
|
|
|
|
|
|
|
( $self->{formatter} ? ( formatter => $self->{formatter} ) : () ), |
|
432
|
|
|
|
|
|
|
); |
|
433
|
|
|
|
|
|
|
|
|
434
|
6314
|
|
|
|
|
78765
|
%$self = %$new; |
|
435
|
|
|
|
|
|
|
|
|
436
|
6314
|
|
|
|
|
76319
|
return $self; |
|
437
|
|
|
|
|
|
|
} |
|
438
|
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
1; |