File Coverage

blib/lib/DBIx/Class/InflateColumn/TimeMoment.pm
Criterion Covered Total %
statement 47 50 94.0
branch 8 14 57.1
condition 6 11 54.5
subroutine 15 15 100.0
pod 1 1 100.0
total 77 91 84.6


line stmt bran cond sub pod time code
1             package DBIx::Class::InflateColumn::TimeMoment;
2              
3             # ABSTRACT: Auto-create TimeMoment objects from date and datetime columns.
4              
5 1     1   126829 use 5.008; # enforce minimum perl version of 5.8
  1         3  
6 1     1   3 use strict;
  1         1  
  1         15  
7 1     1   2 use warnings;
  1         1  
  1         43  
8              
9             our $VERSION = '0.050'; # VERSION
10             our $AUTHORITY = 'cpan:NIGELM'; # AUTHORITY
11              
12              
13 1     1   3 use base qw/DBIx::Class/;
  1         1  
  1         53  
14 1     1   4 use Try::Tiny;
  1         1  
  1         40  
15 1     1   3 use namespace::clean;
  1         1  
  1         4  
16              
17             __PACKAGE__->load_components(qw/InflateColumn/);
18              
19              
20             sub register_column {
21 2     2 1 447 my ( $self, $column, $info, @rest ) = @_;
22              
23 2         5 $self->next::method( $column, $info, @rest );
24              
25 2         637 my $requested_type;
26 2         3 for (qw/datetime timestamp date/) {
27 6         6 my $key = "inflate_${_}";
28 6 50       17 if ( exists $info->{$key} ) {
29              
30             # this bailout is intentional
31 0 0       0 return unless $info->{$key};
32              
33 0         0 $requested_type = $_;
34 0         0 last;
35             }
36             }
37              
38 2 50 33     7 return if ( !$requested_type and !$info->{data_type} );
39              
40 2   50     6 my $data_type = lc( $info->{data_type} || '' );
41              
42 2 50 66     13 return unless ( ( $data_type eq 'datetime' ) or ( $data_type eq 'timestamp' ) or ( $data_type eq 'date' ) );
      66        
43              
44             # shallow copy to avoid unfounded(?) Devel::Cycle complaints
45 1         3 my $infcopy = {%$info};
46              
47             $self->inflate_column(
48             $column => {
49             inflate => sub {
50 11     11   25536 my ( $value, $obj ) = @_;
51              
52             # propagate for error reporting
53 11         20 $infcopy->{__dbic_colname} = $column;
54              
55 11         27 my $dt = $obj->_inflate_to_timemoment( $value, $infcopy );
56              
57 11 100       181 return ( defined $dt )
58             ? $obj->_post_inflate_timemoment( $dt, $infcopy )
59             : undef;
60             },
61             deflate => sub {
62 3     3   302806 my ( $value, $obj ) = @_;
63              
64 3         10 $value = $obj->_pre_deflate_timemoment( $value, $infcopy );
65 3         8 $obj->_deflate_from_timemoment( $value, $infcopy );
66             },
67             }
68 1         14 );
69             }
70              
71             sub _inflate_to_timemoment {
72 11     11   17 my ( $self, $value, $info ) = @_;
73              
74             # Any value should include a timezone element
75             # Should a value not include any timezone element, we add a Z to force
76             # the timestamp into GMT. This will not fix any other syntax issues,
77             # but does allow, eg PostgreSQL timestamps to be inflated correctly
78             # MATCHES: Z or +/- 2 digit timestamp or 4 digit timestamp or UTC/GMT
79 11 100       111 $value .= 'Z'
80             unless ( $value =~ /(?: Z | (?: [+-] \d{2} (?: :? \d{2} )? ) | UTC | GMT )$/x );
81              
82             return try {
83 11     11   459 Time::Moment->from_string( $value, lenient => 1 );
84             }
85             catch {
86             $self->throw_exception("Error while inflating '$value' for $info->{__dbic_colname} on ${self}: $_")
87 2 50   2   29 unless $info->{datetime_undef_if_invalid};
88 2         11 undef; # rv
89 11         88 };
90             }
91              
92             sub _deflate_from_timemoment {
93 3     3   4 my ( $self, $value ) = @_;
94 3         40 return $value->to_string;
95             }
96              
97             sub _post_inflate_timemoment {
98 9     9   14 my ( $self, $dt ) = @_;
99              
100 9         63 return $dt;
101             }
102              
103             sub _pre_deflate_timemoment {
104 3     3   3 my ( $self, $dt ) = @_;
105              
106 3         5 return $dt;
107             }
108              
109             1;
110              
111             __END__