File Coverage

blib/lib/Mo/utils/Date.pm
Criterion Covered Total %
statement 84 84 100.0
branch 42 42 100.0
condition 6 6 100.0
subroutine 12 12 100.0
pod 4 4 100.0
total 148 148 100.0


line stmt bran cond sub pod time code
1             package Mo::utils::Date;
2              
3 6     6   2855143 use base qw(Exporter);
  6         24  
  6         981  
4 6     6   45 use strict;
  6         13  
  6         240  
5 6     6   36 use warnings;
  6         11  
  6         386  
6              
7 6     6   2038 use DateTime;
  6         1187910  
  6         250  
8 6     6   1145 use English;
  6         5545  
  6         48  
9 6     6   6050 use Error::Pure qw(err);
  6         33529  
  6         170  
10 6     6   426 use Readonly;
  6         12  
  6         7557  
11              
12             Readonly::Array our @EXPORT_OK => qw(check_date check_date_dmy check_date_ddmmyy check_date_order);
13              
14             our $VERSION = 0.04;
15              
16             sub check_date {
17 20     20 1 478897 my ($self, $key) = @_;
18              
19 20 100       68 if (! exists $self->{$key}) {
20 1         4 return;
21             }
22              
23 19 100       100 if (! defined $self->{$key}) {
24 1         4 return;
25             }
26              
27             # Check year format.
28 18 100       142 if ($self->{$key} !~ m/^\-?(\d{1,4})\-?\d{0,2}\-?\d{0,2}$/ms) {
29             err "Parameter '$key' is in bad format.",
30 1         9 'Value' => $self->{$key},
31             ;
32             }
33 17         52 my $year = $1;
34              
35             # Check year greater than actual.
36 17 100       77 if ($year > DateTime->now->year) {
37 1         318 err "Parameter '$key' has year greater than actual year.";
38             }
39              
40 16         6058 return;
41             }
42              
43             sub check_date_dmy {
44 9     9 1 368911 my ($self, $key) = @_;
45              
46 9 100       26 if (! exists $self->{$key}) {
47 1         3 return;
48             }
49              
50 8 100       17 if (! defined $self->{$key}) {
51 1         3 return;
52             }
53              
54 7 100       37 if ($self->{$key} !~ m/^(\d{1,2}).(\d{1,2}).(\d{4})$/ms) {
55             err "Parameter '$key' is in bad format.",
56 1         5 'Value' => $self->{$key},
57             ;
58             }
59 6         23 my ($day, $month, $year) = ($1, $2, $3);
60 6         7 eval {
61 6         26 DateTime->new(
62             'day' => $1,
63             'month' => $2,
64             'year' => $3,
65             );
66             };
67 6 100       2249 if ($EVAL_ERROR) {
68             err "Parameter '$key' is bad date.",
69 1         1372 'Value' => $self->{$key},
70             'DateTime error' => $EVAL_ERROR,
71             ;
72             }
73              
74 5         24 return;
75             }
76              
77             sub check_date_ddmmyy {
78 6     6 1 442871 my ($self, $key) = @_;
79              
80 6 100       22 if (! exists $self->{$key}) {
81 1         3 return;
82             }
83              
84 5 100       16 if (! defined $self->{$key}) {
85 1         3 return;
86             }
87              
88 4 100       18 if ($self->{$key} !~ m/^(\d{2})(\d{2})(\d{2})$/ms) {
89             err "Parameter '$key' is in bad date format.",
90 2         12 'Value', $self->{$key},
91             ;
92             }
93 2         14 my ($day, $month, $year) = ($1, $2, $3);
94 2         5 eval {
95 2         24 DateTime->new(
96             'day' => $1,
97             'month' => $2,
98             'year' => 2000 + $3,
99             );
100             };
101 2 100       1722 if ($EVAL_ERROR) {
102             err "Parameter '$key' is bad date.",
103 1         2191 'Value' => $self->{$key},
104             'DateTime error' => $EVAL_ERROR,
105             ;
106             }
107              
108 1         4 return;
109             }
110              
111             sub check_date_order {
112 13     13 1 353171 my ($self, $key1, $key2) = @_;
113              
114 13 100 100     74 if (! exists $self->{$key1} || ! exists $self->{$key2}) {
115 2         6 return;
116             }
117              
118 11 100 100     46 if (! defined $self->{$key1} || ! defined $self->{$key2}) {
119 2         5 return;
120             }
121              
122 9         15 my ($dt1, $dt2);
123 9 100       31 if (ref $self->{$key1} eq 'DateTime') {
124 2         28 $dt1 = $self->{$key1};
125             } else {
126 7         25 $dt1 = _construct_dt($self->{$key1});
127             }
128 7 100       20 if (ref $self->{$key2} eq 'DateTime') {
129 2         3 $dt2 = $self->{$key2};
130             } else {
131 5         11 $dt2 = _construct_dt($self->{$key2});
132             }
133              
134 7         27 my $cmp = DateTime->compare($dt1, $dt2);
135              
136             # dt1 >= dt2
137 7 100       444 if ($cmp != -1) {
138 3         18 err "Parameter '$key1' has date greater or same as parameter '$key2' date.";
139             }
140              
141 4         27 return;
142             }
143              
144             sub _construct_dt {
145 12     12   22 my $date = shift;
146              
147 12         21 my ($year, $month, $day);
148 12 100       77 if ($date =~ m/^(\-?\d{1,4})\-?(\d{0,2})\-?(\d{0,2})$/ms) {
149 11         52 ($year, $month, $day) = ($1, $2, $3);
150             } else {
151 1         3 err 'Cannot parse date/time string.',
152             'Value' => $date,
153             ;
154             }
155 11         15 my $dt = eval {
156 11 100       67 DateTime->new(
    100          
157             'year' => $year,
158             $month ? ('month' => $month) : (),
159             $day ? ('day' => $day) : (),
160             );
161             };
162 11 100       3327 if ($EVAL_ERROR) {
163 1         4 err "Cannot construct DateTime object from date.",
164             'Value' => $date,
165             'DateTime error' => $EVAL_ERROR,
166             ;
167             }
168              
169 10         18 return $dt;
170             }
171              
172             1;
173              
174             __END__
175              
176             =pod
177              
178             =encoding utf8
179              
180             =head1 NAME
181              
182             Mo::utils::Date - Mo date utilities.
183              
184             =head1 SYNOPSIS
185              
186             use Mo::utils::Date qw(check_date);
187              
188             check_date($self, $key);
189             check_date_dmy($self, $key);
190             check_date_ddmmyy($self, $key);
191             check_date_order($self, $key1, $key2);
192              
193             =head1 DESCRIPTION
194              
195             Utilities for checking of data values.
196              
197             =head1 SUBROUTINES
198              
199             =head2 C<check_date>
200              
201             check_date($self, $key);
202              
203             I<Since version 0.01. Described functionality since version 0.02.>
204              
205             Check parameter defined by C<$key> which is date and that date isn't greater
206             than actual year.
207              
208             Possible dates:
209             - YYYY-MM-DD
210             - YYYY-M-D
211             - YYYY-MM
212             - YYYY-M
213             - YYYY
214              
215             Put error if check isn't ok.
216              
217             Returns undef.
218              
219             =head2 C<check_date_dmy>
220              
221             check_date_dmy($self, $key);
222              
223             I<Since version 0.02. Described functionality since version 0.03.>
224              
225             Check parameter defined by C<$key> which is date in right format.
226              
227             Possible dates.
228             - D.M.YYYY
229             - DD.MM.YYYY
230              
231             Date is checked via L<DateTime> if is real.
232              
233             Put error if check isn't ok.
234              
235             Returns undef.
236              
237             =head2 C<check_date_ddmmyy>
238              
239             check_date_ddmmyy($self, $key);
240              
241             I<Since version 0.03.>
242              
243             Check parameter defined by C<$key> which is date in ddmmyy format.
244              
245             Possible dates.
246             - DDMMYY
247              
248             Function is working only for date years > 2000.
249              
250             Date is checked via L<DateTime> if it is real.
251              
252             Put error if check isn't ok.
253              
254             Returns undef.
255              
256             =head2 C<check_date_order>
257              
258             check_date_order($self, $key1, $key2);
259              
260             I<Since version 0.01. Described functionality since version 0.04.>
261              
262             Check if date with C<$key1> is lesser than date with C<$key2>.
263              
264             Possible date formats:
265              
266             =over
267              
268             =item * YYYY-MM-DD
269              
270             =item * -YYYY-MM-DD
271              
272             =item * YEAR
273              
274             =item * L<DateTime> object
275              
276             =back
277              
278             Put error if check isn't ok.
279              
280             Returns undef.
281              
282             =head1 ERRORS
283              
284             check_date():
285             Parameter '%s' for date is in bad format.
286             Value: %s
287             Parameter '%s' has year greater than actual year.
288              
289             check_date_dmy():
290             Parameter '%s' for date is in bad format.
291             Value: %s
292             Parameter '%s' is bad date.
293             Value: %s
294             DateTime error: %s
295              
296             check_date_ddmmyy():
297             Parameter '%s' for date is in bad date format.
298             Value: %s
299             Parameter '%s' is bad date.
300             Value: %s
301             DateTime error: %s
302              
303             check_date_order():
304             Cannot parse date/time string.
305             Value: %s
306             Cannot construct DateTime object from date.
307             Value: %s
308             DateTime error: %s
309             Parameter '%s' has date greater or same as parameter '%s' date.
310              
311             =head1 EXAMPLE1
312              
313             =for comment filename=check_date_ok.pl
314              
315             use strict;
316             use warnings;
317              
318             use Mo::utils::Date qw(check_date);
319              
320             my $self = {
321             'key' => '2022-01-15',
322             };
323             check_date($self, 'key');
324              
325             # Print out.
326             print "ok\n";
327              
328             # Output:
329             # ok
330              
331             =head1 EXAMPLE2
332              
333             =for comment filename=check_date_fail.pl
334              
335             use strict;
336             use warnings;
337              
338             use Error::Pure;
339             use Mo::utils::Date qw(check_date);
340              
341             $Error::Pure::TYPE = 'Error';
342              
343             my $self = {
344             'key' => 'foo',
345             };
346             check_date($self, 'key');
347              
348             # Print out.
349             print "ok\n";
350              
351             # Output like:
352             # #Error [..Utils.pm:?] Parameter 'key' is in bad format.
353              
354             =head1 EXAMPLE3
355              
356             =for comment filename=check_date_ddmmyy_ok.pl
357              
358             use strict;
359             use warnings;
360              
361             use Mo::utils::Date qw(check_date_ddmmyy);
362              
363             my $self = {
364             'key' => '151120',
365             };
366             check_date_ddmmyy($self, 'key');
367              
368             # Print out.
369             print "ok\n";
370              
371             # Output:
372             # ok
373              
374             =head1 EXAMPLE4
375              
376             =for comment filename=check_date_ddmmyy_fail.pl
377              
378             use strict;
379             use warnings;
380              
381             use Error::Pure;
382             use Mo::utils::Date qw(check_date_ddmmyy);
383              
384             $Error::Pure::TYPE = 'Error';
385              
386             my $self = {
387             'key' => 'foo',
388             };
389             check_date_ddmmyy($self, 'key');
390              
391             # Print out.
392             print "ok\n";
393              
394             # Output like:
395             # #Error [..Utils.pm:?] Parameter 'key' for date is in bad format.
396              
397             =head1 DEPENDENCIES
398              
399             L<DateTime>,
400             L<English>,
401             L<Exporter>,
402             L<Error::Pure>,
403             L<Readonly>.
404              
405             =head1 SEE ALSO
406              
407             =over
408              
409             =item L<Mo::utils>
410              
411             Mo utilities.
412              
413             =back
414              
415             =head1 REPOSITORY
416              
417             L<https://github.com/michal-josef-spacek/Mo-utils-Date>
418              
419             =head1 AUTHOR
420              
421             Michal Josef Špaček L<mailto:skim@cpan.org>
422              
423             L<http://skim.cz>
424              
425             =head1 LICENSE AND COPYRIGHT
426              
427             © Michal Josef Špaček 2022-2024
428              
429             BSD 2-Clause License
430              
431             =head1 VERSION
432              
433             0.04
434              
435             =cut