File Coverage

blib/lib/Metabrik/Time/Universal.pm
Criterion Covered Total %
statement 9 230 3.9
branch 0 70 0.0
condition 0 39 0.0
subroutine 3 22 13.6
pod 1 19 5.2
total 13 380 3.4


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # time::universal Brik
5             #
6             package Metabrik::Time::Universal;
7 1     1   582 use strict;
  1         3  
  1         29  
8 1     1   5 use warnings;
  1         2  
  1         28  
9              
10 1     1   5 use base qw(Metabrik);
  1         2  
  1         629  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable timezone) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             timezone => [ qw(string) ],
20             separator => [ qw(character) ],
21             use_hires => [ qw(0|1) ],
22             },
23             attributes_default => {
24             timezone => [ 'Europe/Paris' ],
25             separator => '-',
26             use_hires => 0,
27             },
28             commands => {
29             list_timezones => [ ],
30             search_timezone => [ qw(string) ],
31             localtime => [ qw(timezone|OPTIONAL) ],
32             hour => [ ],
33             today => [ qw(separator|OPTIONAL) ],
34             yesterday => [ qw(separator|OPTIONAL) ],
35             day => [ qw(timestamp|OPTIONAL) ],
36             week => [ qw(timestamp|OPTIONAL) ],
37             year => [ qw(timestamp|OPTIONAL) ],
38             date => [ qw(timestamp|OPTIONAL) ],
39             gmdate => [ qw(timestamp|OPTIONAL) ],
40             month => [ qw(timezone|OPTIONAL) ],
41             last_month => [ qw(timezone|OPTIONAL) ],
42             is_timezone => [ qw(timezone) ],
43             timestamp => [ ],
44             to_timestamp => [ qw(string) ],
45             timestamp_to_tz_time => [ qw(timestamp|OPTIONAL) ],
46             timestamp_to_tz_gmtime => [ qw(timestamp|OPTIONAL) ],
47             },
48             require_modules => {
49             'DateTime' => [ ],
50             'DateTime::TimeZone' => [ ],
51             'POSIX' => [ qw(strftime) ],
52             'Time::Local' => [ qw(timelocal) ],
53             'Time::HiRes' => [ qw(time) ],
54             'Date::Calc' => [ qw(Today Day_of_Week) ],
55             },
56             };
57             }
58              
59             sub list_timezones {
60 0     0 0   my $self = shift;
61              
62 0           return DateTime::TimeZone->all_names;
63             }
64              
65             sub search_timezone {
66 0     0 0   my $self = shift;
67 0           my ($pattern) = @_;
68              
69 0 0         $self->brik_help_run_undef_arg('search_timezone', $pattern) or return;
70              
71 0           my $list = $self->list_timezones;
72              
73 0           my @found = ();
74 0           for my $this (@$list) {
75 0 0         if ($this =~ /$pattern/i) {
76 0           push @found, $this;
77             }
78             }
79              
80 0           return \@found;
81             }
82              
83             sub localtime {
84 0     0 0   my $self = shift;
85 0           my ($timezone) = @_;
86              
87 0   0       $timezone ||= $self->timezone;
88 0 0         $self->brik_help_run_undef_arg('localtime', $timezone) or return;
89              
90 0           my $time = {};
91 0 0         if (ref($timezone) eq 'ARRAY') {
92 0           for my $tz (@$timezone) {
93 0 0         if (! $self->is_timezone($tz)) {
94 0           $self->log->warning("localtime: invalid timezone [$timezone]");
95 0           next;
96             }
97 0           my $dt = DateTime->now(
98             time_zone => $tz,
99             );
100 0           $time->{$tz} = "$dt";
101             }
102             }
103             else {
104 0 0         if (! $self->is_timezone($timezone)) {
105 0           return $self->log->error("localtime: invalid timezone [$timezone]");
106             }
107 0           my $dt = DateTime->now(
108             time_zone => $timezone,
109             );
110 0           $time->{$timezone} = "$dt";
111             }
112              
113 0           return $time;
114             }
115              
116             sub hour {
117 0     0 0   my $self = shift;
118              
119 0           my @a = CORE::localtime();
120 0           my $h = $a[2];
121              
122 0           return sprintf("%02d", $h);
123             }
124              
125             sub today {
126 0     0 0   my $self = shift;
127 0           my ($sep) = @_;
128              
129 0   0       $sep ||= $self->separator;
130              
131 0           my @a = CORE::localtime();
132 0           my $y = $a[5] + 1900;
133 0           my $m = $a[4] + 1;
134 0           my $d = $a[3];
135              
136 0           return sprintf("%04d$sep%02d$sep%02d", $y, $m, $d);
137             }
138              
139             sub yesterday {
140 0     0 0   my $self = shift;
141 0           my ($sep) = @_;
142              
143 0   0       $sep ||= $self->separator;
144              
145 0           my @a = CORE::localtime(time() - (24 * 3600));
146 0           my $y = $a[5] + 1900;
147 0           my $m = $a[4] + 1;
148 0           my $d = $a[3];
149              
150 0           return sprintf("%04d$sep%02d$sep%02d", $y, $m, $d);
151             }
152              
153             sub day {
154 0     0 0   my $self = shift;
155 0           my ($timestamp) = @_;
156              
157 0   0       $timestamp ||= $self->timestamp;
158              
159 0           my @t = CORE::localtime($timestamp);
160              
161 0           my $year = $t[5] + 1900;
162 0           my $month = $t[4] + 1;
163 0           my $day = $t[3];
164              
165 0           return sprintf("%04d-%02d-%02d", $year, $month, $day);
166             }
167              
168             sub week {
169 0     0 0   my $self = shift;
170 0           my ($timestamp) = @_;
171              
172 0   0       $timestamp ||= $self->timestamp;
173              
174 0           my ($year, $month, $day) = Date::Calc::Localtime($timestamp);
175 0           my $week = Date::Calc::Week_of_Year($year, $month, $day);
176              
177 0           return sprintf("%02d", $week);
178             }
179              
180             sub year {
181 0     0 0   my $self = shift;
182 0           my ($timestamp) = @_;
183              
184 0 0         my $day = $self->day($timestamp) or return;
185              
186 0           my ($year) = $day =~ m{^(\d{4})};
187              
188 0           return $year;
189             }
190              
191             sub date {
192 0     0 0   my $self = shift;
193 0           my ($timestamp) = @_;
194              
195 0   0       $timestamp ||= $self->timestamp;
196              
197 0           return CORE::localtime($timestamp)."";
198             }
199              
200             sub gmdate {
201 0     0 0   my $self = shift;
202 0           my ($timestamp) = @_;
203              
204 0   0       $timestamp ||= $self->timestamp;
205              
206 0           return POSIX::strftime("%a %b %e %H:%M:%S %Y", CORE::gmtime($timestamp));
207             }
208              
209             #
210             # timestamp => '2016-11-01T00:06:39.000Z'
211             #
212             sub timestamp_to_tz_time {
213 0     0 0   my $self = shift;
214 0           my ($timestamp) = @_;
215              
216 0   0       $timestamp ||= $self->timestamp;
217 0 0         $self->brik_help_run_undef_arg('timestamp_to_tz_time', $timestamp) or return;
218              
219 0 0         if ($self->use_hires) {
220 0   0       my $t = $timestamp || Time::HiRes::time();
221 0           my $date = POSIX::strftime("%Y-%m-%d".'T'."%H:%M:%S", CORE::localtime($t));
222 0           $date .= sprintf(".%03dZ", ($t-int($t))*1000); # without rounding
223              
224 0           return $date;
225             }
226              
227 0           return POSIX::strftime("%Y-%m-%d".'T'."%H:%M:%S.000Z", CORE::localtime($timestamp));
228             }
229              
230             sub timestamp_to_tz_gmtime {
231 0     0 0   my $self = shift;
232 0           my ($timestamp) = @_;
233              
234 0   0       $timestamp ||= $self->timestamp;
235 0 0         $self->brik_help_run_undef_arg('timestamp_to_tz_gmtime', $timestamp) or return;
236              
237 0 0         if ($self->use_hires) {
238 0   0       my $t = $timestamp || Time::HiRes::time();
239 0           my $date = POSIX::strftime("%Y-%m-%d".'T'."%H:%M:%S", CORE::gmtime($t));
240 0           $date .= sprintf(".%03dZ", ($t-int($t))*1000); # without rounding
241              
242 0           return $date;
243             }
244              
245 0           return POSIX::strftime("%Y-%m-%d".'T'."%H:%M:%S.000Z", CORE::gmtime($timestamp));
246             }
247              
248             sub month {
249 0     0 0   my $self = shift;
250 0           my ($sep) = @_;
251              
252 0   0       $sep ||= $self->separator;
253              
254 0           my @a = CORE::localtime();
255 0           my $y = $a[5] + 1900;
256 0           my $m = $a[4] + 1;
257              
258 0           return sprintf("%04d$sep%02d", $y, $m);
259             }
260              
261             sub last_month {
262 0     0 0   my $self = shift;
263 0           my ($sep) = @_;
264              
265 0   0       $sep ||= $self->separator;
266              
267 0           my @a = CORE::localtime();
268 0           my $y = $a[5] + 1900;
269 0           my $m = $a[4];
270              
271 0 0         if ($m == 0) {
272 0           $m = 12;
273 0           $y -= 1;
274             }
275              
276 0           return sprintf("%04d$sep%02d", $y, $m);
277             }
278              
279             sub is_timezone {
280 0     0 0   my $self = shift;
281 0           my ($tz) = @_;
282              
283 0 0         $self->brik_help_run_undef_arg('is_timezone', $tz) or return;
284              
285 0           my $tz_list = $self->list_timezones;
286 0           my %h = map { $_ => 1 } @$tz_list;
  0            
287              
288 0 0         return exists($h{$tz}) ? 1 : 0;
289             }
290              
291             sub timestamp {
292 0     0 0   my $self = shift;
293              
294 0 0         if ($self->use_hires) {
295 0           return Time::HiRes::time();
296             }
297              
298 0           return CORE::time();
299             }
300              
301             sub to_timestamp {
302 0     0 0   my $self = shift;
303 0           my ($string) = @_;
304              
305 0 0         $self->brik_help_run_undef_arg('to_timestamp', $string) or return;
306              
307 0           my %month = (
308             Jan => 0,
309             Feb => 1,
310             Mar => 2,
311             Apr => 3,
312             May => 4,
313             Jun => 5,
314             Jul => 6,
315             Aug => 7,
316             Sep => 8,
317             Oct => 9,
318             Nov => 10,
319             Dec => 11,
320             );
321              
322 0           my $timestamp = 0;
323             # 2015-12-30
324 0 0         if ($string =~ m{^(\d{4})-(\d{2})-(\d{2})$}) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
325 0           $timestamp = Time::Local::timelocal(0, 0, 12, $3, $2-1, $1);
326 0 0         if ($self->use_hires) {
327 0           my $msec = 0;
328 0           $timestamp .= sprintf(".%03d", $msec);
329             }
330             }
331             # 20190115
332             elsif ($string =~ m{^(\d{4})(\d{2})(\d{2})$}) {
333 0           $timestamp = Time::Local::timelocal(0, 0, 12, $3, $2-1, $1);
334 0 0         if ($self->use_hires) {
335 0           my $msec = 0;
336 0           $timestamp .= sprintf(".%03d", $msec);
337             }
338             }
339             # Wed Nov 9 07:01:18 2016
340             elsif ($string =~ m{^\S+\s+(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)$}) {
341 0           my $mon = $1;
342 0           my $mday = $2;
343 0           my $hour = $3;
344 0           my $min = $4;
345 0           my $sec = $5;
346 0           my $year = $6;
347 0           my $msec = $7;
348 0           $timestamp = Time::Local::timelocal($sec, $min, $hour, $mday, $month{$mon}, $year);
349 0 0         if ($self->use_hires) {
350 0           $timestamp .= sprintf(".%03d", $msec);
351             }
352             }
353             # May 17 18:23:47
354             elsif ($string =~ m{^(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)$}) {
355 0           my $mon = $1;
356 0           my $mday = $2;
357 0           my $hour = $3;
358 0           my $min = $4;
359 0           my $sec = $5;
360 0           my $msec = 0;
361 0           my @time = CORE::localtime();
362 0           my $year = $time[5] + 1900;
363 0           $timestamp = Time::Local::timelocal($sec, $min, $hour, $mday, $mon, $year);
364 0 0         if ($self->use_hires) {
365 0           $timestamp .= sprintf(".%03d", $msec);
366             }
367             }
368             # 2016-04-12T17:25:50.713Z
369             elsif ($string =~ m{^(\d{4})\-(\d{2})\-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$}) {
370 0           my $mon = $2 - 1;
371 0           my $mday = $3;
372 0           my $hour = $4;
373 0           my $min = $5;
374 0           my $sec = $6;
375 0           my $year = $1;
376 0           my $msec = $7;
377 0           $timestamp = Time::Local::timelocal($sec, $min, $hour, $mday, $mon, $year);
378 0 0         if ($self->use_hires) {
379 0           $timestamp .= sprintf(".%03d", $msec);
380             }
381             }
382             # 2019-10-23T18:15Z
383             elsif ($string =~ m{^(\d{4})\-(\d{2})\-(\d{2})T(\d{2}):(\d{2})Z$}) {
384 0           my $mon = $2 - 1;
385 0           my $mday = $3;
386 0           my $hour = $4;
387 0           my $min = $5;
388 0           my $sec = 0;
389 0           my $year = $1;
390 0           my $msec = 0;
391 0           $timestamp = Time::Local::timelocal($sec, $min, $hour, $mday, $mon, $year);
392 0 0         if ($self->use_hires) {
393 0           $timestamp .= sprintf(".%03d", $msec);
394             }
395             }
396             # 2017-10-11 07:40:55.612514
397             elsif ($string =~ m{^(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2}):(\d{2})\.(\d{6})$}) {
398 0           my $mon = $2 - 1;
399 0           my $mday = $3;
400 0           my $hour = $4;
401 0           my $min = $5;
402 0           my $sec = $6;
403 0           my $year = $1;
404 0           my $msec = $7;
405 0           $timestamp = Time::Local::timelocal($sec, $min, $hour, $mday, $mon, $year);
406 0 0         if ($self->use_hires) {
407 0           $timestamp .= sprintf(".%03d", $msec);
408             }
409             }
410             # 2019-01-07 17:02
411             elsif ($string =~ m{^(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2})$}) {
412 0           my $mon = $2 - 1;
413 0           my $mday = $3;
414 0           my $hour = $4;
415 0           my $min = $5;
416 0           my $year = $1;
417 0           $timestamp = Time::Local::timelocal(0, $min, $hour, $mday, $mon, $year);
418             }
419             # 2019-01-07 11:40:24
420             elsif ($string =~ m{^(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2}):(\d{2})$}) {
421 0           my $mon = $2 - 1;
422 0           my $mday = $3;
423 0           my $hour = $4;
424 0           my $min = $5;
425 0           my $sec = $6;
426 0           my $year = $1;
427 0           $timestamp = Time::Local::timelocal($sec, $min, $hour, $mday, $mon, $year);
428             }
429             # 11/04/19 11:40:00
430             elsif ($string =~ m{^(\d{2})/(\d{2})/(\d{2}) (\d{2}):(\d{2}):(\d{2})$}) {
431 0           my $mon = $1 - 1;
432 0           my $mday = $2;
433 0           my $hour = $4;
434 0           my $min = $5;
435 0           my $sec = $6;
436 0           my $year = $3 + 2000; # Y2100 bug.
437 0           $timestamp = Time::Local::timelocal($sec, $min, $hour, $mday, $mon, $year);
438             }
439             # 2000-10-20T00:00:00.000-04:00
440             elsif ($string =~ m{^(\d{4})\-(\d{2})\-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})}) {
441 0           my $mon = $2 - 1;
442 0           my $mday = $3;
443 0           my $hour = $4;
444 0           my $min = $5;
445 0           my $sec = $6;
446 0           my $year = $1;
447 0           my $msec = $7;
448 0           $timestamp = Time::Local::timelocal($sec, $min, $hour, $mday, $mon, $year);
449 0 0         if ($self->use_hires) {
450 0           $timestamp .= sprintf(".%03d", $msec);
451             }
452             }
453             else {
454 0           return $self->log->error("to_timestamp: string [$string] not a valid date format");
455             }
456              
457 0           return $timestamp;
458             }
459              
460             1;
461              
462             __END__