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 72     72   1415935 use Mojo::Base -strict;
  72         7921  
  72         465  
3 72     72   6886 use Mojolicious::Plugin::Vparam::Common;
  72         147  
  72         68722  
4              
5             sub check_date($) {
6 9 100   9 0 26 return 'Value is not defined' unless defined $_[0];
7 8 50       27 return 'Value is not set' unless length $_[0];
8 8         266 return 0;
9             }
10              
11             sub check_time($) {
12 8 100   8 0 22 return 'Value is not defined' unless defined $_[0];
13 7 50       22 return 'Value is not set' unless length $_[0];
14 7         220 return 0;
15             }
16              
17             sub check_datetime($) {
18 36 100   36 0 100 return 'Value is not defined' unless defined $_[0];
19 31 50       105 return 'Value is not set' unless length $_[0];
20 31         1019 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 120 my ($str, $tz) = @_;
27              
28 53 100       119 return undef unless defined $str;
29 50         152 s{^\s+}{}, s{\s+$}{} for $str;
30 50 100       163 return undef unless length $str;
31              
32 47         68 my $dt;
33              
34 47 100       265 if( $str =~ m{^\d+$} ) {
    100          
35 1         7 $dt = DateTime->from_epoch( epoch => int $str, time_zone => 'local' );
36             } elsif( $str =~ m{^[+-]} ) {
37 18         131 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         79 $dt = DateTime->now(time_zone => 'local');
46 18 100       16820 my $sub = $relative[0] eq '+' ? 'add' : 'subtract';
47 18 100       61 $dt->$sub(days => int $relative[1]) if defined $relative[1];
48 18 100       1590 $dt->$sub(hours => int $relative[2]) if defined $relative[2];
49 18 50       2967 $dt->$sub(minutes => int $relative[3]) if defined $relative[3];
50 18 100       12410 $dt->$sub(seconds => int $relative[4]) if defined $relative[4];
51             } else {
52             # RU format
53 28 100       180 if( $str =~ s{^(\d{1,2})\.(\d{1,2})\.(\d{1,4})(.*)$}{$3-$2-$1$4} ) {
54 12         48 my $cur_year = DateTime->now(time_zone => 'local')->strftime('%Y');
55 12         14700 my $cur_len = length( $cur_year ) - 1;
56             # Less digit year
57 12 100       121 if( my ($year) = $str =~ m{^(\d{1,$cur_len})-} ) {
58 1         5 $str = substr($cur_year, 0, 4 - length($year)) . $str;
59             }
60             }
61             # If looks like time add it
62 28 100       136 $str = DateTime->now(time_zone => 'local')->strftime('%F ') . $str
63             if $str =~ m{^\d{2}:};
64              
65 28         3753 $dt = eval { DateTime::Format::DateParse->parse_datetime( $str ); };
  28         136  
66 28 100       21837 return undef if $@;
67             }
68              
69 46 50       10339 return undef unless $dt;
70              
71             # Always local timezone
72 46   33     485 $tz //= DateTime->now(time_zone => 'local')->strftime('%z');
73 46         48959 $dt->set_time_zone( $tz );
74              
75 46         14043 return $dt;
76             }
77              
78             sub register {
79 74     74 0 228 my ($class, $self, $app, $conf) = @_;
80              
81             $app->vtype(
82             date =>
83             load => ['DateTime', 'DateTime::Format::DateParse'],
84 9     9   25 pre => sub { parse_date trim $_[1] },
85 9     9   20 valid => sub { check_date $_[1] },
86             post => sub {
87 9 100   9   22 return unless defined $_[1];
88             return ref($_[1]) && ( $conf->{date} || ! $_[2]->{blessed} )
89             ? $_[1]->strftime( $conf->{date} )
90 8 100 66     59 : $_[1];
91             },
92 74         834 );
93              
94             $app->vtype(
95             time =>
96             load => ['DateTime', 'DateTime::Format::DateParse'],
97 8     8   21 pre => sub { parse_date trim $_[1] },
98 8     8   18 valid => sub { check_time $_[1] },
99             post => sub {
100 8 100   8   23 return unless defined $_[1];
101             return ref($_[1]) && ( $conf->{time} || ! $_[2]->{blessed} )
102             ? $_[1]->strftime( $conf->{time} )
103 7 50 33     50 : $_[1];
104             },
105 74         789 );
106              
107             $app->vtype(
108             datetime =>
109             load => ['DateTime', 'DateTime::Format::DateParse'],
110 36     36   104 pre => sub { parse_date trim $_[1] },
111 36     36   99 valid => sub { check_datetime $_[1] },
112             post => sub {
113 36 100   36   85 return unless defined $_[1];
114             return ref($_[1]) && ( $conf->{datetime} || ! $_[2]->{blessed} )
115             ? $_[1]->strftime( $conf->{datetime} )
116 33 100 100     240 : $_[1];
117             },
118 74         691 );
119              
120              
121 74         331 return;
122             }
123              
124             1;