line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#=============================== ISODate.pm ================================== |
2
|
|
|
|
|
|
|
# Filename: ISODate.pm |
3
|
|
|
|
|
|
|
# Description: ISO date handling. |
4
|
|
|
|
|
|
|
# Original Author: Dale M. Amon |
5
|
|
|
|
|
|
|
# Revised by: $Author: amon $ |
6
|
|
|
|
|
|
|
# Date: $Date: 2008-08-28 23:14:03 $ |
7
|
|
|
|
|
|
|
# Version: $Revision: 1.8 $ |
8
|
|
|
|
|
|
|
# License: LGPL 2.1, Perl Artistic or BSD |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
#============================================================================= |
11
|
1
|
|
|
1
|
|
1147
|
use strict; |
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
53
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package DMA::ISODate; |
14
|
1
|
|
|
1
|
|
5
|
use vars qw{@ISA}; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
63
|
|
15
|
|
|
|
|
|
|
@ISA = qw( UNIVERSAL ); |
16
|
|
|
|
|
|
|
|
17
|
1
|
|
|
1
|
|
1112
|
use POSIX; |
|
1
|
|
|
|
|
11873
|
|
|
1
|
|
|
|
|
7
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
#============================================================================= |
20
|
|
|
|
|
|
|
# Class Methods |
21
|
|
|
|
|
|
|
#============================================================================= |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sub new { |
24
|
0
|
|
|
0
|
1
|
|
my ($class, $datestring) = @_; |
25
|
0
|
|
|
|
|
|
return ($class->_new (0,$datestring)); |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub unix { |
31
|
0
|
|
|
0
|
1
|
|
my ($class, $time,$utcflg) = @_; |
32
|
0
|
|
|
|
|
|
my $self = bless {}, $class; |
33
|
|
|
|
|
|
|
|
34
|
0
|
0
|
|
|
|
|
defined $time || (return undef); |
35
|
0
|
0
|
|
|
|
|
defined $utcflg || ($utcflg = 0); |
36
|
|
|
|
|
|
|
|
37
|
0
|
|
|
|
|
|
my($havedate,$havetime,$y2k) = (1,1,0); |
38
|
0
|
0
|
|
|
|
|
my ($sec,$min,$hr,$day,$mon,$yr) = |
39
|
|
|
|
|
|
|
($utcflg) ? gmtime($time) : localtime ($time); |
40
|
0
|
|
|
|
|
|
$yr+=1900; $mon+=1; |
|
0
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
42
|
0
|
|
|
|
|
|
@$self{'y2k','havetime','isUTC', |
43
|
|
|
|
|
|
|
'yr','mon','day','hr','min','sec'} = |
44
|
|
|
|
|
|
|
($y2k,$havetime,$utcflg, |
45
|
|
|
|
|
|
|
$yr,$mon,$day,$hr,$min,$sec); |
46
|
|
|
|
|
|
|
|
47
|
0
|
|
|
|
|
|
$self->_set_iso_strings; |
48
|
0
|
|
|
|
|
|
return $self; |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
52
|
|
|
|
|
|
|
|
53
|
0
|
|
|
0
|
1
|
|
sub now {return (shift->_new (0,undef));} |
54
|
0
|
|
|
0
|
1
|
|
sub utc {return (shift->_new (1,undef));} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub new_formatted { |
59
|
0
|
|
|
0
|
1
|
|
my ($class,$fmt,$string) = @_; |
60
|
0
|
|
|
|
|
|
my $self = bless {}, $class; |
61
|
|
|
|
|
|
|
|
62
|
0
|
|
|
|
|
|
return $self; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
#============================================================================= |
66
|
|
|
|
|
|
|
# Object Methods |
67
|
|
|
|
|
|
|
#============================================================================= |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub get { |
70
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
71
|
0
|
0
|
|
|
|
|
return $self->{'date'} . (($self->{'havetime'}) ? $self->{'time'} : "");} |
72
|
|
|
|
|
|
|
|
73
|
0
|
|
|
0
|
1
|
|
sub canonical {my ($self) = @_; return $self->{'date'} . $self->{'time'};} |
|
0
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub yearly { |
78
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
79
|
0
|
|
|
|
|
|
@$self{'mon','day','hr','min','sec','havetime'} = (0,0,0,0,0,0); |
80
|
0
|
|
|
|
|
|
$self->_set_iso_strings; |
81
|
0
|
|
|
|
|
|
return $self; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub monthly { |
85
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
86
|
0
|
|
|
|
|
|
@$self{'day','hr','min','sec','havetime'} = (0,0,0,0,0); |
87
|
0
|
|
|
|
|
|
$self->_set_iso_strings; |
88
|
0
|
|
|
|
|
|
return $self; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub isyearly { |
94
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
95
|
0
|
0
|
|
|
|
|
return (($self->{'mon'} + $self->{'day'} + $self->{'havetime'}) ? 0 : 1); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub ismonthly { |
99
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
100
|
0
|
0
|
|
|
|
|
return (($self->{'day'} + $self->{'havetime'}) ? 0 : 1); |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
my @Q = ("Q1-Q4", |
106
|
|
|
|
|
|
|
"Q1", "Q1", "Q1", |
107
|
|
|
|
|
|
|
"Q2", "Q2", "Q2", |
108
|
|
|
|
|
|
|
"Q3", "Q3", "Q3", |
109
|
|
|
|
|
|
|
"Q4", "Q4", "Q4"); |
110
|
|
|
|
|
|
|
|
111
|
0
|
|
|
0
|
1
|
|
sub quarter {return $Q[shift->{'month'}];} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
114
|
|
|
|
|
|
|
|
115
|
0
|
|
|
0
|
1
|
|
sub date {return shift->{'date'};} |
116
|
0
|
|
|
0
|
1
|
|
sub time {return shift->{'time'};} |
117
|
0
|
|
|
0
|
1
|
|
sub y2k {return shift->{'y2k'};} |
118
|
0
|
|
|
0
|
1
|
|
sub havetime {return shift->{'havetime'};} |
119
|
0
|
|
|
0
|
1
|
|
sub isUTC {return shift->{'isUTC'};} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub timearray { |
124
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
125
|
0
|
|
|
|
|
|
return (@$self{'yr','mon','day','hr','min','sec', |
126
|
|
|
|
|
|
|
'havetime','isUTC','y2k'}); |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
#============================================================================= |
130
|
|
|
|
|
|
|
# Internal Methods |
131
|
|
|
|
|
|
|
#============================================================================= |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub _new { |
134
|
0
|
|
|
0
|
|
|
my ($class, $utcflg,$str) = @_; |
135
|
0
|
|
|
|
|
|
my $self = bless {}, $class; |
136
|
|
|
|
|
|
|
|
137
|
0
|
|
|
|
|
|
my ($havedate,$havetime,$y2k, |
138
|
|
|
|
|
|
|
$yr,$mon,$day,$hr,$min,$sec) = |
139
|
|
|
|
|
|
|
(0,0,0, |
140
|
|
|
|
|
|
|
0,0,0,0,0,0); |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# Times come back in 2-3 digit format which we treat as a y2k correction. |
143
|
0
|
0
|
|
|
|
|
if (!defined $str) { |
144
|
0
|
|
|
|
|
|
($havedate,$havetime,$y2k) = (1,1,0); |
145
|
0
|
0
|
|
|
|
|
($sec,$min,$hr,$day,$mon,$yr) = |
146
|
|
|
|
|
|
|
($utcflg) ? gmtime(CORE::time) : localtime (CORE::time); |
147
|
0
|
|
|
|
|
|
$yr+=1900; $mon+=1; |
|
0
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
else { |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# Try ISO date format first. |
152
|
|
|
|
|
|
|
# ***** THESE VALUES ARE NOT CHECKED FOR LIMITS OR THAT THE DAY OF THE |
153
|
|
|
|
|
|
|
# MONTH EXISTS IN THAT MONTH AND YEAR. |
154
|
0
|
|
|
|
|
|
($havedate,$havetime,$y2k, |
155
|
|
|
|
|
|
|
$yr,$mon,$day,$hr,$min,$sec) = $self->_isodate($str); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# ***** Later on fill this in so it handles other formats. |
158
|
0
|
0
|
|
|
|
|
if (!$havedate) {return undef;} |
|
0
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
0
|
0
|
|
|
|
|
$havedate || return undef; |
162
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
|
@$self{'y2k','havetime','isUTC', |
164
|
|
|
|
|
|
|
'yr','mon','day','hr','min','sec'} = |
165
|
|
|
|
|
|
|
($y2k,$havetime,$utcflg, |
166
|
|
|
|
|
|
|
$yr,$mon,$day,$hr,$min,$sec); |
167
|
|
|
|
|
|
|
|
168
|
0
|
|
|
|
|
|
$self->_set_iso_strings; |
169
|
0
|
|
|
|
|
|
return $self; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
173
|
|
|
|
|
|
|
# See if we can make an ISODATE out of the string with no chars left over. |
174
|
|
|
|
|
|
|
# An ISODATE must be at least 6 digits long; it may be for 1 Million AD, |
175
|
|
|
|
|
|
|
# so we allow lots of digits. Of course you can't stuff that in a Unix |
176
|
|
|
|
|
|
|
# timval, but we don't need to anyway. |
177
|
|
|
|
|
|
|
# |
178
|
|
|
|
|
|
|
# The return values are in a canonical form: |
179
|
|
|
|
|
|
|
# havedate => true if we found the date |
180
|
|
|
|
|
|
|
# havetime => true if we found the time |
181
|
|
|
|
|
|
|
# y2k => true if we had a 2 digit year on input. |
182
|
|
|
|
|
|
|
# |
183
|
|
|
|
|
|
|
# We could get fancier if we had to. It would not be hard to deal with |
184
|
|
|
|
|
|
|
# ISO time and date seperated by delimiters; we could also check potential |
185
|
|
|
|
|
|
|
# MM,DD,YY,HH, MM, SS for validity if we needed to. We will let the caller |
186
|
|
|
|
|
|
|
# use a standard Perl Module of some sort for that job rather than redoing |
187
|
|
|
|
|
|
|
# it. We just assume that if it looks ISODATE and is not, it was wrong |
188
|
|
|
|
|
|
|
# and could not have been parsed in an alternative format. Until someone |
189
|
|
|
|
|
|
|
# points out an exception, that's my story and I'm sticking to it. |
190
|
|
|
|
|
|
|
# |
191
|
|
|
|
|
|
|
# I am leaving extra conditionals here as hooks for in case I was wrong. |
192
|
|
|
|
|
|
|
# Otherwise I could simplify the routine by a number of lines. Likewise, |
193
|
|
|
|
|
|
|
# |
194
|
|
|
|
|
|
|
# ASSUME: I assume two or three digit years should always be replaced |
195
|
|
|
|
|
|
|
# by yr+1900. Two digit is assumed to be a Y2K problem; 3 digit |
196
|
|
|
|
|
|
|
# is assumed to be a Unix timval that really is yr-1900. Perhaps |
197
|
|
|
|
|
|
|
# we'll need a U2K for 2038... |
198
|
|
|
|
|
|
|
# |
199
|
|
|
|
|
|
|
# ASSUME: There is no such thing as an ISODATE that only has the time |
200
|
|
|
|
|
|
|
# portion HHMMSS. |
201
|
|
|
|
|
|
|
# |
202
|
|
|
|
|
|
|
# Args: self |
203
|
|
|
|
|
|
|
# string |
204
|
|
|
|
|
|
|
# Returns: (havedate, havetime, y2k, |
205
|
|
|
|
|
|
|
# year, month, day, hour, minute, second, |
206
|
|
|
|
|
|
|
# remaining_chars) |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub _isodate { |
209
|
0
|
|
|
0
|
|
|
my ($self, $str) = @_; |
210
|
0
|
|
|
|
|
|
my $r = $str; |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# See if we've got a possible ISO date, at least 6 chars. |
213
|
0
|
0
|
|
|
|
|
if ($str =~ /^(\d{6,})$/) { |
214
|
0
|
|
|
|
|
|
my ($a1,$a2,$a3,$b1,$b2,$b3,$b4,$b5,$b6); |
215
|
0
|
|
|
|
|
|
my ($iso, $len) = ($1, length $1); |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
# The 3 item (minimum 6 digits) parse |
218
|
0
|
0
|
|
|
|
|
if ($iso =~ /^(\d{2,})(\d\d)(\d\d)(.*)/) {($a1,$a2,$a3,$r) = ($1,$2,$3,$4);} |
|
0
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# The 6 item (minimum 12 digits) parse |
221
|
0
|
0
|
0
|
|
|
|
if (($len > 6) && |
222
|
|
|
|
|
|
|
($iso =~ /^(\d{2,})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(.*)$/)) { |
223
|
0
|
|
|
|
|
|
($b1,$b2,$b3,$b4,$b5,$b6,$r) = ($1,$2,$3,$4,$5,$6,$7);} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# 3 item: YYMMDD; (or HHMMSS if we allowed that). This is a Y2K. |
226
|
0
|
0
|
|
|
|
|
if ($len == 6) {return (1,0,1, $a1+1900,$a2,$a3, 0,0,0, $r);} |
|
0
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# 3 item: YYYMMDD, probably a Unix year after 1900. Not a y2k. |
229
|
0
|
0
|
|
|
|
|
if ($len == 7) {return (1,0,0, $a1+1900,$a2,$a3, 0,0,0, $r);} |
|
0
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# 3 item: YYYYMMDD to YYYYYYYYMMDD, the later being rather unlikely |
232
|
0
|
0
|
0
|
|
|
|
if (($len >= 8) && ($len < 12)) {return (1,0,0, $a1,$a2,$a3, 0,0,0, $r);} |
|
0
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# 6 item: YYMMDDHHMMSS, a y2k date or 3 item: YYYYYYYYMMDD, the later |
235
|
|
|
|
|
|
|
# being rather unlikely but an annoying loss. |
236
|
0
|
0
|
|
|
|
|
if ($len == 12) {return (1,1,1, $b1+1900,$b2,$b3, $b4,$b5,$b6, $r);} |
|
0
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
# YYYMMDDHHMMSS or YYYYYYYYYYMMDD, the first being a format error |
239
|
|
|
|
|
|
|
# with a Unix year after 1900 but more likely than the later. |
240
|
0
|
0
|
|
|
|
|
if ($len == 13) {return (1,1,0, $b1+1900,$b2,$b3, $b4,$b5,$b6, $r);} |
|
0
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# YYYYMMDDHHMMSS to {Y...}YYYYMMDDHHMMSS to infinity and beyond... |
243
|
0
|
|
|
|
|
|
return (1,1,0, $b1,$b2,$b3, $b4,$b5,$b6, $r); |
244
|
|
|
|
|
|
|
} |
245
|
0
|
|
|
|
|
|
return (0,0,0, 0,0,0, 0,0,0, $r); |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
249
|
|
|
|
|
|
|
# Update the date and time strings from the yr,mon,day,hr,min,sec fields. |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub _set_iso_strings { |
252
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
253
|
0
|
|
|
|
|
|
@$self{'date','time','havetime'} = |
254
|
|
|
|
|
|
|
(sprintf ("%04d%02d%02d", @$self{'yr','mon','day'}), |
255
|
|
|
|
|
|
|
sprintf ("%02d%02d%02d", @$self{'hr','min','sec'}), |
256
|
|
|
|
|
|
|
$self->{'havetime'}); |
257
|
0
|
|
|
|
|
|
return $self; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
#============================================================================= |
261
|
|
|
|
|
|
|
# Pod Documentation |
262
|
|
|
|
|
|
|
#============================================================================= |
263
|
|
|
|
|
|
|
# You may extract and format the documentation section with the 'perldoc' cmd. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=head1 NAME |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
DMA::ISODate.pm - ISO date handling. |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=head1 SYNOPSIS |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
use DMA::ISODate; |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
$obj = DMA::ISOdate->new ($datestring); |
274
|
|
|
|
|
|
|
$obj = DMA::ISOdate->now; |
275
|
|
|
|
|
|
|
$obj = DMA::ISOdate->utc; |
276
|
|
|
|
|
|
|
$obj = DMA::ISOdate->unix ($time, $gmflag); |
277
|
|
|
|
|
|
|
$obj = DMA::ISOdate->new_formatted ($fmt, $string); |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
$datestring = $obj->get; |
280
|
|
|
|
|
|
|
$datestring = $obj->canonical; |
281
|
|
|
|
|
|
|
$obj = $obj->yearly; |
282
|
|
|
|
|
|
|
$obj = $obj->monthly; |
283
|
|
|
|
|
|
|
$obj = $obj->isyearly; |
284
|
|
|
|
|
|
|
$obj = $obj->ismonthly; |
285
|
|
|
|
|
|
|
$quarter = $obj->quarter; |
286
|
|
|
|
|
|
|
$season = $obj->season; |
287
|
|
|
|
|
|
|
$datestring = $obj->date; |
288
|
|
|
|
|
|
|
$timestring = $obj->time; |
289
|
|
|
|
|
|
|
$havetime = $obj->havetime; |
290
|
|
|
|
|
|
|
$y2k = $obj->y2k; |
291
|
|
|
|
|
|
|
$utc = $obj->isUTC; |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
($yr,$mon,$day,$hr,$min,$sec,$havetime,$utc,$y2k) = $obj->timearray; |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=head1 Inheritance |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
UNIVERSAL |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head1 Description |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
The primary date time we use is the ISO date, almost always in the basic |
302
|
|
|
|
|
|
|
form of YYYYMMDD , like 20021209, but the DMA::ISOdate class will attempt to |
303
|
|
|
|
|
|
|
create an ISODate from what ever you give it: |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
Input data Canonical ISO result |
306
|
|
|
|
|
|
|
YYMMDD => 19YYMMDD000000 |
307
|
|
|
|
|
|
|
YYYMMDD => (1900+YYY)MMDD000000 |
308
|
|
|
|
|
|
|
YYYYMMDD => YYYYMMDD000000 |
309
|
|
|
|
|
|
|
YYYYYMMDD => YYYYYMMDD000000 |
310
|
|
|
|
|
|
|
YYYYYYMMDD => YYYYYYMMDD000000 |
311
|
|
|
|
|
|
|
YYYYYYYMMDD => YYYYYYYMMDD000000 |
312
|
|
|
|
|
|
|
YYMMDDHHMMSS => 19YYMMDDHHMMSS |
313
|
|
|
|
|
|
|
YYYMMDDHHMMSS => (1900+YY)MMDDHHMMSS |
314
|
|
|
|
|
|
|
YYYYMMDDHHMMSS => YYYYMMDDHHMMSS |
315
|
|
|
|
|
|
|
{Y..}YYYYMMDDHHMMSS => {Y..}YYYYMMDDHHMMSS |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Note that a minimum of 4 digits is needed to correctly express years like |
318
|
|
|
|
|
|
|
40AD so as to differentiate it from 1940AD which is what the Y2K correction |
319
|
|
|
|
|
|
|
would do with "401209". There are also problems: years cannot be expressed |
320
|
|
|
|
|
|
|
beyond 9999999 in the date only format. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Two digit years (00-99) are assume to be Y2K legacy dates. We set the y2k |
323
|
|
|
|
|
|
|
flag and add 1900 to the year value when we see one. |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
Three digit years (000-999) are likely to be uncorrected Unix date returns. |
326
|
|
|
|
|
|
|
We do not set the y2k but we do add 1900. This is safe until we hit what |
327
|
|
|
|
|
|
|
I'll call the "U2K" date of 2038 when Unix 32b int timevals roll over. This |
328
|
|
|
|
|
|
|
is not a problem for this Class; we follow the philosophy of "be liberal on |
329
|
|
|
|
|
|
|
inputs and conservative on outputs". |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
If this all seems very ad hoc -- it is. Date formats are very ad hoc with |
332
|
|
|
|
|
|
|
ambiguities which can only be decided with contextual information. That's a |
333
|
|
|
|
|
|
|
job for people, not a poor wee ISODate Class. |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
Four digit year formats are not limited to 4 digits. We can express dates far |
336
|
|
|
|
|
|
|
into the future. In any place hereafter where we use "YYYY", any number of |
337
|
|
|
|
|
|
|
extra digits are possible. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
[We aren't affected by the size of Unix timval (ie the 2038 max year) except |
340
|
|
|
|
|
|
|
it is not convenient right now to do a perpetual calendar of my own to check |
341
|
|
|
|
|
|
|
the validity of a date.] |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
We do not, however, have any means of representing dates BC. For this we might |
344
|
|
|
|
|
|
|
consider using the Peter Kokh dating system which adds 10000 to the AD date to |
345
|
|
|
|
|
|
|
represent all of human history after the end of the most recent Ice Age. This |
346
|
|
|
|
|
|
|
allows much easier translation between all modern and ancient dating systems |
347
|
|
|
|
|
|
|
if you remember there was no year zero as they had not gotten around to |
348
|
|
|
|
|
|
|
inventing nothing back then. (Given some recent discoveries offshore in India, |
349
|
|
|
|
|
|
|
I might prefer adding 20000 years!) |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head1 Examples |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
None. |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
=head1 Class Variables |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
None. |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
=head1 Instance Variables |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
y2k Set if external input was in two digit year format, t/f. |
362
|
|
|
|
|
|
|
havetime Set if input included the time, t/f |
363
|
|
|
|
|
|
|
isUTC date/time is known to be UTC, t/f. |
364
|
|
|
|
|
|
|
(What should the default be since we will |
365
|
|
|
|
|
|
|
only know this if we got the time via newgm.) |
366
|
|
|
|
|
|
|
date "YYYYMMDD" |
367
|
|
|
|
|
|
|
time "HHMMSS", default is "000000" |
368
|
|
|
|
|
|
|
yr integer year, 0 -size of int |
369
|
|
|
|
|
|
|
mon integer month, 1-12,; 0=no month |
370
|
|
|
|
|
|
|
day integer day, 1-28,29,30 or 31; 0=no day |
371
|
|
|
|
|
|
|
hr integer hour, 0-23 |
372
|
|
|
|
|
|
|
min integer minute, 0-59 |
373
|
|
|
|
|
|
|
sec integer second, 0-59 |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=head1 Class Methods |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=over 4 |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=item B<$obj = DMA::ISOdate-Enew ($datestring)> |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
Assume the $datestring is a local ISO date or date/time in one of the formats |
382
|
|
|
|
|
|
|
discussed earlier. Returns undef if $datestring can't be parsed our way; 1900 |
383
|
|
|
|
|
|
|
is added to the year if 2 or 3 digits are found and the y2k flag set for 2 |
384
|
|
|
|
|
|
|
digit years. havetime is set if there was an HHMMSS in the string. |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
Returns a new object or undef on failure. |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=item B<$obj = DMA::ISOdate-Enew_formatted ($fmt, $string)> |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
Use a Perl date format string to identify the date format we believe $string |
391
|
|
|
|
|
|
|
to be in. It returns undef instead of creating a new object if the date |
392
|
|
|
|
|
|
|
doesn't work in the given format. |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=item B<$obj = DMA::ISOdate-Enow> |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
Create an object with the current time set to right now in local time. Always |
397
|
|
|
|
|
|
|
succeeds, always Y2K compliant and has HHMMSS available. |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=item B<$obj = DMA::ISOdate-Eunix ($time, $gmflag)> |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
Create an object for a unix timeval. $time is required and assumed to be a |
402
|
|
|
|
|
|
|
unix time integer. If $gmflag is present and set, make it a UTC time, |
403
|
|
|
|
|
|
|
otherwise it is local time. Always succeeds, always Y2K compliant and has |
404
|
|
|
|
|
|
|
HHMMSS available. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
This routine is useful when dealing with info from archive file directory |
407
|
|
|
|
|
|
|
stats. |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=item B<$obj = DMA::ISOdate-Eutc> |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
Create an object with the current time set to right now in UTC time. Always |
412
|
|
|
|
|
|
|
succeeds, always Y2K compliant and has HHMMSS available. |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
=back 4 |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=head1 Instance Methods |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=over 4 |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=item B<$datestring = $obj-Ecanonical> |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
Returns an the object's ISODATE. In a canonical form: YYYYMMDD HHMMSS . If |
423
|
|
|
|
|
|
|
havetime is not set, we get YYYYMMDD000000. |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
=item B<$datestring = $obj-Edate> |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Returns the ISO date as YYYYMMDD . |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
=item B<$datestring = $obj-Eget> |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
Returns an the object's ISODATE. In one of two forms, either YYYYMMDD if |
432
|
|
|
|
|
|
|
havetime is not set or YYYYMMDDHHMMSS if it is. |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
=item B<$havetime = $obj-Ehavetime> |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
True if we have a time of day stored. |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=item B<$obj = $obj-Eismonthly> |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
Test if the ISO date is suitable for things like monthly magazines. Returns |
441
|
|
|
|
|
|
|
true if havetime and day of month are clear. It means your ISO date is of the |
442
|
|
|
|
|
|
|
form "19950500". |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
=item B<$utc = $obj-EisUTC> |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
True if the time we stored was UTC. |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
=item B<$obj = $obj-Eisyearly> |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
Test if the ISO date is suitable for things like yearly reports. Returns true |
451
|
|
|
|
|
|
|
if havetime, month and day of month are clear. It means your ISO date is of |
452
|
|
|
|
|
|
|
the form "19950000". |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=item B<$obj = $obj-Emonthly> |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
Change the ISO date so it is of use for things like monthly magazines. |
457
|
|
|
|
|
|
|
havetime is cleared. All time and date field below month are zeroed. Your |
458
|
|
|
|
|
|
|
ISO date will now look like "19950500". |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=item B<$quarter = $obj-Equarter> |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
Returns the quarter string for the date. Q1,Q2,Q3,Q4 or Q1-Q4 if the date has |
463
|
|
|
|
|
|
|
no month, eg "19950000". |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=item B<$season = $obj-Eseason> |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
Returns the season: winter, spring,summer,fall. |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
=item B<$timestring = $obj-Etime> |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
Returns the time as HHMMSS if havetime is set; otherwise the midnight time |
472
|
|
|
|
|
|
|
string "000000". |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=item B<($yr,$mon,$day,$hr,$min,$sec,$havetime,$utc,$y2k) = $obj-Etimearray> |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
Return the date/time information. |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
=item B<$y2k = $obj-Ey2k> |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
True if we applied a Y2K correction to the year in our stored date. |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
=item B<$obj = $obj-Eyearly> |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
Change the ISO date so it is of use for things like yearly reports. havetime |
485
|
|
|
|
|
|
|
is cleared. All time and date field below year are zeroed. Your ISO date |
486
|
|
|
|
|
|
|
will now look like "19950000". |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=back 4 |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=head1 Private Class Methods |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=over 4 |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=item B<$obj = DMA::ISOdate-E_new ($type,$gmflag,$datestring)> |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
Internal base initializer method which all the other initializer methods |
497
|
|
|
|
|
|
|
call. |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
Not part of the advertised interface for this class, so don't try to use it |
500
|
|
|
|
|
|
|
directly. |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
Returns self or undef if no date found/created. |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=back 4 |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=head1 Private Instance Methods |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
None, although I may wish to include the code comments from _isodate here as |
509
|
|
|
|
|
|
|
it is quite extensive. |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=head1 KNOWN BUGS |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
See TODO. |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=head1 SEE ALSO |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
None. |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
=head1 AUTHOR |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
Dale Amon |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=cut |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
#============================================================================= |
526
|
|
|
|
|
|
|
# CVS HISTORY |
527
|
|
|
|
|
|
|
#============================================================================= |
528
|
|
|
|
|
|
|
# $Log: ISODate.pm,v $ |
529
|
|
|
|
|
|
|
# Revision 1.8 2008-08-28 23:14:03 amon |
530
|
|
|
|
|
|
|
# perldoc section regularization. |
531
|
|
|
|
|
|
|
# |
532
|
|
|
|
|
|
|
# Revision 1.7 2008-08-15 21:47:52 amon |
533
|
|
|
|
|
|
|
# Misc documentation and format changes. |
534
|
|
|
|
|
|
|
# |
535
|
|
|
|
|
|
|
# Revision 1.6 2008-04-18 14:07:54 amon |
536
|
|
|
|
|
|
|
# Minor documentation format changes |
537
|
|
|
|
|
|
|
# |
538
|
|
|
|
|
|
|
# Revision 1.5 2008-04-11 22:25:23 amon |
539
|
|
|
|
|
|
|
# Add blank line after cut. |
540
|
|
|
|
|
|
|
# |
541
|
|
|
|
|
|
|
# Revision 1.4 2008-04-11 18:56:35 amon |
542
|
|
|
|
|
|
|
# Fixed quoting problem with formfeeds. |
543
|
|
|
|
|
|
|
# |
544
|
|
|
|
|
|
|
# Revision 1.3 2008-04-11 18:39:15 amon |
545
|
|
|
|
|
|
|
# Implimented new standard for headers and trailers. |
546
|
|
|
|
|
|
|
# |
547
|
|
|
|
|
|
|
# Revision 1.2 2008-04-10 15:01:08 amon |
548
|
|
|
|
|
|
|
# Added license to headers, removed claim that the documentation section still |
549
|
|
|
|
|
|
|
# relates to the old doc file. |
550
|
|
|
|
|
|
|
# |
551
|
|
|
|
|
|
|
# Revision 1.1.1.1 2004-09-19 21:59:12 amon |
552
|
|
|
|
|
|
|
# Dale's library of primitives in Perl |
553
|
|
|
|
|
|
|
# |
554
|
|
|
|
|
|
|
# 20040813 Dale Amon |
555
|
|
|
|
|
|
|
# Moved to DMA:: from Archivist:: |
556
|
|
|
|
|
|
|
# to make it easier to enforce layers. |
557
|
|
|
|
|
|
|
# |
558
|
|
|
|
|
|
|
# 20021207 Dale Amon |
559
|
|
|
|
|
|
|
# Created. |
560
|
|
|
|
|
|
|
1; |