File Coverage

blib/lib/Dallycot/Value/DateTime.pm
Criterion Covered Total %
statement 30 96 31.2
branch 0 12 0.0
condition 0 14 0.0
subroutine 10 22 45.4
pod 0 11 0.0
total 40 155 25.8


line stmt bran cond sub pod time code
1             package Dallycot::Value::DateTime;
2             our $AUTHORITY = 'cpan:JSMITH';
3              
4             # ABSTRACT: Date and time values
5              
6 23     23   13589 use strict;
  23         43  
  23         755  
7 23     23   96 use warnings;
  23         27  
  23         576  
8 23     23   95 use experimental qw(switch);
  23         24  
  23         137  
9              
10 23     23   2272 use utf8;
  23         28  
  23         93  
11 23     23   467 use parent 'Dallycot::Value::Any';
  23         29  
  23         104  
12              
13 23     23   1293 use Carp qw(croak);
  23         34  
  23         1117  
14 23     23   20141 use DateTime;
  23         2485122  
  23         1127  
15 23     23   241 use List::Util qw(any);
  23         36  
  23         2786  
16 23     23   131 use Scalar::Util qw(blessed);
  23         38  
  23         1132  
17 23     23   123 use Promises qw(deferred);
  23         37  
  23         205  
18              
19             sub new {
20 0     0 0   my($class, %options) = @_;
21              
22 0   0       $class = ref $class || $class;
23              
24 0           for my $k (keys %options) {
25 0 0 0       $options{$k} = $options{$k} -> value -> numify if blessed($options{$k}) && $options{$k}->isa('Dallycot::Value::Numeric');
26             }
27              
28 0           my $datetime_class = delete $options{'class'};
29 0   0       $datetime_class //= 'DateTime';
30              
31 0 0         if($options{object}) {
32 0           return bless [
33             $datetime_class->from_object(object => $options{object})
34             ] => $class;
35             }
36             else {
37 0           return bless [
38             $datetime_class->new(
39 0           map { $_ => $options{$_} } grep { $options{$_} } keys %options
  0            
40             )
41             ] => $class;
42             }
43             }
44              
45             sub to_rdf {
46 0     0 0   my($self, $model) = @_;
47              
48             # we need to record the date/time as represented in RDF, but might want to
49             # record the calendar type as well
50 0           my $literal = RDF::Trine::Node::Literal->new(
51             DateTime->from_object(object => $self->[0])->iso8601,
52             '',
53             $model -> meta_uri('xsd:dateTime')
54             );
55              
56 0 0         return $literal if $self->[0] -> isa('DateTime');
57              
58 0           my $bnode = $model->bnode;
59 0           $model -> add_type($bnode, 'loc:DateTime');
60 0           $model -> add_connection($bnode, 'rdf:value', $literal);
61 0           my $calendar_type = (reverse split(/::/, blessed($self->[0])))[0];
62 0           $model -> add_connection($bnode, 'loc:calendar', $calendar_type);
63 0 0         if($self->[0]->can('epoch')) {
64 0           $model -> add_connection($bnode, 'loc:epoch', $model->integer(
65             $self->[0]->epoch
66             ));
67             }
68              
69 0           return $bnode;
70             }
71              
72             sub now {
73 0     0 0   my($class, $timezone) = @_;
74              
75 0   0       $class = ref $class || $class;
76              
77 0           return bless [ DateTime -> now(time_zone => $timezone) ] => $class;
78             }
79              
80             sub in_timezone {
81 0     0 0   my($self, $timezone) = @_;
82              
83 0           my $class = ref $self;
84              
85 0           return bless [ $self -> [0] -> clone -> set_time_zone($timezone) ] => $class;
86             }
87              
88             # sub to_calendar {
89             # my($self, $calendar_class) = @_;
90             #
91             # my $class = ref $self;
92             #
93             # return bless [ $calendar_class->from_object(object => $self->[0]) ] => $class;
94             # }
95              
96             sub as_text {
97 0     0 0   my($self) = @_;
98              
99 0 0         if($self -> [0] -> can('datetime')) {
100 0           return $self -> [0] -> datetime;
101             }
102             else {
103 0           return $self -> [0] -> date;
104             }
105             }
106              
107             sub is_equal {
108 0     0 0   my ( $self, $engine, $other ) = @_;
109              
110 0           my $d = deferred;
111              
112 0           $d->resolve( $self->value == $other->value );
113              
114 0           return $d->promise;
115             }
116              
117             sub is_less {
118 0     0 0   my ( $self, $engine, $other ) = @_;
119              
120 0           my $d = deferred;
121              
122 0           $d->resolve( $self->value < $other->value );
123              
124 0           return $d->promise;
125             }
126              
127             sub is_less_or_equal {
128 0     0 0   my ( $self, $engine, $other ) = @_;
129              
130 0           my $d = deferred;
131              
132 0           $d->resolve( $self->value <= $other->value );
133              
134 0           return $d->promise;
135             }
136              
137             sub is_greater {
138 0     0 0   my ( $self, $engine, $other ) = @_;
139              
140 0           my $d = deferred;
141              
142 0           $d->resolve( $self->value > $other->value );
143              
144 0           return $d->promise;
145             }
146              
147             sub is_greater_or_equal {
148 0     0 0   my ( $self, $engine, $other ) = @_;
149              
150 0           my $d = deferred;
151              
152 0           $d->resolve( $self->value >= $other->value );
153              
154 0           return $d->promise;
155             }
156              
157             sub prepend {
158 0     0 0   my( $self, @things ) = @_;
159              
160             # if durations, we add
161             # if numeric, we add as seconds
162             # otherwise, we can't prepend
163 0 0 0 0     if(any { !$_->isa('Dallycot::Value::Numeric') && !$_->isa('Dallycot::Value::Duration') } @things) {
  0            
164 0           croak 'Only durations and numeric values may be added to dates and times';
165             }
166              
167 0           my @durations = map {
168 0           my $v = $_;
169 0           given(blessed $v) {
170 0           when('Dallycot::Value::Numeric') {
171 0           DateTime::Duration->new(
172             seconds => $v->value->numify
173             );
174             }
175 0           when('Dallycot::Value::Duration') {
176 0           $v -> value;
177             }
178             }
179             } @things;
180              
181 0           my $accumulator = $self->value;
182 0           $accumulator = $accumulator + $_ for @durations;
183 0           return $self -> new(object => $accumulator, class => blessed($accumulator));
184             }
185              
186             1;