File Coverage

lib/Mojolicious/Plugin/Vparam/Datetime.pm
Criterion Covered Total %
statement 59 59 100.0
branch 46 52 88.4
condition 7 12 58.3
subroutine 16 16 100.0
pod 0 5 0.0
total 128 144 88.8


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Vparam::Datetime;
2 73     73   1817184 use Mojo::Base -strict;
  73         122973  
  73         413  
3 73     73   7694 use Mojolicious::Plugin::Vparam::Common;
  73         166  
  73         73386  
4              
5             sub check_date($) {
6 9 100   9 0 33 return 'Value is not defined' unless defined $_[0];
7 8 50       29 return 'Value is not set' unless length $_[0];
8 8         286 return 0;
9             }
10              
11             sub check_time($) {
12 8 100   8 0 32 return 'Value is not defined' unless defined $_[0];
13 7 50       28 return 'Value is not set' unless length $_[0];
14 7         337 return 0;
15             }
16              
17             sub check_datetime($) {
18 36 100   36 0 87 return 'Value is not defined' unless defined $_[0];
19 31 50       95 return 'Value is not set' unless length $_[0];
20 31         979 return 0;
21             }
22              
23             # Get a string and return DateTime or undef.
24             # Have a hack for parse Russian data and time.
25             sub parse_date($;$) {
26 53     53 0 112 my ($str, $tz) = @_;
27              
28 53 100       113 return undef unless defined $str;
29 50         165 s{^\s+}{}, s{\s+$}{} for $str;
30 50 100       145 return undef unless length $str;
31              
32 47         60 my $dt;
33              
34 47 100       238 if( $str =~ m{^\d+$} ) {
    100          
35 1         8 $dt = DateTime->from_epoch( epoch => int $str, time_zone => 'local' );
36             } elsif( $str =~ m{^[+-]} ) {
37 18         104 my @relative = $str =~ m{
38             ^([+-]) # sign
39             \s*
40             (?:(\d+)\s+)? # days
41             (?:(\d+):)?? # hours
42             (\d+) # minutes
43             (?::(\d+))? # seconds
44             $}x;
45 18         64 $dt = DateTime->now(time_zone => 'local');
46 18 100       13971 my $sub = $relative[0] eq '+' ? 'add' : 'subtract';
47 18 100       52 $dt->$sub(days => int $relative[1]) if defined $relative[1];
48 18 100       1395 $dt->$sub(hours => int $relative[2]) if defined $relative[2];
49 18 50       2690 $dt->$sub(minutes => int $relative[3]) if defined $relative[3];
50 18 100       11381 $dt->$sub(seconds => int $relative[4]) if defined $relative[4];
51             } else {
52             # RU format
53 28 100       201 if( $str =~ s{^(\d{1,2})\.(\d{1,2})\.(\d{1,4})(.*)$}{$3-$2-$1$4} ) {
54 12         64 my $cur_year = DateTime->now(time_zone => 'local')->strftime('%Y');
55 12         14644 my $cur_len = length( $cur_year ) - 1;
56             # Less digit year
57 12 100       162 if( my ($year) = $str =~ m{^(\d{1,$cur_len})-} ) {
58 1         6 $str = substr($cur_year, 0, 4 - length($year)) . $str;
59             }
60             }
61             # If looks like time add it
62 28 100       106 $str = DateTime->now(time_zone => 'local')->strftime('%F ') . $str
63             if $str =~ m{^\d{2}:};
64              
65 28         3585 $dt = eval { DateTime::Format::DateParse->parse_datetime( $str ); };
  28         167  
66 28 100       23479 return undef if $@;
67             }
68              
69 46 50       9179 return undef unless $dt;
70              
71             # Always local timezone
72 46   33     403 $tz //= DateTime->now(time_zone => 'local')->strftime('%z');
73 46         45014 $dt->set_time_zone( $tz );
74              
75 46         13259 return $dt;
76             }
77              
78             sub register {
79 75     75 0 238 my ($class, $self, $app, $conf) = @_;
80              
81             $app->vtype(
82             date =>
83             load => ['DateTime', 'DateTime::Format::DateParse'],
84 9     9   37 pre => sub { parse_date trim $_[1] },
85 9     9   27 valid => sub { check_date $_[1] },
86             post => sub {
87 9 100   9   23 return unless defined $_[1];
88             return ref($_[1]) && ( $conf->{date} || ! $_[2]->{blessed} )
89             ? $_[1]->strftime( $conf->{date} )
90 8 100 66     61 : $_[1];
91             },
92 75         900 );
93              
94             $app->vtype(
95             time =>
96             load => ['DateTime', 'DateTime::Format::DateParse'],
97 8     8   27 pre => sub { parse_date trim $_[1] },
98 8     8   27 valid => sub { check_time $_[1] },
99             post => sub {
100 8 100   8   28 return unless defined $_[1];
101             return ref($_[1]) && ( $conf->{time} || ! $_[2]->{blessed} )
102             ? $_[1]->strftime( $conf->{time} )
103 7 50 33     69 : $_[1];
104             },
105 75         794 );
106              
107             $app->vtype(
108             datetime =>
109             load => ['DateTime', 'DateTime::Format::DateParse'],
110 36     36   89 pre => sub { parse_date trim $_[1] },
111 36     36   76 valid => sub { check_datetime $_[1] },
112             post => sub {
113 36 100   36   72 return unless defined $_[1];
114             return ref($_[1]) && ( $conf->{datetime} || ! $_[2]->{blessed} )
115             ? $_[1]->strftime( $conf->{datetime} )
116 33 100 100     207 : $_[1];
117             },
118 75         721 );
119              
120              
121 75         286 return;
122             }
123              
124             1;