This repository has been archived by the owner on May 23, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathDateTime.pm
120 lines (98 loc) · 3.55 KB
/
DateTime.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package CIF::Plugin::DateTime;
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
# This allows declaration use CIF ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = ( 'all' => [ qw(
is_datetime normalize_timestamp
) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw(
);
use DateTime::Format::DateParse;
use Try::Tiny;
use constant RE_DATETIME_STR => qr/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
use constant RE_DATETIME_INT => qr/^\d{6,}/;
sub is_datetime {
my $arg = shift || return;
return 'dt_string' if(is_datetime_string($arg));
return 'dt_int' if(is_datetime_int($arg));
return 0;
}
sub is_datetime_string {
my $arg = shift || return;
return 1 if($arg =~ RE_DATETIME_STR());
}
sub is_datetime_int {
my $arg = shift || return;
return 1 if($arg =~ RE_DATETIME_INT());
}
## TODO: this needs significant re-factoring
sub normalize_timestamp {
my $dt = shift;
my $now = shift || DateTime->from_epoch(epoch => time()); # better perf in loops if we can pass the default now value
my $asString = shift;
my $err;
return DateTime::Format::DateParse->parse_datetime($dt) if(!$asString && $dt =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/);
# already epoch
if($dt =~ /^\d{10}+$/){
return DateTime->from_epoch(epoch => $dt) unless($asString);
$dt = DateTime->from_epoch(epoch => $dt);
return $dt->ymd().'T'.$dt->hms().'Z';
}
# high-res
if($dt =~ /^\d+\.\d+$/){
my @a = split(/\./,$dt);
$dt = DateTime->from_epoch(epoch => $a[0]);
return $dt->ymd().'T'.$dt->hms().'Z' if($asString);
}
return DateTime->today() if(lc($dt) =~ /^today$/);
# something else
if($dt && ref($dt) ne 'DateTime'){
if($dt =~ /^(yesterday)$/){
$dt = DateTime->today()->subtract(days => 1);
} elsif($dt =~ /^(\d+) days? ago/){
$dt = DateTime->today()->subtract(days => $1);
} elsif($dt =~ /^\d+$/){
if($dt =~ /^\d{8}$/){
$dt.= 'T00:00:00Z';
$dt = eval { DateTime::Format::DateParse->parse_datetime($dt) };
unless($dt){
$dt = $now;
}
} else {
$dt = $now;
}
} elsif($dt =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\S+)?$/) {
my ($year,$month,$day,$hour,$min,$sec,$tz) = ($1,$2,$3,$4,$5,$6,$7);
$dt = DateTime::Format::DateParse->parse_datetime($year.'-'.$month.'-'.$day.' '.$hour.':'.$min.':'.$sec,$tz);
} else {
$dt =~ s/_/ /g;
try {
$dt = DateTime::Format::DateParse->parse_datetime($dt);
} catch {
$err = shift;
if($err =~ /^The 'day'/){
my @bits = split(/\//,$dt);
unless($#bits){
@bits = split(/\-/, $dt);
}
$dt = join('/',($bits[1],$bits[0],$bits[2]));
$dt = DateTime::Format::DateParse->parse_datetime($dt);
} else {
die $err;
}
};
return unless($dt);
}
}
return $dt->ymd().'T'.$dt->hms().'Z' if($asString);
return $dt;
}
1;