line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
package MooseX::TimestampTZ; |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
=head1 NAME |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
MooseX::Timestamp - simple timestamp type for Moose, with Time Zone |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 SYNOPSIS |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use MooseX::TimestampTZ qw(:all); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
print zone 0; # +0000 |
13
|
|
|
|
|
|
|
print zone 0, 1; # Z |
14
|
|
|
|
|
|
|
print zone 12*3600; # +1200 |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
print offset_s "Z"; # 0 |
17
|
|
|
|
|
|
|
print offset_s "+1200"; # 43200 (= 12 * 3600) |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# local times |
20
|
|
|
|
|
|
|
print timestamptz; # 2007-12-06 23:23:22+1300 |
21
|
|
|
|
|
|
|
print timestamptz 0; # 1970-01-01 12:00:00+1200 |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# UTC times |
24
|
|
|
|
|
|
|
print gmtimestamptz; # 2007-12-06 10:23:22+0000 |
25
|
|
|
|
|
|
|
print gmtimestamptz 0; # 1970-01-01 00:00:00+0000 |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# hires timestamps |
28
|
|
|
|
|
|
|
print tmtimestamptz 0.123; # 1970-01-01 00:00:00.123+0000 |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
use MooseX::TimestampTZ ":all" => { hires => 1 }; |
31
|
|
|
|
|
|
|
print tmtimestamptz; # 2010-07-20 14:13:23.73418+1200 |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# conversion the other way |
34
|
|
|
|
|
|
|
print epoch "1970-01-01 00:00:00+0000"; # 0 |
35
|
|
|
|
|
|
|
print epoch "1970-01-01 12:00:00+1200"; # 0 |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
print for epochtz "1970-01-01 12:00:00+1200"; # 0, 43200 |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# you can get these ISO forms if you want, too. functions |
40
|
|
|
|
|
|
|
# that take a timestamptz accept either |
41
|
|
|
|
|
|
|
package SomewhereElse; |
42
|
|
|
|
|
|
|
use MooseX::TimestampTZ gmtimestamptz => { use_z => 1 }; |
43
|
|
|
|
|
|
|
print gmtimestamptz 0; # 1970-01-01 00:00:00Z |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
package MyClass; |
46
|
|
|
|
|
|
|
use Moose; |
47
|
|
|
|
|
|
|
has 'stamp' => |
48
|
|
|
|
|
|
|
isa => "Timestamp", |
49
|
|
|
|
|
|
|
is => "rw", |
50
|
|
|
|
|
|
|
coerce => 1; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
package main; |
53
|
|
|
|
|
|
|
my $obj = MyClass->new(stamp => "2007-01-02 12:00:12"); # ok |
54
|
|
|
|
|
|
|
$obj->stamp("2007-01-02 12:01"); |
55
|
|
|
|
|
|
|
$obj->stamp("2007-01-02 12"); |
56
|
|
|
|
|
|
|
$obj->stamp("2007-01-02 12:00:00Gibbons"); #fail |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head1 DESCRIPTION |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
This module provides floating dates on the Gregorian calendar without |
61
|
|
|
|
|
|
|
much code. It operates in (one particular variant of) ISO-8601 date |
62
|
|
|
|
|
|
|
format with time zone, and epoch times. Sub-second resolution is not |
63
|
|
|
|
|
|
|
yet supported. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=cut |
66
|
|
|
|
|
|
|
|
67
|
3
|
|
|
3
|
|
44250
|
use strict; |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
130
|
|
68
|
3
|
|
|
3
|
|
19
|
use warnings; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
114
|
|
69
|
3
|
|
|
3
|
|
16
|
use Carp; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
530
|
|
70
|
3
|
|
|
3
|
|
842
|
use MooseX::Timestamp qw(:all); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
use Moose::Util::TypeConstraints; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub _curry { |
74
|
|
|
|
|
|
|
my $class = shift; |
75
|
|
|
|
|
|
|
my $name = shift; |
76
|
|
|
|
|
|
|
my $arg_h = shift; |
77
|
|
|
|
|
|
|
my $col_h = shift; |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
my $chain = \&$name; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
if ( defined $arg_h->{use_z} or defined $col_h->{defaults}{use_z} ) { |
82
|
|
|
|
|
|
|
my $use_z = defined $arg_h->{use_z} ? |
83
|
|
|
|
|
|
|
$arg_h->{use_z} : $col_h->{defaults}{use_z}; |
84
|
|
|
|
|
|
|
my $old_chain = $chain; |
85
|
|
|
|
|
|
|
$chain = sub { $old_chain->($_[0], $use_z) }; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
if ( defined $arg_h->{hires} or defined $col_h->{defaults}{hires} ) { |
89
|
|
|
|
|
|
|
my $hires = defined $arg_h->{hires} ? |
90
|
|
|
|
|
|
|
$arg_h->{hires} : $col_h->{defaults}{hires}; |
91
|
|
|
|
|
|
|
if ( $hires ) { |
92
|
|
|
|
|
|
|
require Time::HiRes; |
93
|
|
|
|
|
|
|
my $old_chain = $chain; |
94
|
|
|
|
|
|
|
$chain = sub { |
95
|
|
|
|
|
|
|
$old_chain->( |
96
|
|
|
|
|
|
|
defined($_[0])?$_[0]:&Time::HiRes::time, |
97
|
|
|
|
|
|
|
@_[1..$#_], |
98
|
|
|
|
|
|
|
); |
99
|
|
|
|
|
|
|
}; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
$chain; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub _curry_epoch { |
107
|
|
|
|
|
|
|
my $class = shift; |
108
|
|
|
|
|
|
|
my $name = shift; |
109
|
|
|
|
|
|
|
my $arg_h = shift; |
110
|
|
|
|
|
|
|
my $col_h = shift; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
my $chain = \&$name; |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
if ( defined $arg_h->{hires} or defined $col_h->{defaults}{hires} ) { |
115
|
|
|
|
|
|
|
my $hires = defined $arg_h->{hires} ? |
116
|
|
|
|
|
|
|
$arg_h->{hires} : $col_h->{defaults}{hires}; |
117
|
|
|
|
|
|
|
if ( $hires ) { |
118
|
|
|
|
|
|
|
require Time::HiRes; |
119
|
|
|
|
|
|
|
my $old_chain = $chain; |
120
|
|
|
|
|
|
|
$chain = sub { |
121
|
|
|
|
|
|
|
if ( @_ ) { |
122
|
|
|
|
|
|
|
$old_chain->(@_); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
else { |
125
|
|
|
|
|
|
|
return &Time::HiRes::time; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
}; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
$chain; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
use Sub::Exporter -setup => |
135
|
|
|
|
|
|
|
{ exports => |
136
|
|
|
|
|
|
|
[ qw(offset_s timestamp posixtime epochtz), |
137
|
|
|
|
|
|
|
epoch => \&_curry_epoch, |
138
|
|
|
|
|
|
|
map { ($_ => \&_curry) } qw(zone timestamptz gmtimestamptz), |
139
|
|
|
|
|
|
|
], |
140
|
|
|
|
|
|
|
groups => |
141
|
|
|
|
|
|
|
{ default => [ qw(timestamptz gmtimestamptz epoch) ] }, |
142
|
|
|
|
|
|
|
collectors => { defaults => sub { |
143
|
|
|
|
|
|
|
1; |
144
|
|
|
|
|
|
|
} }, |
145
|
|
|
|
|
|
|
}; |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
subtype "TimestampTZ" |
148
|
|
|
|
|
|
|
=> as "Str" |
149
|
|
|
|
|
|
|
=> where { |
150
|
|
|
|
|
|
|
m{^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[\-+]\d{4}|Z)$} |
151
|
|
|
|
|
|
|
and do { |
152
|
|
|
|
|
|
|
my $x; |
153
|
|
|
|
|
|
|
eval { $x = epoch($_) }; |
154
|
|
|
|
|
|
|
warn "Error: $@ on $_" if $@; |
155
|
|
|
|
|
|
|
!$@ |
156
|
|
|
|
|
|
|
}; |
157
|
|
|
|
|
|
|
}; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
use Time::Local; |
160
|
|
|
|
|
|
|
use Memoize; |
161
|
|
|
|
|
|
|
memoize qw(zone); |
162
|
|
|
|
|
|
|
sub zone { |
163
|
|
|
|
|
|
|
my $offset_s = shift; |
164
|
|
|
|
|
|
|
my $use_z = shift; |
165
|
|
|
|
|
|
|
if ( $use_z and $offset_s == 0 ) { |
166
|
|
|
|
|
|
|
"Z"; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
else { |
169
|
|
|
|
|
|
|
my $hh = sprintf("%.2d", int(abs($offset_s)/3600)); |
170
|
|
|
|
|
|
|
my $mm = sprintf("%.2d", int((abs($offset_s)-$hh*3600)/60)); |
171
|
|
|
|
|
|
|
my $s = ( $offset_s >= 0 ? "+" : "-" ); |
172
|
|
|
|
|
|
|
"$s$hh$mm"; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub offset_s { |
177
|
|
|
|
|
|
|
my $zone = shift or croak "no zone passed to offset_s!"; |
178
|
|
|
|
|
|
|
if ( $zone eq "Z" ) { |
179
|
|
|
|
|
|
|
return 0; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
elsif ( $zone =~ m{^([\-+])(\d{2}):?(\d{2})?$}) { |
182
|
|
|
|
|
|
|
return ( ($1 eq "-" ? -1 : 1) * |
183
|
|
|
|
|
|
|
(($2 * 60) + ($3||0)) * 60 ); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
else { |
186
|
|
|
|
|
|
|
croak "no timezone on '$zone'"; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub timestamptz { |
191
|
|
|
|
|
|
|
my $time = shift; |
192
|
|
|
|
|
|
|
defined($time)||($time = time); |
193
|
|
|
|
|
|
|
my $use_z = shift; |
194
|
|
|
|
|
|
|
my @lt = localtime(int($time)); |
195
|
|
|
|
|
|
|
my $offset_s = timegm(@lt) - int($time); |
196
|
|
|
|
|
|
|
if ( int($time) != $time ) { |
197
|
|
|
|
|
|
|
$lt[0] += $time - int($time); |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
timestamp(@lt).zone($offset_s, $use_z); |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub gmtimestamptz { |
203
|
|
|
|
|
|
|
my $time = shift; |
204
|
|
|
|
|
|
|
defined($time)||($time = time); |
205
|
|
|
|
|
|
|
my $use_z = shift; |
206
|
|
|
|
|
|
|
my @gt = gmtime($time); |
207
|
|
|
|
|
|
|
if ( int($time) != $time ) { |
208
|
|
|
|
|
|
|
$gt[0] += $time - int($time); |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
timestamp(@gt).zone(0, $use_z); |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub epochtz { |
214
|
|
|
|
|
|
|
my $timestamptz = shift || timestamptz; |
215
|
|
|
|
|
|
|
my ($timestamp, $zone) = |
216
|
|
|
|
|
|
|
($timestamptz =~ m{^(.*)([\-+]\d{2}(?::?\d{2})?|Z)$}x) |
217
|
|
|
|
|
|
|
or die "bad TimestampTZ passed to epoch: '$timestamptz'"; |
218
|
|
|
|
|
|
|
my @wct = posixtime($timestamp); |
219
|
|
|
|
|
|
|
my $frac = $wct[0] - int($wct[0]); |
220
|
|
|
|
|
|
|
$wct[0] = int($wct[0]); |
221
|
|
|
|
|
|
|
my $offset_s = offset_s($zone); |
222
|
|
|
|
|
|
|
(timegm(@wct) - $offset_s + $frac, $offset_s); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub epoch { |
226
|
|
|
|
|
|
|
return time unless @_; |
227
|
|
|
|
|
|
|
return (epochtz(@_))[0]; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
subtype 'time_t' |
231
|
|
|
|
|
|
|
=> as "Int"; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
sub _looks_like_timestamp { |
234
|
|
|
|
|
|
|
my ($epoch, $off) = eval { epochtz $_ }; |
235
|
|
|
|
|
|
|
if ( defined $epoch ) { |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
elsif ( eval { valid_posixtime(posixtime($_)) } and !$@ ) { |
238
|
|
|
|
|
|
|
my @gt = posixtime($_); |
239
|
|
|
|
|
|
|
my $frac = $gt[0] - int($gt[0]); |
240
|
|
|
|
|
|
|
$gt[0] = int($gt[0]); |
241
|
|
|
|
|
|
|
my $gmtime = timegm(@gt); |
242
|
|
|
|
|
|
|
my $localtime = timelocal(@gt); |
243
|
|
|
|
|
|
|
$epoch = $localtime + $frac; |
244
|
|
|
|
|
|
|
$off = ($localtime - $gmtime); |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
else { |
247
|
|
|
|
|
|
|
croak "bad TimestampTZ $_"; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
if ( wantarray ) { |
250
|
|
|
|
|
|
|
return ($epoch, $off); |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
else { |
253
|
|
|
|
|
|
|
return $epoch; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
coerce 'time_t' |
258
|
|
|
|
|
|
|
=> from "Num" |
259
|
|
|
|
|
|
|
=> via { $_ }, |
260
|
|
|
|
|
|
|
=> from "TimestampTZ" |
261
|
|
|
|
|
|
|
=> via { epoch($_) } |
262
|
|
|
|
|
|
|
=> from "Str" |
263
|
|
|
|
|
|
|
=> via \&_looks_like_timestamp; |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
coerce 'Timestamp' |
266
|
|
|
|
|
|
|
=> from "TimestampTZ" |
267
|
|
|
|
|
|
|
=> via { |
268
|
|
|
|
|
|
|
my $epoch = epoch($_); |
269
|
|
|
|
|
|
|
my $frac = $epoch - int($epoch); |
270
|
|
|
|
|
|
|
my @lt = localtime(int($epoch)); |
271
|
|
|
|
|
|
|
$lt[0] += $frac; |
272
|
|
|
|
|
|
|
timestamp(@lt); |
273
|
|
|
|
|
|
|
}; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# traditionally, coercing a timestamp to one with time zone and back |
276
|
|
|
|
|
|
|
# uses the local time, with the resultant ambiguities |
277
|
|
|
|
|
|
|
coerce 'TimestampTZ' |
278
|
|
|
|
|
|
|
=> from "TimestampTZ" |
279
|
|
|
|
|
|
|
=> via { $_ }, |
280
|
|
|
|
|
|
|
=> from "time_t" |
281
|
|
|
|
|
|
|
=> via { timestamptz($_) } |
282
|
|
|
|
|
|
|
=> from "Timestamp" |
283
|
|
|
|
|
|
|
=> via { |
284
|
|
|
|
|
|
|
my @lt = posixtime($_); |
285
|
|
|
|
|
|
|
my $frac = $lt[0] - int($lt[0]); |
286
|
|
|
|
|
|
|
$lt[0] = int($lt[0]); |
287
|
|
|
|
|
|
|
timestamptz(timelocal(@lt)+$frac); |
288
|
|
|
|
|
|
|
}, |
289
|
|
|
|
|
|
|
=> from "Str" |
290
|
|
|
|
|
|
|
=> via { |
291
|
|
|
|
|
|
|
my ($epoch, $off) = _looks_like_timestamp; |
292
|
|
|
|
|
|
|
my $frac = $epoch - int($epoch); |
293
|
|
|
|
|
|
|
my @gt = gmtime(int($epoch)+$off); |
294
|
|
|
|
|
|
|
$gt[0] += $frac; |
295
|
|
|
|
|
|
|
timestamp(@gt).zone($off); |
296
|
|
|
|
|
|
|
}; |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=head1 FUNCTIONS |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
The following functions are available for import. If you want to |
301
|
|
|
|
|
|
|
import them all, use the C<:all> import group, as below: |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
use MooseX::TimestampTZ qw(:all); |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=head2 zone(Int $offset, Bool $use_z = false) |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
Returns the timezone of the given offset. Pass $use_z to select |
308
|
|
|
|
|
|
|
returning "Z" as a timezone if the offset is 0. |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=head2 offset_s(Str) |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
Returns the offset corresponding to the given timezone. Does NOT |
313
|
|
|
|
|
|
|
accept nicknames like "EST", etc (which EST did you mean, US or |
314
|
|
|
|
|
|
|
Australian Eastern Standard Time?). |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=head2 timestamptz(time_t $time_t = time(), Bool $use_z = false) |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
Returns the passed epoch time as a valid TimestampTZ, according to the |
319
|
|
|
|
|
|
|
local time zone rules in effect. C<$use_z> functions as with C<zone>. |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=head2 gmtimestamptz(time_t $time_t = time(), Bool $use_z = false) |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
Returns the passed epoch time as a valid TimestampTZ, corresponding to |
324
|
|
|
|
|
|
|
the time in UTC. C<$use_z> functions as with C<zone>, and if passed |
325
|
|
|
|
|
|
|
this function will always return TimestampTZs ending with C<Z>. |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head2 epoch() |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Synonym for the built-in C<time()>. |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head2 epoch(TimestampTZ) |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
Converts the passed TimestampTZ value to an epoch time. Does B<not> |
334
|
|
|
|
|
|
|
perform any coercion - the passed value must already have a time zone |
335
|
|
|
|
|
|
|
on it. You may omit any part of the time, specify the time zone in |
336
|
|
|
|
|
|
|
hours or with a C<Z>, and optionally separate your time from your date |
337
|
|
|
|
|
|
|
with a C<T>. Single digit values for fields are accepted. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
Example valid forms: |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
2007-12-07 16:34:02+1200 |
342
|
|
|
|
|
|
|
2007-12-07 16:34+12 |
343
|
|
|
|
|
|
|
2007-12-07 04Z |
344
|
|
|
|
|
|
|
2007-12-7T4Z |
345
|
|
|
|
|
|
|
2007-12-7+12 |
346
|
|
|
|
|
|
|
2007120704:12:32 # Date::Manip format |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
Examples of ISO-8601 valid forms which are not currently accepted: |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
07-12-07Z |
351
|
|
|
|
|
|
|
071207Z |
352
|
|
|
|
|
|
|
20071207Z # seperators required |
353
|
|
|
|
|
|
|
2007120704Z |
354
|
|
|
|
|
|
|
-12-07Z # no year specified |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
No locale-specific date forms, such as C</> delimited dates, are |
357
|
|
|
|
|
|
|
accepted. |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
=head2 epochtz(...) |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
Just like C<epoch()>, except returns the timezone as well. |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
=head1 TYPES AND COERCIONS |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
The following subtypes are defined by this module: |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=head2 TimestampTZ |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
This is a subtype of C<Str> which conforms to one of the two |
370
|
|
|
|
|
|
|
normalized forms of a TimestampTZ (either with a Z, or without). |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
Rules exist to coerce C<Str>, C<Timestamp> and C<time_t> to this type, |
373
|
|
|
|
|
|
|
and are available by using the C<coerce =E<gt> 1> flag on a Moose |
374
|
|
|
|
|
|
|
attribute declaration: |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
package Widget; |
377
|
|
|
|
|
|
|
use MooseX::TimestampTZ; |
378
|
|
|
|
|
|
|
has 'created' => |
379
|
|
|
|
|
|
|
isa => TimestampTZ, |
380
|
|
|
|
|
|
|
is => "rw", |
381
|
|
|
|
|
|
|
coerce => 1; |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
With the above, if you set C<created> to a time_t value, it will |
384
|
|
|
|
|
|
|
automatically get converted into a TimestampTZ in the current time |
385
|
|
|
|
|
|
|
zone. |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
A TimestampTZ value with a fractional second part is considered valid, |
388
|
|
|
|
|
|
|
regardless of whether C<hires> is passed to the importer. |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
B<New in 0.07>: Timestamp to TimestampTZ conversion now happens in |
391
|
|
|
|
|
|
|
I<local time>, not UTC. |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=head2 time_t |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
C<time_t> is a nicer way of writing an epoch time. If you set |
396
|
|
|
|
|
|
|
C<coerce =E<gt> 1> on your accessors, then you can happily pass in |
397
|
|
|
|
|
|
|
timestamps. As of MooseX::Timestamp 0.07, B<time_t> is a C<Num>, not |
398
|
|
|
|
|
|
|
merely an C<Int>. |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=head1 EXPORTS |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
The default exporting action of this module is to export the |
403
|
|
|
|
|
|
|
C<timestamptz>, C<gmtimestamptz> and C<epoch> methods. To avoid this, |
404
|
|
|
|
|
|
|
pass an empty argument list to the use statement: |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
use MooseX::TimestampTZ (); |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=head2 ISO-8601 "Z" TIMEZONE |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
Several of the functions which return a timezone may be told to return |
411
|
|
|
|
|
|
|
"Z" if the offset is 0, that is, the time is in UTC. To select this, |
412
|
|
|
|
|
|
|
pass a true second argument to any of the three functions (C<zone>, |
413
|
|
|
|
|
|
|
C<timestamptz> and C<gmtimestamptz>), or curry them on import; |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
use MooseX::TimestampTZ qw(:default), defaults => { use_z => 1 }; |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
You can also curry individual functions like this: |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
use MooseX::TimestampTZ zone => { use_z => 1 }; |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
=cut |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=head1 BUGS |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
This module is relatively slow, as conversions and calls to C<timegm> |
426
|
|
|
|
|
|
|
and friends happen far too often, really - especially with coercion. |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=head1 AUTHOR AND LICENSE |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
Sam Vilain, <samv@cpan.org> |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
Copyright 2007, Sam Vilain. All Rights Reserved. This program is |
433
|
|
|
|
|
|
|
Free Software; you may use it and/or redistribute it under the terms |
434
|
|
|
|
|
|
|
of Perl itself. |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
=cut |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
1; |