File Coverage

blib/lib/DateTime/Format/Natural/Calc.pm
Criterion Covered Total %
statement 198 200 99.0
branch 30 42 71.4
condition 10 19 52.6
subroutine 34 34 100.0
pod n/a
total 272 295 92.2


line stmt bran cond sub pod time code
1             package DateTime::Format::Natural::Calc;
2              
3 26     26   215 use strict;
  26         62  
  26         732  
4 26     26   125 use warnings;
  26         68  
  26         748  
5 26         12847 use base qw(
6             DateTime::Format::Natural::Compat
7             DateTime::Format::Natural::Utils
8             DateTime::Format::Natural::Wrappers
9 26     26   134 );
  26         55  
10              
11 26     26   200 use constant MORNING => '08';
  26         62  
  26         2146  
12 26     26   164 use constant AFTERNOON => '14';
  26         237  
  26         1353  
13 26     26   182 use constant EVENING => '20';
  26         61  
  26         65566  
14              
15             our $VERSION = '1.46';
16              
17             my $multiply_by = sub
18             {
19             my ($value, $opts) = @_;
20             return $value * $opts->{multiply_by} if exists $opts->{multiply_by};
21             return $value;
22             };
23              
24             sub _no_op
25             {
26 92     92   181 my $self = shift;
27 92         352 $self->_register_trace;
28 92         306 my $opts = pop;
29             }
30              
31             sub _ago_variant
32             {
33 485     485   1041 my $self = shift;
34 485         1628 $self->_register_trace;
35 485         1396 my $opts = pop;
36 485         1831 $self->_subtract($opts->{unit} => $multiply_by->(shift, $opts));
37             }
38              
39             sub _now_variant
40             {
41 96     96   199 my $self = shift;
42 96         327 $self->_register_trace;
43 96         272 my $opts = pop;
44 96         252 my ($value, $when) = @_;
45             $self->_add_or_subtract({
46             when => $when,
47             unit => $opts->{unit},
48 96         300 value => $multiply_by->($value, $opts),
49             });
50             }
51              
52             sub _daytime_variant
53             {
54 409     409   812 my $self = shift;
55 409         1378 $self->_register_trace;
56 409         1144 my $opts = pop;
57 409         913 my ($daytime) = @_;
58 409         1547 my %lookup = (
59             0 => 'morning',
60             1 => 'afternoon',
61             2 => 'evening',
62             );
63 409         998 $daytime = $lookup{$daytime};
64 409         1389 my %daytimes = (
65             morning => MORNING,
66             afternoon => AFTERNOON,
67             evening => EVENING,
68             );
69             my $hour = exists $self->{Daytime}{$daytime}
70             ? $self->{Daytime}{$daytime}
71 409 100       1280 : $daytimes{$daytime};
72 409 50       1538 if ($self->_valid_time(hour => $hour)) {
73 409         5922 $self->_set(hour => $hour);
74             }
75             }
76              
77             sub _daytime
78             {
79 390     390   785 my $self = shift;
80 390         1305 $self->_register_trace;
81 390         1192 my $opts = pop;
82 390         972 my ($hour) = @_;
83 390   100     1827 $hour += $opts->{hours} || 0;
84 390 50       1536 if ($self->_valid_time(hour => $hour)) {
85 390         5859 $self->_set(hour => $hour);
86             }
87             }
88              
89             sub _hourtime_variant
90             {
91 96     96   181 my $self = shift;
92 96         331 $self->_register_trace;
93 96         278 my $opts = pop;
94 96         243 my ($value, $when) = @_;
95 96   100     357 my $hours = $opts->{hours} || 0;
96 96 50       407 if ($self->_valid_time(hour => $hours)) {
97 96         1393 $self->_set(hour => $hours);
98 96         365 $self->{datetime}->set(minute => 0, second => 0, nanosecond => 0);
99             $self->_add_or_subtract({
100             when => $when,
101             unit => $opts->{unit},
102 96         44162 value => $multiply_by->($value, $opts),
103             });
104             }
105             }
106              
107             sub _month_day
108             {
109 2633     2633   4907 my $self = shift;
110 2633         8785 $self->_register_trace;
111 2633         7261 my $opts = pop;
112 2633         6988 my ($day, $month) = @_;
113 2633 50       10570 if ($self->_valid_date(month => $month, day => $day)) {
114 2633         38945 $self->_set(
115             month => $month,
116             day => $day,
117             );
118             }
119             }
120              
121             sub _unit_date
122             {
123 528     528   1106 my $self = shift;
124 528         1801 $self->_register_trace;
125 528         1667 my $opts = pop;
126 528         1346 my ($value) = @_;
127 528 100       1995 $self->{datetime}->set(day => 1) if $opts->{unit} eq 'month';
128 528 50       48232 if ($self->_valid_date($opts->{unit} => $value)) {
129 528         7969 $self->_set($opts->{unit} => $value);
130             }
131             }
132              
133             sub _weekday
134             {
135 2319     2319   4214 my $self = shift;
136 2319         7735 $self->_register_trace;
137 2319         6712 my $opts = pop;
138 2319         5034 my ($day) = @_;
139 2319 100       8560 if ($day > $self->{datetime}->wday) {
140 748         4923 $self->_add(day => ($day - $self->{datetime}->wday));
141             }
142             else {
143 1571         8517 $self->_subtract(day => ($self->{datetime}->wday - $day));
144             }
145             }
146              
147             sub _count_day_variant_week
148             {
149 1116     1116   2292 my $self = shift;
150 1116         4023 $self->_register_trace;
151 1116         3549 my $opts = pop;
152 1116         3053 my ($when, $day) = @_;
153             my %days = (
154             -1 => ($self->{datetime}->wday + (7 - $day)),
155             0 => ($day - $self->{datetime}->wday),
156 1116         5129 1 => (7 - $self->{datetime}->wday + $day),
157             );
158             $self->_add_or_subtract({
159             when => ($when == 0) ? 1 : $when,
160             unit => 'day',
161 1116 100       18148 value => $days{$when},
162             });
163             }
164              
165             sub _count_day_variant_month
166             {
167 54     54   105 my $self = shift;
168 54         236 $self->_register_trace;
169 54         158 my $opts = pop;
170 54         152 my ($when, $day) = @_;
171 54 50       280 if ($self->_valid_date(day => $day)) {
172 54         924 $self->_add(month => $when);
173 54         225 $self->_set(day => $day);
174             }
175             }
176              
177             sub _unit_variant
178             {
179 2254     2254   4079 my $self = shift;
180 2254         7407 $self->_register_trace;
181 2254         6381 my $opts = pop;
182 2254         4676 my ($when) = @_;
183             $self->_add_or_subtract({
184             when => $when,
185             unit => $opts->{unit},
186 2254         7345 value => $multiply_by->(1, $opts),
187             });
188             }
189              
190             sub _count_month_variant_year
191             {
192 54     54   120 my $self = shift;
193 54         197 $self->_register_trace;
194 54         159 my $opts = pop;
195 54         163 my ($when, $month) = @_;
196 54 50       247 if ($self->_valid_date(month => $month)) {
197 54         859 $self->_add(year => $when);
198 54         259 $self->_set(month => $month);
199             }
200             }
201              
202             sub _in_count_variant
203             {
204 136     136   309 my $self = shift;
205 136         533 $self->_register_trace;
206 136         415 my $opts = pop;
207 136         582 $self->_add_or_subtract($opts->{unit} => $multiply_by->(shift, $opts));
208             }
209              
210             sub _month_variant
211             {
212 108     108   236 my $self = shift;
213 108         399 $self->_register_trace;
214 108         345 my $opts = pop;
215 108         304 my ($when, $month) = @_;
216 108 50       832 if ($self->_valid_date(month => $month)) {
217 108         1756 $self->_add(year => $when);
218 108         479 $self->_set(month => $month);
219             }
220             }
221              
222             sub _count_weekday_variant_month
223             {
224 168     168   335 my $self = shift;
225 168         634 $self->_register_trace;
226 168         501 my $opts = pop;
227 168         590 my ($when, $count, $day, $month) = @_;
228 168         308 my $year;
229 168         302 local $@;
230 168         346 eval {
231             ($year, $month, $day) =
232             $self->_Nth_Weekday_of_Month_Year(
233             $self->{datetime}->year + $when,
234             defined $month
235             ? $month
236             : $self->{datetime}->month,
237 168 100       824 $day,
238             $count,
239             );
240             };
241 168 50 33     3067 if (!$@
      33        
      33        
      33        
242             and defined $year && defined $month && defined $day
243             and $self->_check_date($year, $month, $day)
244             ) {
245 168         780 $self->_set(
246             year => $year,
247             month => $month,
248             day => $day,
249             );
250             }
251             else {
252 0         0 $self->_set_failure;
253 0         0 $self->_set_error("(date is not valid)");
254             }
255             }
256              
257             sub _daytime_unit_variant
258             {
259 144     144   288 my $self = shift;
260 144         534 $self->_register_trace;
261 144         403 my $opts = pop;
262 144         412 my ($value, $when, $days) = @_;
263 144         651 $self->_add(day => $days);
264 144         763 $self->{datetime}->set(hour => 0, minute => 0, second => 0, nanosecond => 0);
265             $self->_add_or_subtract({
266             when => $when,
267             unit => $opts->{unit},
268 144         72299 value => $multiply_by->($value, $opts),
269             });
270             }
271              
272             # wrapper for <time> AM/PM
273             sub _at
274             {
275 6331     6331   12767 my $self = shift;
276 6331         21137 $self->_register_trace;
277 6331         24599 $self->_at_time(@_);
278             }
279              
280             # wrapper for <time>
281             sub _time
282             {
283 1817     1817   4074 my $self = shift;
284 1817         6892 $self->_register_trace;
285 1817         7442 $self->_at_time(@_);
286             }
287              
288             sub _at_time
289             {
290 8148     8148   15962 my $self = shift;
291 8148         13990 my $opts = pop;
292 8148         18060 my ($time) = @_;
293 8148         21650 my @units = qw(hour minute second nanosecond);
294 8148         38382 my %values = map { shift @units => $_ } split /[:\.]/, $time;
  17589         53968  
295 8148 100       29212 $values{nanosecond} *= 1_000_000 if exists $values{nanosecond}; # milli to nano
296 8148 50       35625 if ($self->_valid_time(%values)) {
297 8148         125941 $self->_set(%values);
298             }
299             }
300              
301             sub _count_yearday_variant_year
302             {
303 132     132   307 my $self = shift;
304 132         501 $self->_register_trace;
305 132         403 my $opts = pop;
306 132         376 my ($day, $when) = @_;
307 132         257 my ($year, $month);
308 132         560 ($year, $month, $day) = $self->_Add_Delta_Days($self->{datetime}->year, $day);
309 132         1622 $self->_set(
310             year => $year + $when,
311             month => $month,
312             day => $day,
313             );
314             }
315              
316             sub _count_weekday
317             {
318 78     78   183 my $self = shift;
319 78         401 $self->_count_weekday_variant_month(0, @_[0,1], undef, $_[-1]);
320             }
321              
322             sub _day_month_year
323             {
324 6     6   17 my $self = shift;
325 6         23 $self->_register_trace;
326 6         20 my $opts = pop;
327 6         22 my ($day, $month, $year) = @_;
328 6 50       30 if ($self->_valid_date(year => $year, month => $month, day => $day)) {
329 6         100 $self->_set(
330             year => $year,
331             month => $month,
332             day => $day,
333             );
334             }
335             }
336              
337             sub _count_weekday_from_now
338             {
339 42     42   76 my $self = shift;
340 42         155 $self->_register_trace;
341 42         125 my $opts = pop;
342 42         113 my ($count, $day) = @_;
343 42         200 my $wday = $self->{datetime}->wday;
344 42 50       369 $self->_add(day => ($count - 1) * 7 +
345             (($wday < $day)
346             ? $day - $wday
347             : (7 - $wday) + $day)
348             );
349             }
350              
351             sub _final_weekday_in_month
352             {
353 60     60   125 my $self = shift;
354 60         248 $self->_register_trace;
355 60         196 my $opts = pop;
356 60         149 my ($wday, $month) = @_;
357 60         257 my $days = $self->_Days_in_Month($self->{datetime}->year, $month);
358 60         340 my ($year, $day);
359             ($year, $month, $day) = $self->_Nth_Weekday_of_Month_Year(
360             $self->{datetime}->year,
361 60         174 $month,
362             $wday,
363             1,
364             );
365 60         628 while ($day <= $days - 7) {
366 186         375 $day += 7;
367             }
368             $self->_set(
369 60         226 year => $year,
370             month => $month,
371             day => $day,
372             );
373             }
374              
375             sub _first_last_day_unit
376             {
377 78     78   170 my $self = shift;
378 78         268 $self->_register_trace;
379 78         230 my $opts = pop;
380 78         138 my ($year, $month, $day) = do {
381 78 100       317 @_ >= 3 ? @_ : (undef, @_);
382             };
383 78   66     462 $year ||= $self->{datetime}->year;
384 78 100       580 unless (defined $day) {
385 39         233 $day = $self->_Days_in_Month($year, $month);
386             }
387             $self->_set(
388 78         407 year => $year,
389             month => $month,
390             day => $day,
391             );
392             }
393              
394             sub _variant_last_month
395             {
396 12     12   27 my $self = shift;
397 12         45 $self->_register_trace;
398 12         33 my $opts = pop;
399 12         27 my ($day) = @_;
400 12         55 $self->_subtract(month => 1);
401 12 100       43 unless (defined $day) {
402 6         32 $day = $self->_Days_in_Month($self->{datetime}->year, $self->{datetime}->month);
403             }
404 12         64 $self->_set(day => $day);
405             }
406              
407             sub _variant_quarter
408             {
409 18     18   40 my $self = shift;
410 18         61 $self->_register_trace;
411 18         55 my $opts = pop;
412 18         40 my ($when) = @_;
413 18         74 $self->_subtract(day => $self->{datetime}->day_of_quarter - 1);
414             $self->_add_or_subtract({
415             when => $when,
416             unit => $opts->{unit},
417 18         110 value => 3,
418             });
419             }
420              
421             1;
422             __END__
423              
424             =head1 NAME
425              
426             DateTime::Format::Natural::Calc - Basic calculations
427              
428             =head1 SYNOPSIS
429              
430             Please see the DateTime::Format::Natural documentation.
431              
432             =head1 DESCRIPTION
433              
434             The C<DateTime::Format::Natural::Calc> class defines the worker methods.
435              
436             =head1 SEE ALSO
437              
438             L<DateTime::Format::Natural>
439              
440             =head1 AUTHOR
441              
442             Steven Schubiger <schubiger@cpan.org>
443              
444             =head1 LICENSE
445              
446             This program is free software; you may redistribute it and/or
447             modify it under the same terms as Perl itself.
448              
449             See L<http://dev.perl.org/licenses/>
450              
451             =cut