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   202 use strict;
  26         65  
  26         720  
4 26     26   130 use warnings;
  26         53  
  26         823  
5 26         12157 use base qw(
6             DateTime::Format::Natural::Compat
7             DateTime::Format::Natural::Utils
8             DateTime::Format::Natural::Wrappers
9 26     26   139 );
  26         50  
10              
11 26     26   194 use constant MORNING => '08';
  26         60  
  26         2094  
12 26     26   157 use constant AFTERNOON => '14';
  26         238  
  26         1290  
13 26     26   160 use constant EVENING => '20';
  26         59  
  26         62441  
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   208 my $self = shift;
27 92         326 $self->_register_trace;
28 92         337 my $opts = pop;
29             }
30              
31             sub _ago_variant
32             {
33 485     485   992 my $self = shift;
34 485         1619 $self->_register_trace;
35 485         1388 my $opts = pop;
36 485         1594 $self->_subtract($opts->{unit} => $multiply_by->(shift, $opts));
37             }
38              
39             sub _now_variant
40             {
41 96     96   193 my $self = shift;
42 96         343 $self->_register_trace;
43 96         273 my $opts = pop;
44 96         225 my ($value, $when) = @_;
45             $self->_add_or_subtract({
46             when => $when,
47             unit => $opts->{unit},
48 96         338 value => $multiply_by->($value, $opts),
49             });
50             }
51              
52             sub _daytime_variant
53             {
54 409     409   737 my $self = shift;
55 409         1294 $self->_register_trace;
56 409         1151 my $opts = pop;
57 409         882 my ($daytime) = @_;
58 409         1440 my %lookup = (
59             0 => 'morning',
60             1 => 'afternoon',
61             2 => 'evening',
62             );
63 409         902 $daytime = $lookup{$daytime};
64 409         1330 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       1219 : $daytimes{$daytime};
72 409 50       1372 if ($self->_valid_time(hour => $hour)) {
73 409         5707 $self->_set(hour => $hour);
74             }
75             }
76              
77             sub _daytime
78             {
79 390     390   794 my $self = shift;
80 390         1268 $self->_register_trace;
81 390         1487 my $opts = pop;
82 390         860 my ($hour) = @_;
83 390   100     1713 $hour += $opts->{hours} || 0;
84 390 50       1390 if ($self->_valid_time(hour => $hour)) {
85 390         5605 $self->_set(hour => $hour);
86             }
87             }
88              
89             sub _hourtime_variant
90             {
91 96     96   206 my $self = shift;
92 96         316 $self->_register_trace;
93 96         279 my $opts = pop;
94 96         238 my ($value, $when) = @_;
95 96   100     424 my $hours = $opts->{hours} || 0;
96 96 50       381 if ($self->_valid_time(hour => $hours)) {
97 96         1534 $self->_set(hour => $hours);
98 96         409 $self->{datetime}->set(minute => 0, second => 0, nanosecond => 0);
99             $self->_add_or_subtract({
100             when => $when,
101             unit => $opts->{unit},
102 96         44459 value => $multiply_by->($value, $opts),
103             });
104             }
105             }
106              
107             sub _month_day
108             {
109 2633     2633   5097 my $self = shift;
110 2633         8529 $self->_register_trace;
111 2633         7263 my $opts = pop;
112 2633         6145 my ($day, $month) = @_;
113 2633 50       8945 if ($self->_valid_date(month => $month, day => $day)) {
114 2633         37662 $self->_set(
115             month => $month,
116             day => $day,
117             );
118             }
119             }
120              
121             sub _unit_date
122             {
123 528     528   1163 my $self = shift;
124 528         2017 $self->_register_trace;
125 528         1643 my $opts = pop;
126 528         1310 my ($value) = @_;
127 528 100       2070 $self->{datetime}->set(day => 1) if $opts->{unit} eq 'month';
128 528 50       47812 if ($self->_valid_date($opts->{unit} => $value)) {
129 528         7991 $self->_set($opts->{unit} => $value);
130             }
131             }
132              
133             sub _weekday
134             {
135 2319     2319   4306 my $self = shift;
136 2319         7924 $self->_register_trace;
137 2319         6581 my $opts = pop;
138 2319         5377 my ($day) = @_;
139 2319 100       8584 if ($day > $self->{datetime}->wday) {
140 723         4384 $self->_add(day => ($day - $self->{datetime}->wday));
141             }
142             else {
143 1596         8943 $self->_subtract(day => ($self->{datetime}->wday - $day));
144             }
145             }
146              
147             sub _count_day_variant_week
148             {
149 1116     1116   2157 my $self = shift;
150 1116         3785 $self->_register_trace;
151 1116         3317 my $opts = pop;
152 1116         2727 my ($when, $day) = @_;
153             my %days = (
154             -1 => ($self->{datetime}->wday + (7 - $day)),
155             0 => ($day - $self->{datetime}->wday),
156 1116         4669 1 => (7 - $self->{datetime}->wday + $day),
157             );
158             $self->_add_or_subtract({
159             when => ($when == 0) ? 1 : $when,
160             unit => 'day',
161 1116 100       17222 value => $days{$when},
162             });
163             }
164              
165             sub _count_day_variant_month
166             {
167 54     54   106 my $self = shift;
168 54         192 $self->_register_trace;
169 54         187 my $opts = pop;
170 54         131 my ($when, $day) = @_;
171 54 50       206 if ($self->_valid_date(day => $day)) {
172 54         829 $self->_add(month => $when);
173 54         237 $self->_set(day => $day);
174             }
175             }
176              
177             sub _unit_variant
178             {
179 2254     2254   3968 my $self = shift;
180 2254         7281 $self->_register_trace;
181 2254         6018 my $opts = pop;
182 2254         4724 my ($when) = @_;
183             $self->_add_or_subtract({
184             when => $when,
185             unit => $opts->{unit},
186 2254         6812 value => $multiply_by->(1, $opts),
187             });
188             }
189              
190             sub _count_month_variant_year
191             {
192 54     54   102 my $self = shift;
193 54         190 $self->_register_trace;
194 54         152 my $opts = pop;
195 54         166 my ($when, $month) = @_;
196 54 50       220 if ($self->_valid_date(month => $month)) {
197 54         867 $self->_add(year => $when);
198 54         250 $self->_set(month => $month);
199             }
200             }
201              
202             sub _in_count_variant
203             {
204 136     136   276 my $self = shift;
205 136         473 $self->_register_trace;
206 136         411 my $opts = pop;
207 136         458 $self->_add_or_subtract($opts->{unit} => $multiply_by->(shift, $opts));
208             }
209              
210             sub _month_variant
211             {
212 108     108   238 my $self = shift;
213 108         383 $self->_register_trace;
214 108         310 my $opts = pop;
215 108         321 my ($when, $month) = @_;
216 108 50       452 if ($self->_valid_date(month => $month)) {
217 108         1676 $self->_add(year => $when);
218 108         446 $self->_set(month => $month);
219             }
220             }
221              
222             sub _count_weekday_variant_month
223             {
224 168     168   341 my $self = shift;
225 168         621 $self->_register_trace;
226 168         527 my $opts = pop;
227 168         538 my ($when, $count, $day, $month) = @_;
228 168         279 my $year;
229 168         369 local $@;
230 168         386 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       722 $day,
238             $count,
239             );
240             };
241 168 50 33     2961 if (!$@
      33        
      33        
      33        
242             and defined $year && defined $month && defined $day
243             and $self->_check_date($year, $month, $day)
244             ) {
245 168         811 $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   281 my $self = shift;
260 144         522 $self->_register_trace;
261 144         424 my $opts = pop;
262 144         373 my ($value, $when, $days) = @_;
263 144         607 $self->_add(day => $days);
264 144         668 $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         70590 value => $multiply_by->($value, $opts),
269             });
270             }
271              
272             # wrapper for <time> AM/PM
273             sub _at
274             {
275 6331     6331   11468 my $self = shift;
276 6331         20251 $self->_register_trace;
277 6331         23842 $self->_at_time(@_);
278             }
279              
280             # wrapper for <time>
281             sub _time
282             {
283 1817     1817   3717 my $self = shift;
284 1817         6272 $self->_register_trace;
285 1817         7472 $self->_at_time(@_);
286             }
287              
288             sub _at_time
289             {
290 8148     8148   15306 my $self = shift;
291 8148         14375 my $opts = pop;
292 8148         17928 my ($time) = @_;
293 8148         20709 my @units = qw(hour minute second nanosecond);
294 8148         36792 my %values = map { shift @units => $_ } split /[:\.]/, $time;
  17589         51857  
295 8148 100       28213 $values{nanosecond} *= 1_000_000 if exists $values{nanosecond}; # milli to nano
296 8148 50       33981 if ($self->_valid_time(%values)) {
297 8148         120459 $self->_set(%values);
298             }
299             }
300              
301             sub _count_yearday_variant_year
302             {
303 132     132   302 my $self = shift;
304 132         474 $self->_register_trace;
305 132         409 my $opts = pop;
306 132         366 my ($day, $when) = @_;
307 132         253 my ($year, $month);
308 132         573 ($year, $month, $day) = $self->_Add_Delta_Days($self->{datetime}->year, $day);
309 132         1668 $self->_set(
310             year => $year + $when,
311             month => $month,
312             day => $day,
313             );
314             }
315              
316             sub _count_weekday
317             {
318 78     78   157 my $self = shift;
319 78         371 $self->_count_weekday_variant_month(0, @_[0,1], undef, $_[-1]);
320             }
321              
322             sub _day_month_year
323             {
324 6     6   16 my $self = shift;
325 6         30 $self->_register_trace;
326 6         20 my $opts = pop;
327 6         19 my ($day, $month, $year) = @_;
328 6 50       25 if ($self->_valid_date(year => $year, month => $month, day => $day)) {
329 6         102 $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   82 my $self = shift;
340 42         138 $self->_register_trace;
341 42         149 my $opts = pop;
342 42         105 my ($count, $day) = @_;
343 42         205 my $wday = $self->{datetime}->wday;
344 42 50       314 $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   128 my $self = shift;
354 60         224 $self->_register_trace;
355 60         168 my $opts = pop;
356 60         155 my ($wday, $month) = @_;
357 60         252 my $days = $self->_Days_in_Month($self->{datetime}->year, $month);
358 60         345 my ($year, $day);
359             ($year, $month, $day) = $self->_Nth_Weekday_of_Month_Year(
360             $self->{datetime}->year,
361 60         206 $month,
362             $wday,
363             1,
364             );
365 60         631 while ($day <= $days - 7) {
366 186         380 $day += 7;
367             }
368             $self->_set(
369 60         289 year => $year,
370             month => $month,
371             day => $day,
372             );
373             }
374              
375             sub _first_last_day_unit
376             {
377 78     78   155 my $self = shift;
378 78         265 $self->_register_trace;
379 78         227 my $opts = pop;
380 78         158 my ($year, $month, $day) = do {
381 78 100       322 @_ >= 3 ? @_ : (undef, @_);
382             };
383 78   66     480 $year ||= $self->{datetime}->year;
384 78 100       497 unless (defined $day) {
385 39         253 $day = $self->_Days_in_Month($year, $month);
386             }
387             $self->_set(
388 78         428 year => $year,
389             month => $month,
390             day => $day,
391             );
392             }
393              
394             sub _variant_last_month
395             {
396 12     12   38 my $self = shift;
397 12         49 $self->_register_trace;
398 12         47 my $opts = pop;
399 12         28 my ($day) = @_;
400 12         62 $self->_subtract(month => 1);
401 12 100       42 unless (defined $day) {
402 6         26 $day = $self->_Days_in_Month($self->{datetime}->year, $self->{datetime}->month);
403             }
404 12         71 $self->_set(day => $day);
405             }
406              
407             sub _variant_quarter
408             {
409 18     18   28 my $self = shift;
410 18         65 $self->_register_trace;
411 18         65 my $opts = pop;
412 18         37 my ($when) = @_;
413 18         89 $self->_subtract(day => $self->{datetime}->day_of_quarter - 1);
414             $self->_add_or_subtract({
415             when => $when,
416             unit => $opts->{unit},
417 18         126 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