File Coverage

blib/lib/Time/Moment/Role/TimeZone.pm
Criterion Covered Total %
statement 30 31 96.7
branch 4 8 50.0
condition 2 8 25.0
subroutine 7 7 100.0
pod 4 4 100.0
total 47 58 81.0


line stmt bran cond sub pod time code
1             package Time::Moment::Role::TimeZone;
2              
3 2     2   1581 use Role::Tiny;
  2         6  
  2         18  
4 2     2   443 use Carp ();
  2         7  
  2         45  
5 2     2   1277 use Time::Local ();
  2         5973  
  2         924  
6              
7             our $VERSION = '0.002';
8              
9             requires qw(epoch offset with_offset_same_instant with_offset_same_local
10             utc_rd_as_seconds utc_rd_values local_rd_as_seconds local_rd_values utc_year);
11              
12             sub with_time_zone_offset_same_instant {
13 2     2 1 3059 my ($self, $tz) = @_;
14 2 50 33     23 Carp::croak "Invalid time zone object $tz" unless defined $tz and $tz->can('offset_for_datetime');
15 2         11 return $self->with_offset_same_instant($tz->offset_for_datetime($self) / 60);
16             }
17              
18             sub with_time_zone_offset_same_local {
19 2     2 1 4579 my ($self, $tz) = @_;
20 2 50 33     21 Carp::croak "Invalid time zone object $tz" unless defined $tz and $tz->can('offset_for_local_datetime');
21 2         8 my ($offset, $error);
22 2         4 { local $@;
  2         4  
23 2 50       5 unless (eval { $offset = $tz->offset_for_local_datetime($self); 1 }) {
  2         8  
  2         12  
24 0   0     0 $error = $@ || 'Error';
25             }
26             }
27 2 50       8 Carp::croak $error if defined $error;
28 2         21 return $self->with_offset_same_local($offset / 60);
29             }
30              
31             sub with_system_offset_same_instant {
32 1     1 1 944 my ($self) = @_;
33 1         9 my $time = $self->epoch;
34 1         28 my $offset = Time::Local::timegm_nocheck(localtime $time) - $time;
35 1         50 return $self->with_offset_same_instant($offset / 60);
36             }
37              
38             sub with_system_offset_same_local {
39 1     1 1 1890 my ($self) = @_;
40 1         13 my $time = $self->epoch + $self->offset * 60;
41 1         10 my $offset = $time - Time::Local::timelocal_nocheck(gmtime $time);
42 1         80 return $self->with_offset_same_local($offset / 60);
43             }
44              
45             1;
46              
47             =head1 NAME
48              
49             Time::Moment::Role::TimeZone - Adjust Time::Moment with time zone objects
50              
51             =head1 SYNOPSIS
52              
53             use Time::Moment;
54             use Role::Tiny ();
55             use DateTime::TimeZone;
56              
57             my $class = Role::Tiny->create_class_with_roles('Time::Moment', 'Time::Moment::Role::TimeZone');
58              
59             my $tz = DateTime::TimeZone->new(name => 'America/New_York');
60             my $tm = $class->from_epoch(1000212360)->with_time_zone_offset_same_instant($tz);
61              
62             use DateTime::TimeZone::Olson 'olson_tz';
63              
64             my $tz = olson_tz('Europe/Oslo');
65             my $tm = Time::Moment->new(year => 2012, month => 3, day => 4, hour => 13, minute => 7, second => 42);
66             Role::Tiny->apply_roles_to_object($tm, 'Time::Moment::Role::TimeZone');
67             $tm = $tm->with_time_zone_offset_same_local($tz);
68              
69             my $tm = $class->from_epoch(1522095272)->with_system_offset_same_instant;
70              
71             my $tm = $class->new_from_string('2009-05-02T12:15:30Z')->with_system_offset_same_local;
72              
73             =head1 DESCRIPTION
74              
75             This role provides convenience methods to return a new L object
76             adjusted according to a L/
77             L<::Tzfile|DateTime::TimeZone::Tzfile>-compatible time zone object, as in
78             L. See L regarding usage with date math.
79              
80             =head1 METHODS
81              
82             =head2 with_time_zone_offset_same_instant
83              
84             my $same_instant = $tm->with_time_zone_offset_same_instant($tz);
85              
86             Returns a L of the same instant, but at an offset from UTC
87             according to the given time zone object at that instant.
88              
89             =head2 with_time_zone_offset_same_local
90              
91             my $same_local = $tm->with_time_zone_offset_same_local($tz);
92              
93             Returns a L of the same local time, with an offset from UTC
94             according to the given time zone object at that local time.
95              
96             If the local time of the L object is ambiguous in the given time
97             zone (such as when Daylight Savings Time ends), the time zone object will
98             usually use the earliest time. If the local time does not exist (such as when
99             Daylight Savings Time starts), the time zone object will usually throw an
100             exception.
101              
102             =head2 with_system_offset_same_instant
103              
104             my $same_instant = $tm->with_system_offset_same_instant;
105              
106             As in L, but using the system local time
107             zone via L.
108              
109             =head2 with_system_offset_same_local
110              
111             my $same_local = $tm->with_system_offset_same_local;
112              
113             As in L, but using the system local time
114             zone via L.
115              
116             If the local time of the L object is ambiguous in the system
117             local time zone (such as when Daylight Savings Time ends), L will
118             use the earliest time. If the local time does not exist (such as when Daylight
119             Savings Time starts), L will use the time one hour later.
120              
121             =head1 CAVEATS
122              
123             L does not store a time zone; these methods only set the offset
124             and local time for the instantaneous moment represented by the object. After
125             doing date math with the object, new times may need to be corrected, based on
126             whether the date math was intended to be done relative to the absolute or local
127             time.
128              
129             my $tm = $class->now_utc->with_time_zone_offset_same_instant($tz); # now in $tz
130             my $next_day = $tm->plus_days(1)->with_time_zone_offset_same_local($tz); # 1 day from now in $tz
131             my $24h_later = $tm->plus_days(1)->with_time_zone_offset_same_instant($tz); # 24 hours from now in $tz
132              
133             my $tm = $class->now; # now in system local time
134             my $next_day = $tm->plus_days(1)->with_system_offset_same_local; # 1 day from now in system local time
135             my $24h_later = $tm->plus_days(1)->with_system_offset_same_instant; # 24 hours from now in system local time
136              
137             Note that L may throw an exception here if
138             the new local time does not exist in that time zone (e.g. between 2 and 3 AM at
139             the start of Daylight Savings Time).
140              
141             =head1 BUGS
142              
143             Report any issues on the public bugtracker.
144              
145             =head1 AUTHOR
146              
147             Dan Book
148              
149             =head1 CONTRIBUTORS
150              
151             =over
152              
153             =item Christian Hansen (chansen)
154              
155             =back
156              
157             =head1 COPYRIGHT AND LICENSE
158              
159             This software is Copyright (c) 2018 by Dan Book.
160              
161             This is free software, licensed under:
162              
163             The Artistic License 2.0 (GPL Compatible)
164              
165             =head1 SEE ALSO
166              
167             L, L, L