File Coverage

blib/lib/Data/Sah/Util/Type/Date.pm
Criterion Covered Total %
statement 66 78 84.6
branch 52 64 81.2
condition 42 62 67.7
subroutine 5 6 83.3
pod 2 2 100.0
total 167 212 78.7


line stmt bran cond sub pod time code
1              
2             use 5.010;
3 1     1   89630 use strict;
  1         13  
4 1     1   5 use warnings;
  1         2  
  1         345  
5 1     1   5 #use Log::Any '$log';
  1         1  
  1         41  
6              
7             use Scalar::Util qw(blessed looks_like_number);
8 1     1   5  
  1         2  
  1         1133  
9             require Exporter;
10              
11             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
12             our $DATE = '2022-08-20'; # DATE
13             our $DIST = 'Data-Sah'; # DIST
14             our $VERSION = '0.912'; # VERSION
15              
16             our @ISA = qw(Exporter);
17             our @EXPORT_OK = qw(
18             coerce_date
19             coerce_duration
20             );
21              
22             our $DATE_MODULE = $ENV{DATA_SAH_DATE_MODULE} // $ENV{PERL_DATE_MODULE} //
23             "DateTime"; # XXX change defaults to Time::Piece (core)
24              
25             my $re_ymd = qr/\A([0-9]{4})-([0-9]{2})-([0-9]{2})\z/;
26             my $re_ymdThmsZ = qr/\A([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})Z\z/;
27              
28             my $val = shift;
29             if (!defined($val)) {
30 33     33 1 492728 return undef; ## no critic: Subroutines::ProhibitExplicitReturnUndef
31 33 100       73 }
32 3         12  
33             if ($DATE_MODULE eq 'DateTime') {
34             require DateTime;
35 30 100       81 if (blessed($val) && $val->isa('DateTime')) {
    100          
    50          
36 10         44 return $val;
37 10 100 100     179 } elsif (looks_like_number($val) && $val >= 10**8 && $val <= 2**31) {
    100 100        
    100 100        
    100 100        
    100 66        
    100          
38 1         5 return DateTime->from_epoch(epoch => $val);
39             } elsif ($val =~ $re_ymd) {
40 1         9 my $d;
41             eval { $d = DateTime->new(year=>$1, month=>$2, day=>$3, time_zone=>'UTC') };
42 2         4 return undef if $@; ## no critic: Subroutines::ProhibitExplicitReturnUndef
43 2         3 return $d;
  2         34  
44 2 100       1434 } elsif ($val =~ $re_ymdThmsZ) {
45 1         5 my $d;
46             eval { $d = DateTime->new(year=>$1, month=>$2, day=>$3, hour=>$4, minute=>$5, second=>$6, time_zone=>'UTC') };
47 1         3 return undef if $@; ## no critic: Subroutines::ProhibitExplicitReturnUndef
48 1         2 return $d;
  1         6  
49 1 50       279 } elsif (blessed($val) && $val->isa('Time::Moment')) {
50 1         4 return DateTime->from_epoch(epoch => $val->epoch);
51             } elsif (blessed($val) && $val->isa('Time::Piece')) {
52 1         8 return DateTime->from_epoch(epoch => $val->epoch);
53             } else {
54 1         56 return undef; ## no critic: Subroutines::ProhibitExplicitReturnUndef
55             }
56 3         10 } elsif ($DATE_MODULE eq 'Time::Moment') {
57             require Time::Moment;
58             if (blessed($val) && $val->isa('Time::Moment')) {
59 10         47 return $val;
60 10 100 100     179 } elsif (looks_like_number($val) && $val >= 10**8 && $val <= 2**31) {
    100 100        
    100 100        
    100 100        
    100 66        
    100          
61 1         7 return Time::Moment->from_epoch(int($val), $val-int($val));
62             } elsif ($val =~ $re_ymd) {
63 1         10 my $d;
64             eval { $d = Time::Moment->new(year=>$1, month=>$2, day=>$3) };
65 2         4 return undef if $@; ## no critic: Subroutines::ProhibitExplicitReturnUndef
66 2         4 return $d;
  2         28  
67 2 100       27 } elsif ($val =~ $re_ymdThmsZ) {
68 1         6 my $d;
69             eval { $d = Time::Moment->new(year=>$1, month=>$2, day=>$3, hour=>$4, minute=>$5, second=>$6) };
70 1         3 return undef if $@; ## no critic: Subroutines::ProhibitExplicitReturnUndef
71 1         2 return $d;
  1         10  
72 1 50       4 } elsif (blessed($val) && $val->isa('DateTime')) {
73 1         5 return Time::Moment->from_epoch($val->epoch);
74             } elsif (blessed($val) && $val->isa('Time::Piece')) {
75 1         98 return Time::Moment->from_epoch($val->epoch);
76             } else {
77 1         63 return undef; ## no critic: Subroutines::ProhibitExplicitReturnUndef
78             }
79 3         15 } elsif ($DATE_MODULE eq 'Time::Piece') {
80             require Time::Piece;
81             if (blessed($val) && $val->isa('Time::Piece')) {
82 10         49 return $val;
83 10 100 100     163 } elsif (looks_like_number($val) && $val >= 10**8 && $val <= 2**31) {
    100 100        
    100 100        
    100 100        
    100 66        
    100          
84 1         5 return scalar Time::Piece->gmtime($val);
85             } elsif ($val =~ $re_ymd) {
86 1         6 my $d;
87             eval { $d = Time::Piece->strptime($val, "%Y-%m-%d") };
88 2         5 return undef if $@; ## no critic: Subroutines::ProhibitExplicitReturnUndef
89 2         3 return $d;
  2         10  
90 2 100       120 } elsif ($val =~ $re_ymdThmsZ) {
91 1         6 my $d;
92             eval { $d = Time::Piece->strptime($val, "%Y-%m-%dT%H:%M:%SZ") };
93 1         3 return undef if $@; ## no critic: Subroutines::ProhibitExplicitReturnUndef
94 1         2 return $d;
  1         4  
95 1 50       50 } elsif (blessed($val) && $val->isa('DateTime')) {
96 1         5 return scalar Time::Piece->gmtime(epoch => $val->epoch);
97             } elsif (blessed($val) && $val->isa('Time::Moment')) {
98 1         98 return scalar Time::Piece->gmtime(epoch => $val->epoch);
99             } else {
100 1         8 return undef; ## no critic: Subroutines::ProhibitExplicitReturnUndef
101             }
102 3         11 } else {
103             die "BUG: Unknown Perl date module '$DATE_MODULE'";
104             }
105 0           }
106              
107             my $val = shift;
108             if (!defined($val)) {
109             return undef; ## no critic: Subroutines::ProhibitExplicitReturnUndef
110 0     0 1   } elsif (blessed($val) && $val->isa('DateTime::Duration')) {
111 0 0 0       return $val;
    0          
    0          
112 0           } elsif ($val =~ /\AP
113             (?: ([0-9]+(?:\.[0-9]+)?)Y )?
114 0           (?: ([0-9]+(?:\.[0-9]+)?)M )?
115             (?: ([0-9]+(?:\.[0-9]+)?)W )?
116             (?: ([0-9]+(?:\.[0-9]+)?)D )?
117             (?:
118             T
119             (?: ([0-9]+(?:\.[0-9]+)?)H )?
120             (?: ([0-9]+(?:\.[0-9]+)?)M )?
121             (?: ([0-9]+(?:\.[0-9]+)?)S )?
122             )?
123             \z/x) {
124             require DateTime::Duration;
125             my $d;
126             eval {
127 0           $d = DateTime::Duration->new(
128 0           years => $1 // 0,
129 0           months => $2 // 0,
130 0   0       weeks => $3 // 0,
      0        
      0        
      0        
      0        
      0        
      0        
131             days => $4 // 0,
132             hours => $5 // 0,
133             minutes => $6 // 0,
134             seconds => $7 // 0,
135             );
136             };
137             return undef if $@; ## no critic: Subroutines::ProhibitExplicitReturnUndef
138             return $d;
139             } else {
140 0 0         return undef; ## no critic: Subroutines::ProhibitExplicitReturnUndef
141 0           }
142             }
143 0            
144             1;
145             # ABSTRACT: Utility related to date/duration type
146              
147              
148             =pod
149              
150             =encoding UTF-8
151              
152             =head1 NAME
153              
154             Data::Sah::Util::Type::Date - Utility related to date/duration type
155              
156             =head1 VERSION
157              
158             This document describes version 0.912 of Data::Sah::Util::Type::Date (from Perl distribution Data-Sah), released on 2022-08-20.
159              
160             =head1 DESCRIPTION
161              
162             =head1 FUNCTIONS
163              
164             =head2 coerce_date($val) => DATETIME OBJ|undef
165              
166             Coerce value to DateTime object according to perl Sah compiler (see
167             L<Data::Sah::Compiler::perl::TH::date>). Return undef if value is not
168             acceptable.
169              
170             =head2 coerce_duration($val) => DATETIME_DURATION OBJ|undef
171              
172             Coerce value to DateTime::Duration object according to perl Sah compiler (see
173             L<Data::Sah::Compiler::perl::TH::duration>). Return undef if value is not
174             acceptable.
175              
176             =head1 ENVIRONMENT
177              
178             =head2 DATA_SAH_DATE_MODULE => string (default: DateTime)
179              
180             Pick the date module to use. Available choices: DateTime, Time::Moment.
181              
182             =head2 PERL_DATE_MODULE => string (default: DateTime)
183              
184             Pick the date module to use. Available choices: DateTime, Time::Moment. Has
185             lower priority compared to DATA_SAH_DATE_MODULE.
186              
187             =head1 HOMEPAGE
188              
189             Please visit the project's homepage at L<https://metacpan.org/release/Data-Sah>.
190              
191             =head1 SOURCE
192              
193             Source repository is at L<https://github.com/perlancar/perl-Data-Sah>.
194              
195             =head1 AUTHOR
196              
197             perlancar <perlancar@cpan.org>
198              
199             =head1 CONTRIBUTING
200              
201              
202             To contribute, you can send patches by email/via RT, or send pull requests on
203             GitHub.
204              
205             Most of the time, you don't need to build the distribution yourself. You can
206             simply modify the code, then test via:
207              
208             % prove -l
209              
210             If you want to build the distribution (e.g. to try to install it locally on your
211             system), you can install L<Dist::Zilla>,
212             L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
213             L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
214             Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
215             that are considered a bug and can be reported to me.
216              
217             =head1 COPYRIGHT AND LICENSE
218              
219             This software is copyright (c) 2022, 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012 by perlancar <perlancar@cpan.org>.
220              
221             This is free software; you can redistribute it and/or modify it under
222             the same terms as the Perl 5 programming language system itself.
223              
224             =head1 BUGS
225              
226             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Data-Sah>
227              
228             When submitting a bug or request, please include a test-file or a
229             patch to an existing test-file that illustrates the bug or desired
230             feature.
231              
232             =cut