File Coverage

blib/lib/Random/Day.pm
Criterion Covered Total %
statement 95 106 89.6
branch 25 36 69.4
condition n/a
subroutine 19 19 100.0
pod 9 9 100.0
total 148 170 87.0


line stmt bran cond sub pod time code
1             package Random::Day;
2              
3 33     33   233524 use strict;
  33         159  
  33         1068  
4 33     33   161 use warnings;
  33         70  
  33         968  
5              
6 33     33   16689 use Class::Utils qw(set_params);
  33         191959  
  33         648  
7 33     33   34577 use DateTime;
  33         19037347  
  33         1887  
8 33     33   21450 use DateTime::Event::Random;
  33         1763516  
  33         1490  
9 33     33   20706 use DateTime::Event::Recurrence;
  33         225826  
  33         1293  
10 33     33   292 use English;
  33         98  
  33         359  
11 33     33   17845 use Error::Pure qw(err);
  33         101  
  33         48548  
12              
13             our $VERSION = 0.13;
14              
15             # Constructor.
16             sub new {
17 96     96 1 84418 my ($class, @params) = @_;
18              
19             # Create object.
20 96         266 my $self = bless {}, $class;
21              
22             # Day.
23 96         665 $self->{'day'} = undef;
24              
25             # DateTime object from.
26 96         417 $self->{'dt_from'} = DateTime->new(
27             'year' => 1900,
28             );
29              
30             # DateTime object to.
31 96         34388 $self->{'dt_to'} = DateTime->new(
32             'year' => 2050,
33             );
34              
35             # Month.
36 96         26952 $self->{'month'} = undef;
37              
38             # Year.
39 96         222 $self->{'year'} = undef;
40              
41             # Process parameters.
42 96         424 set_params($self, @params);
43              
44 90         1903 return $self;
45             }
46              
47             # Get DateTime object with random date.
48             sub get {
49 3     3 1 28 my ($self, $date) = @_;
50              
51 3 50       13 if ($self->{'year'}) {
52 0 0       0 if ($self->{'month'}) {
53 0 0       0 if ($self->{'day'}) {
54             $date = $self->random_day_month_year(
55             $self->{'day'},
56             $self->{'month'},
57 0         0 $self->{'year'},
58             );
59             } else {
60             $date = $self->random_month_year(
61             $self->{'month'},
62 0         0 $self->{'year'},
63             );
64             }
65             } else {
66 0 0       0 if ($self->{'day'}) {
67             $date = $self->random_day_year(
68             $self->{'day'},
69 0         0 $self->{'year'},
70             );
71             } else {
72 0         0 $date = $self->random_year($self->{'year'});
73             }
74             }
75             } else {
76 3 50       16 if ($self->{'month'}) {
77 0 0       0 if ($self->{'day'}) {
78             $date = $self->random_day_month(
79             $self->{'day'},
80 0         0 $self->{'month'},
81             );
82             } else {
83 0         0 $date = $self->random_month($self->{'month'});
84             }
85             } else {
86 3 50       10 if ($self->{'day'}) {
87 0         0 $date = $self->random_day($self->{'day'});
88             } else {
89 3         19 $date = $self->random;
90             }
91             }
92             }
93              
94 3         27568 return $date;
95             }
96              
97             # Random DateTime object for day.
98             sub random {
99 21     21 1 66 my $self = shift;
100              
101 21         144 my $daily = DateTime::Event::Recurrence->daily;
102              
103 21         9467 return $daily->next($self->_range);
104             }
105              
106             # Random DateTime object for day defined by day.
107             sub random_day {
108 18     18 1 171 my ($self, $day) = @_;
109              
110 18         62 $self->_check_day($day);
111 6         50 my $monthly_day = DateTime::Event::Recurrence->monthly(
112             'days' => $day,
113             );
114              
115 6         3134 return $monthly_day->next($self->random);
116             }
117              
118             # Random DateTime object for day defined by day and month.
119             sub random_day_month {
120 15     15 1 118 my ($self, $day, $month) = @_;
121              
122 15         50 $self->_check_day($day);
123 9         81 my $yearly_day_month = DateTime::Event::Recurrence->yearly(
124             'days' => $day,
125             'months' => $month,
126             );
127 9         3791 my $dt = $yearly_day_month->next($self->random);
128 9 100       93624 if (! defined $dt) {
129 6         27 err 'Cannot create DateTime object.';
130             }
131              
132 3         58 return $dt;
133             }
134              
135             # DateTime object for day defined by day, month and year.
136             sub random_day_month_year {
137 21     21 1 328 my ($self, $day, $month, $year) = @_;
138              
139 21         67 $self->_check_day($day);
140 12         18 my $dt = eval {
141 12         42 DateTime->new(
142             'day' => $day,
143             'month' => $month,
144             'year' => $year,
145             );
146             };
147 12 100       5620 if ($EVAL_ERROR) {
148 3         6726 err 'Cannot create DateTime object.',
149             'Error', $EVAL_ERROR;
150             }
151              
152 9 100       48 if (DateTime->compare($self->{'dt_from'}, $dt) == 1) {
153             err "Begin of expected month is lesser than minimal date.",
154             'Expected year', $year,
155             'Expected month', $month,
156             'Expected day', $day,
157             'Minimal year', $self->{'dt_from'}->year,
158             'Minimal month', $self->{'dt_from'}->month,
159 3         400 'Minimal day', $self->{'dt_from'}->day,
160             ;
161             }
162              
163 6 100       908 if (DateTime->compare($dt, $self->{'dt_to'}) == 1) {
164             err "End of expected month is greater than maximal date.",
165             'Expected year', $year,
166             'Expected month', $month,
167             'Expected day', $day,
168             'Maximal year', $self->{'dt_to'}->year,
169             'Maximal month', $self->{'dt_to'}->month,
170 3         352 'Maximal day', $self->{'dt_to'}->day,
171             ;
172             }
173              
174 3         421 return $dt;
175             }
176              
177             # Random DateTime object for day defined by month.
178             sub random_month {
179 6     6 1 49 my ($self, $month) = @_;
180              
181 6         38 my $random_day = $self->_range;
182              
183 6         39046 return $self->random_month_year($month, $random_day->year);
184             }
185              
186             # Random DateTime object for day defined by month and year.
187             sub random_month_year {
188 18     18 1 259 my ($self, $month, $year) = @_;
189              
190 18         27 my $after = eval {
191 18         84 DateTime->new(
192             'day' => 1,
193             'month' => $month,
194             'year' => $year,
195             );
196             };
197 18 100       9384 if ($EVAL_ERROR) {
198 6         12688 err 'Cannot create DateTime object.',
199             'Error', $EVAL_ERROR;
200             }
201              
202 12 100       57 if (DateTime->compare($self->{'dt_from'}, $after) == 1) {
203             err "Begin of expected month is lesser than minimal date.",
204             'Expected year', $year,
205             'Expected month', $month,
206             'Minimal year', $self->{'dt_from'}->year,
207 3         418 'Minimal month', $self->{'dt_from'}->month,
208             ;
209             }
210              
211 9         1188 my $before = $after->clone;
212 9         125 $before->add(months => 1)->subtract(days => 1);
213              
214 9 100       21318 if (DateTime->compare($before, $self->{'dt_to'}) == 1) {
215             err "End of expected month is greater than maximal date.",
216             'Expected year', $year,
217             'Expected month', $month,
218             'Maximal year', $self->{'dt_to'}->year,
219 3         353 'Maximal month', $self->{'dt_to'}->month,
220             ;
221             }
222              
223 6         725 my $daily = DateTime::Event::Recurrence->daily;
224 6         4063 return $daily->next(DateTime::Event::Random->datetime(
225             'after' => $after,
226             'before' => $before,
227             ));
228             }
229              
230             # Random DateTime object for day defined by year.
231             sub random_year {
232 9     9 1 69 my ($self, $year) = @_;
233              
234 9 100       27 if ($self->{'dt_from'}->year > $year) {
235             err "Year is lesser than minimal year.",
236             'Expected year', $year,
237 3         33 'Minimal year', $self->{'dt_from'}->year,
238             ;
239             }
240 6 100       58 if ($self->{'dt_to'}->year < $year) {
241             err "Year is greater than maximal year.",
242             'Expected year', $year,
243 3         30 'Maximal year', $self->{'dt_to'}->year,
244             ;
245             }
246              
247 3         57 my $daily = DateTime::Event::Recurrence->daily;
248              
249 3         2303 return $daily->next(DateTime::Event::Random->datetime(
250             'after' => DateTime->new(
251             'day' => 1,
252             'month' => 1,
253             'year' => $year,
254             ),
255             'before' => DateTime->new(
256             'day' => 31,
257             'month' => 12,
258             'year' => $year,
259             ),
260             ));
261             }
262              
263             # Check day.
264             sub _check_day {
265 54     54   125 my ($self, $day) = @_;
266              
267 54 100       312 if ($day !~ m/^\d+$/ms) {
268 18         158 err "Day isn't positive number.";
269             }
270 36 100       116 if ($day == 0) {
271 9         54 err 'Day cannot be a zero.';
272             }
273 27         47 return;
274             }
275              
276             # Random date in range.
277             sub _range {
278 27     27   66 my $self = shift;
279              
280             return DateTime::Event::Random->datetime(
281             'after' => $self->{'dt_from'},
282 27         263 'before' => $self->{'dt_to'},
283             );
284             }
285              
286             1;
287              
288             __END__
289              
290             =pod
291              
292             =encoding utf8
293              
294             =head1 NAME
295              
296             Random::Day - Class for random day generation.
297              
298             =head1 SYNOPSIS
299              
300             use Random::Day;
301              
302             my $obj = Random::Day->new(%params);
303             my $dt = $obj->get;
304             my $dt = $obj->random;
305             my $dt = $obj->random_day($day);
306             my $dt = $obj->random_day_month($day, $month);
307             my $dt = $obj->random_day_month_year($day, $month, $year);
308             my $dt = $obj->random_month($month);
309             my $dt = $obj->random_month_year($month, $year);
310             my $dt = $obj->random_year($year);
311              
312             =head1 METHODS
313              
314             =head2 C<new>
315              
316             my $obj = Random::Day->new(%params);
317              
318             Constructor.
319              
320             =over 8
321              
322             =item * C<day>
323              
324             Day.
325              
326             Default value is undef.
327              
328             =item * C<dt_from>
329              
330             DateTime object from.
331              
332             Default value is DateTime object for 1900 year.
333              
334             =item * C<dt_to>
335              
336             DateTime object to.
337              
338             Default value is DateTime object for 2050 year.
339              
340             =item * C<month>
341              
342             Month.
343              
344             Default value is undef.
345              
346             =item * C<year>
347              
348             Year.
349              
350             Default value is undef.
351              
352             =back
353              
354             =head2 C<get>
355              
356             my $dt = $obj->get;
357              
358             Get random date defined by constructor parameters.
359              
360             Returns DateTime object for date.
361              
362             =head2 C<random>
363              
364             my $dt = $obj->random;
365              
366             Get random date.
367              
368             Returns DateTime object for date.
369              
370             =head2 C<random_day>
371              
372             my $dt = $obj->random_day($day);
373              
374             Get random date defined by day.
375              
376             Returns DateTime object for date.
377              
378             =head2 C<random_day_month>
379              
380             my $dt = $obj->random_day_month($day, $month);
381              
382             Get random date defined by day and month.
383              
384             Returns DateTime object for date.
385              
386             =head2 C<random_day_month_year>
387              
388             my $dt = $obj->random_day_month_year($day, $month, $year);
389              
390             Get date defined by day, month and year.
391              
392             Returns DateTime object for date.
393              
394             =head2 C<random_month>
395              
396             my $dt = $obj->random_month($month);
397              
398             Get random date defined by month.
399              
400             Returns DateTime object for date.
401              
402             =head2 C<random_month_year>
403              
404             my $dt = $obj->random_month_year($month, $year);
405              
406             Get random date defined by month and year.
407              
408             Returns DateTime object for date.
409              
410             =head2 C<random_year>
411              
412             my $dt = $obj->random_year($year);
413              
414             Get random date defined by year.
415              
416             Returns DateTime object for date.
417              
418             =head1 ERRORS
419              
420             new():
421             From Class::Utils::set_params():
422             Unknown parameter '%s'.
423              
424             random_day():
425             Day cannot be a zero.
426             Day isn't number.
427              
428             random_day_month():
429             Cannot create DateTime object.
430             Day cannot be a zero.
431             Day isn't number.
432              
433             random_day_month_year():
434             Begin of expected month is lesser than minimal date.
435             Expected year: %s
436             Expected month: %s
437             Expected day: %s
438             Minimal year: %s
439             Minimal month: %s
440             Minimal day: %s
441             Cannot create DateTime object.
442             Error: %s
443             Day cannot be a zero.
444             Day isn't number.
445             End of expected month is greater than maximal date.
446             Expected year: %s
447             Expected month: %s
448             Expected day: %s
449             Maximal year: %s
450             Maximal month: %s
451             Maximal day: %s
452              
453             random_month():
454             Cannot create DateTime object.
455             Error: %s
456              
457             random_month_year():
458             Begin of expected month is lesser than minimal date.
459             Expected year: %s
460             Expected month: %s
461             Minimal year: %s
462             Minimal month: %s
463             Cannot create DateTime object.
464             Error: %s
465             End of expected month is greater than maximal date.
466             Expected year: %s
467             Expected month: %s
468             Maximal year: %s
469             Maximal month: %s
470              
471             random_year():
472             Year is greater than maximal year.
473             Expected year: %s
474             Maximal year: %s
475             Year is lesser than minimal year.
476             Expected year: %s
477             Minimal year: %s
478              
479             =head1 EXAMPLE
480              
481             =for comment filename=get_random_day.pl
482              
483             use strict;
484             use warnings;
485              
486             use Random::Day;
487              
488             # Object.
489             my $obj = Random::Day->new;
490              
491             # Get date.
492             my $dt = $obj->get;
493              
494             # Print out.
495             print $dt->ymd."\n";
496              
497             # Output like:
498             # \d\d\d\d-\d\d-\d\d
499              
500             =head1 DEPENDENCIES
501              
502             L<Class::Utils>,
503             L<DateTime>,
504             L<DateTime::Event::Random>,
505             L<DateTime::Event::Recurrence>,
506             L<English>,
507             L<Error::Pure>.
508              
509             =head1 SEE ALSO
510              
511             =over
512              
513             =item L<Data::Random>
514              
515             Perl module to generate random data
516              
517             =item L<Random::Day::InTheFuture>
518              
519             Class for random day generation in the future.
520              
521             =item L<Random::Day::InThePast>
522              
523             Class for random day generation in the past.
524              
525             =back
526              
527             =head1 REPOSITORY
528              
529             L<https://github.com/michal-josef-spacek/Random-Day>
530              
531             =head1 AUTHOR
532              
533             Michal Josef Špaček L<mailto:skim@cpan.org>
534              
535             L<http://skim.cz>
536              
537             =head1 LICENSE AND COPYRIGHT
538              
539             © 2013-2023 Michal Josef Špaček
540              
541             BSD 2-Clause License
542              
543             =head1 VERSION
544              
545             0.13
546              
547             =cut