File Coverage

blib/lib/Time/Format.pm
Criterion Covered Total %
statement 78 83 93.9
branch 28 40 70.0
condition 4 6 66.6
subroutine 13 13 100.0
pod 2 2 100.0
total 125 144 86.8


line stmt bran cond sub pod time code
1             =for gpg
2             -----BEGIN PGP SIGNED MESSAGE-----
3             Hash: SHA1
4              
5             =encoding utf8
6              
7             =head1 NAME
8              
9             Time::Format - Easy-to-use date/time formatting.
10              
11             =head1 VERSION
12              
13             This is version 1.15 of Time::Format, July 26, 2019.
14              
15             =cut
16              
17 25     25   4640727 use strict;
  25         209  
  25         14831  
18             package Time::Format;
19             $Time::Format::VERSION = '1.15';
20              
21             # This module claims to be compatible with the following versions
22             # of Time::Format_XS.
23             %Time::Format::XSCOMPAT = map {$_ => 1} qw(1.01 1.02 1.03);
24              
25             sub _croak
26             {
27 2     2   11 require Carp;
28 2         270 goto &Carp::croak;
29             }
30              
31             # Store the file offset of the __DATA__ region.
32             my $data_pos = tell DATA;
33             close DATA; # so we don't hold a lock on this file.
34              
35             # Here we go through a bunch of tests to decide whether we can use the
36             # XS module, or if we need to load and compile the perl-only
37             # subroutines (which are stored in __DATA__).
38             my $load_perlonly = 0;
39             $load_perlonly = 1 if defined $Time::Format::NOXS && $Time::Format::NOXS;
40              
41             if (!$load_perlonly)
42             {
43             # Check whether the optional XS module is installed.
44             eval { require Time::Format_XS };
45              
46             if ($@ || !defined $Time::Format_XS::VERSION)
47             {
48             $load_perlonly = 1;
49             }
50             else
51             {
52             # Check that we're compatible with them (backwards compatibility)
53             # or they're compatible with us (forwards compatibility).
54             unless ($Time::Format::XSCOMPAT{$Time::Format_XS::VERSION}
55             || $Time::Format_XS::PLCOMPAT{$Time::Format::VERSION})
56             {
57             warn "Your Time::Format_XS version ($Time::Format_XS::VERSION) "
58             . "is not compatible with Time::Format version ($Time::Format::VERSION).\n"
59             . "Using Perl-only functions.\n";
60             $load_perlonly = 1;
61             }
62             }
63              
64             # Okay to use the XS version? Great. Wrap it.
65             if (!$load_perlonly)
66             {
67             *time_format = \&Time::Format_XS::time_format;
68             }
69             }
70              
71             if ($load_perlonly)
72             {
73             # Time::Format_XS not installed, or version mismatch, or NOXS was set.
74             # The perl routines will need to be loaded.
75             # But let's defer this until someone actually calls time_format().
76             *time_format = sub
77             {
78 256 100   256   583365 if (not defined &time_format_perlonly)
79             {
80 11 50       461 open DATA, '<', __FILE__
81             or die "Can't access code in " . __FILE__ . ": $!\n";;
82              
83 11         129 flock DATA, 1; # LOCK_SH
84 11         102 seek DATA, $data_pos, 0;
85 11         85 local $^W = 0; # disable warning about subroutines redefined
86 11         58 local $/ = undef; # slurp
87 11         941 my $code = <DATA>;
88 11         107 flock DATA, 8; # LOCK_UN
89 11         107 close DATA;
90              
91 11         3136 eval $code;
92 11 50       47989 die if $@;
93             }
94 256         787 goto &time_format_perlonly;
95             };
96             undef $Time::Format_XS::VERSION; # Indicate that XS version is not available.
97             }
98              
99              
100             my @EXPORT = qw(%time time_format);
101             my @EXPORT_OK = qw(%time %strftime %manip time_format time_strftime time_manip);
102              
103             # We don't need any of Exporter's fancy features, so it's quicker to
104             # do the import ourselves.
105             sub import
106             {
107 25     25   197 my $pkg = shift;
108 25         1907 my ($cpkg,$file,$line) = caller;
109 25         76 my @symbols;
110 25 100       97 if (@_)
111             {
112 19 100       88 if (grep $_ eq ':all', @_)
113             {
114 5         19 @symbols = (@EXPORT, @EXPORT_OK, grep $_ ne ':all', @_);
115             } else {
116 14         41 @symbols = @_;
117             }
118 19         38 my %seen;
119 19         133 @symbols = grep !$seen{$_}++, @symbols;
120             } else {
121 6         17 @symbols = @EXPORT;
122             }
123 25         53 my %ok;
124 25         114 @ok{@EXPORT_OK,@EXPORT} = ();
125 25         80 my @badsym = grep !exists $ok{$_}, @symbols;
126 25 50       105 if (@badsym)
127             {
128 0 0       0 my $s = @badsym>1? 's' : '';
129 0 0       0 my $v = @badsym>1? 'are' : 'is';
130 0         0 _croak ("The symbol$s ", join(', ', @badsym), " $v not exported by Time::Format at $file line $line.\n");
131             }
132              
133 25     25   206 no strict 'refs';
  25         65  
  25         5593  
134 25         66 foreach my $sym (@symbols)
135             {
136 67         284 $sym =~ s/^([\$\&\@\%])?//;
137 67   100     323 my $pfx = $1 || '&';
138 67         156 my $calsym = $cpkg . '::' . $sym;
139 67         124 my $mysym = $pkg . '::' . $sym;
140 67 100       206 if ($pfx eq '%')
    50          
    50          
141             {
142 34         309 *$calsym = \%$mysym;
143             } elsif ($pfx eq '@') {
144 0         0 *$calsym = \@$mysym;
145             } elsif ($pfx eq '$') {
146 0         0 *$calsym = \$$mysym;
147             } else {
148 33         3752 *$calsym = \&$mysym;
149             }
150             }
151             }
152              
153             # Simple tied-hash implementation.
154              
155             # Each hash is simply tied to a subroutine reference. "Fetching" a
156             # value from the hash invokes the subroutine. If a hash (tied or
157             # otherwise) has multiple comma-separated values but the leading
158             # character is a $, then Perl joins the values with $;. This makes it
159             # easy to simulate function calls with tied hashes -- we just split on
160             # $; to recreate the argument list.
161             #
162             # 2005/12/01: We must ensure that time_format gets two arguments, since
163             # the XS version cannot handle variable argument lists.
164              
165 25     25   199 use vars qw(%time %strftime %manip);
  25         54  
  25         6952  
166             tie %time, 'Time::Format', sub { push @_, 'time' if @_ == 1; goto &time_format};
167             tie %strftime, 'Time::Format', \&time_strftime;
168             tie %manip, 'Time::Format', \&time_manip;
169              
170             sub TIEHASH
171             {
172 75     75   149 my $class = shift;
173 75   50     184 my $func = shift || die "Bad call to $class\::TIEHASH";
174 75         193 bless $func, $class;
175             }
176              
177             sub FETCH
178             {
179 221     221   4029785 my $self = shift;
180 221         463 my $key = shift;
181 221         3768 my @args = split $;, $key, -1;
182 221         922 $self->(@args);
183             }
184              
185 25         149 use subs qw(
186 25     25   13382 STORE EXISTS CLEAR FIRSTKEY NEXTKEY );
  25         791  
187             *STORE = *EXISTS = *CLEAR = *FIRSTKEY = *NEXTKEY = sub
188             {
189 2     2   1582 my ($pkg,$file,$line) = caller;
190 2         14 _croak "Invalid call to Time::Format internal function at $file line $line.";
191             };
192              
193              
194             # Module finder -- do we have the specified module available?
195             {
196             my %have;
197             sub _have
198             {
199 366   50 366   22056 my $module = shift || return;
200 366 100       1382 return $have{$module} if exists $have{$module};
201              
202 18         49 my $incmod = $module;
203 18         102 $incmod =~ s!::!/!g;
204 18 100       166 return $have{$module} = 1 if exists $INC{"$incmod.pm"};
205              
206 5         20 $@ = '';
207 5         439 eval "require $module";
208 5 50       448182 return $have{$module} = $@? 0 : 1;
209             }
210             }
211              
212              
213             # POSIX strftime, for people who like those weird % formats.
214             sub time_strftime
215             {
216             # Check if POSIX is available (why wouldn't it be?)
217 14 50   14 1 712 return 'NO_POSIX' unless _have('POSIX');
218              
219 14         45 my $fmt = shift;
220 14         38 my @time;
221              
222             # If more than one arg, assume they're doing the whole arg list
223 14 100       52 if (@_ > 1)
224             {
225 1         4 @time = @_;
226             }
227             else # use unix time (current or passed)
228             {
229 13 100       39 my $time = @_? shift : time;
230 13         313 @time = localtime $time;
231             }
232              
233 14         481 return POSIX::strftime($fmt, @time);
234             }
235              
236              
237             # Date::Manip interface
238             sub time_manip
239             {
240 14 50   14 1 71153 return "NO_DATEMANIP" unless _have('Date::Manip');
241              
242 14         71 my $fmt = shift;
243 14 100       54 my $time = @_? shift : 'now';
244              
245 14 100       80 $time = $1 if $time =~ /^\s* (epoch \s+ \d+)/x;
246              
247 14         59 return Date::Manip::UnixDate($time, $fmt);
248             }
249              
250              
251             1;
252             __DATA__
253             # The following is only compiled if Time::Format_XS is not available.
254             #line 248 "Time/Format.pm"
255              
256             use Time::Local;
257              
258             # Default names for months, days
259             my %english_names =
260             (
261             Month => [qw[January February March April May June July August September October November December]],
262             Weekday => [qw[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]],
263             th => [qw[/th st nd rd th th th th th th th th th th th th th th th th th st nd rd th th th th th th th st]],
264             );
265             my %names;
266             my $locale;
267             my %loc_cache; # Cache for remembering times that have already been parsed out.
268             my $cache_size=0; # Number of keys in %loc_cache
269             my $cache_size_limit = 1024; # Max number of times to cache
270              
271             # Internal function to initialize locale info.
272             # Returns true if the locale changed.
273             sub setup_locale
274             {
275             # Do nothing if locale has not changed since %names was set up.
276             my $locale_in_use;
277             $locale_in_use = POSIX::setlocale(POSIX::LC_TIME()) if _have('POSIX');
278             $locale_in_use = '' if !defined $locale_in_use;
279             return if defined $locale && $locale eq $locale_in_use;
280              
281             my (@Month, @Mon, @Weekday, @Day);
282              
283             unless (eval {
284             require I18N::Langinfo;
285             I18N::Langinfo->import(qw(langinfo));
286             @Month = map langinfo($_), I18N::Langinfo::MON_1(), I18N::Langinfo::MON_2(), I18N::Langinfo::MON_3(),
287             I18N::Langinfo::MON_4(), I18N::Langinfo::MON_5(), I18N::Langinfo::MON_6(),
288             I18N::Langinfo::MON_7(), I18N::Langinfo::MON_8(), I18N::Langinfo::MON_9(),
289             I18N::Langinfo::MON_10(), I18N::Langinfo::MON_11(), I18N::Langinfo::MON_12();
290             @Mon = map langinfo($_), I18N::Langinfo::ABMON_1(), I18N::Langinfo::ABMON_2(), I18N::Langinfo::ABMON_3(),
291             I18N::Langinfo::ABMON_4(), I18N::Langinfo::ABMON_5(), I18N::Langinfo::ABMON_6(),
292             I18N::Langinfo::ABMON_7(), I18N::Langinfo::ABMON_8(), I18N::Langinfo::ABMON_9(),
293             I18N::Langinfo::ABMON_10(), I18N::Langinfo::ABMON_11(), I18N::Langinfo::ABMON_12();
294             @Weekday = map langinfo($_), I18N::Langinfo::DAY_1(), I18N::Langinfo::DAY_2(), I18N::Langinfo::DAY_3(),
295             I18N::Langinfo::DAY_4(), I18N::Langinfo::DAY_5(), I18N::Langinfo::DAY_6(), I18N::Langinfo::DAY_7();
296             @Day = map langinfo($_), I18N::Langinfo::ABDAY_1(), I18N::Langinfo::ABDAY_2(), I18N::Langinfo::ABDAY_3(),
297             I18N::Langinfo::ABDAY_4(), I18N::Langinfo::ABDAY_5(), I18N::Langinfo::ABDAY_6(), I18N::Langinfo::ABDAY_7();
298             1;
299             }
300             )
301             { # Internationalization didn't work for some reason; go with English.
302             @Month = @{ $english_names{Month} };
303             @Weekday = @{ $english_names{Weekday} };
304             @Mon = map substr($_,0,3), @Month;
305             @Day = map substr($_,0,3), @Weekday;
306             $@ = '';
307             }
308              
309             # Store in %names, setting proper case
310             $names{Month} = \@Month;
311             $names{Weekday} = \@Weekday;
312             $names{Mon} = \@Mon;
313             $names{Day} = \@Day;
314             $names{th} = $english_names{th};
315             $names{TH} = [map uc, @{$names{th}}];
316              
317             foreach my $name (keys %names)
318             {
319             my $aref = $names{$name}; # locale-native case
320             $names{uc $name} = [map uc, @$aref]; # upper=case
321             $names{lc $name} = [map lc, @$aref]; # lower-case
322             }
323              
324             %loc_cache = (); # locale changes are rare. Clear out cache.
325             $cache_size = 0;
326             $locale = $locale_in_use;
327              
328             return 1;
329             }
330              
331             # Types of time values we can handle:
332             my $NUMERIC_TIME = \&decode_epoch;
333             my $DATETIME_OBJECT = \&decode_DateTime_object;
334             my $DATETIME_STRING = \&decode_DateTime_string;
335             # my $DATEMANIP_STRING = \&decode_DateManip_string;
336              
337             # What kind of argument was passed to time_format?
338             # Returns (type, time, cache_time_key, milliseconds, microseconds)
339             sub _classify_time
340             {
341             my $timeval = shift;
342             $timeval = 'time' if !defined $timeval;
343              
344             my $frac; # Fractional seconds, if any
345             my $cache_value; # 1/20 of 1 cent
346             my $time_type;
347              
348             # DateTime object?
349             if (UNIVERSAL::isa($timeval, 'DateTime'))
350             {
351             $cache_value = "$timeval"; # stringify
352             $frac = $timeval->nanosecond() / 1e9;
353             $time_type = $DATETIME_OBJECT;
354             }
355             # Numeric time?
356             # 1 to 11 digits-- Epoch time should be <= 10 digits, and 12 digits might be YYYYMMDDHHMM.
357             elsif ($timeval =~ /^\s* ( (\d{1,11}) (?:[.,](\d+))? ) $/x)
358             {
359             $timeval = $1;
360             $cache_value = $2;
361             $frac = $3? '0.' . $3 : 0;
362             $time_type = $NUMERIC_TIME;
363             }
364             # Stringified DateTime object?
365             # Except we make it more flexible by allowing the date OR the time to be specfied
366             # This will also match Date::Manip strings, and many ISO-8601 strings.
367             elsif ($timeval =~ m{\A( (?!\d{6,8}\z) # string must not consist of only 6 or 8 digits.
368             (?: # year-month-day
369             \d{4} # year
370             [-/.]? (?:0[1-9]|1[0-2]) # month
371             [-/.]? (?:0[1-9]|[12]\d|3[01]) # day
372             )? # ymd is optional
373             (?: (?<=\d) [T_ ] (?=\d) )? # separator: T or _ or space, but only if ymd and hms both present
374             ) # End of $1: YMD and separator
375             (?: # hms is optional
376             (
377             (?:[01]\d|2[0-4]) # hour
378             [:.]? (?:[0-5]\d) # minute
379             [:.]? (?:[0-5]\d|6[0-1])? # second
380             ) # End of $2: HMS
381             (?: [,.] (\d+))? # optional fraction
382             (Z?) # optional "zulu" (UTC) designator
383             )? # end of optional (HMS.fraction)
384             \z
385             }x)
386             {
387             $cache_value = ($1 || q{}) . ($2 || q{}) . ($4 || q{});
388             $frac = $3? '0.' . $3 : 0;
389             $time_type = $DATETIME_STRING;
390             }
391             # Not set, or set to 'time' string?
392             elsif ($timeval eq 'time' || $timeval eq q{})
393             {
394             # Get numeric time
395             $timeval = _have('Time::HiRes')? Time::HiRes::time() : time;
396             $cache_value = int $timeval;
397             $frac = $timeval - $cache_value;
398             $time_type = $NUMERIC_TIME;
399             }
400             # *Tiny* numeric time (very close to zero; exponential notation)?
401             # (See bug 87484, https://rt.cpan.org/Ticket/Display.html?id=87484)
402             elsif ($timeval =~ /^\s* -? \d\.\d+ e-\d+ \s*$/x)
403             {
404             $timeval = sprintf '%8.6f', abs($timeval);
405             $cache_value = int $timeval;
406             $frac = $timeval - $cache_value;
407             $time_type = $NUMERIC_TIME;
408             }
409             else
410             {
411             # User passed us something we don't know how to handle.
412             _croak qq{Unrecognized time value: "$timeval"};
413             }
414             # We messed up.
415             die qq{Illegal time type "$time_type"; programming error in Time::Format. Contact author.}
416             if !defined &$time_type;
417              
418             # Calculate millisecond, microsecond from fraction
419             # msec and usec are TRUNCATED, not ROUNDED, because rounding up
420             # to the next higher second would be a nightmare.
421             my $msec = sprintf '%03d', int ( 1_000 * $frac);
422             my $usec = sprintf '%06d', int (1_000_000 * $frac);
423              
424             return ($time_type, $timeval, $cache_value, $msec, $usec);
425             }
426              
427             # Helper function -- returns localtime() hashref
428             sub _loctime
429             {
430             my ($decode, $time, $cachekey, $msec, $usec) = _classify_time(@_);
431             my $locale_changed = setup_locale;
432              
433             # Cached, because I expect this'll be called on the same time values frequently.
434             die "Programming error: undefined cache value. Contact Time::Format author."
435             if !defined $cachekey;
436              
437             # If locale has changed, can't use the cached value.
438             if (!$locale_changed && exists $loc_cache{$cachekey})
439             {
440             my $h = $loc_cache{$cachekey};
441             ($h->{mmm}, $h->{uuuuuu}) = ($msec, $usec);
442             return $h;
443             }
444              
445             # Hour-12, time zone, localtime parts, decoded from input
446             my ($h12, $tz, @time_parts) = $decode->($time);
447              
448             # Populate a whole mess o' data elements
449             my %th;
450             my $m0 = $time_parts[4] - 1; # zero-based month
451              
452             # NOTE: When adding new codes, be wary of adding any that interfere
453             # with the user's ability to use the words "at", "on", or "of" literally.
454              
455             # year, hour(12), month, day, hour, minute, second, millisecond, microsecond, time zone
456             @th{qw[yyyy H m{on} d h m{in} s mmm uuuuuu tz]} = ( $time_parts[5], $h12, @time_parts[4,3,2,1,0], $msec, $usec, $tz);
457             @th{qw[yy HH mm{on} dd hh mm{in} ss]} = map $_<10?"0$_":$_, $time_parts[5]%100, $h12, @time_parts[4,3,2,1,0];
458             @th{qw[ ?H ?m{on} ?d ?h ?m{in} ?s]} = map $_<10?" $_":$_, $h12, @time_parts[4,3,2,1,0];
459              
460             # AM/PM
461             my ($h,$d,$wx) = @time_parts[2,3,6]; # Day, weekday index
462             my $a = $h<12? 'a' : 'p';
463             $th{am} = $th{pm} = $a . 'm';
464             $th{'a.m.'} = $th{'p.m.'} = $a . '.m.';
465             @th{qw/AM PM A.M. P.M./} = map uc, @th{qw/am pm a.m. p.m./};
466              
467             $th{$_} = $names{$_}[$wx] for qw/Weekday WEEKDAY weekday Day DAY day/;
468             $th{$_} = $names{$_}[$m0] for qw/Month MONTH month Mon MON mon/;
469             $th{$_} = $names{$_}[$d] for qw/th TH/;
470              
471             # Don't let the time cache grow boundlessly.
472             if (++$cache_size == $cache_size_limit)
473             {
474             $cache_size = 0;
475             %loc_cache = ();
476             }
477             return $loc_cache{$cachekey} = \%th;
478             }
479              
480             sub decode_DateTime_object
481             {
482             my $dt = shift;
483              
484             my @t = ($dt->hour_12, $dt->time_zone_short_name,
485             $dt->second, $dt->minute, $dt->hour,
486             $dt->day, $dt->month, $dt->year,
487             $dt->dow, $dt->doy, $dt->is_dst);
488             $t[-3] = 0 if $t[-3] == 7; # Convert 1-7 (Mon-Sun) to 0-6 (Sun-Sat).
489              
490             return @t;
491             }
492              
493             # 2005-10-31T15:14:39
494             sub decode_DateTime_string
495             {
496             my $dts = shift;
497             unless ($dts =~ m{\A (?!>\d{6,8}\z) # string must not consist of only 6 or 8 digits.
498             (?:
499             (\d{4}) [-/.]? (\d{2}) [-/.]? (\d{2}) # year-month-day
500             )? # ymd is optional, but next must not be digit
501             (?: (?<=\d) [T_ ] (?=\d) )? # separator: T or _ or space, but only if ymd and hms both present
502             (?: # hms is optional
503             (\d{2}) [:.]? (\d{2}) [:.]? (\d{2}) # hour:minute:second
504             (?: [,.] \d+)? # optional fraction (ignored in this sub)
505             (Z?) # optional "zulu" (UTC) indicator
506             )? \z
507             }x)
508             {
509             # This "should" never happen, since we checked the format of
510             # the string already.
511             die qq{Unrecognized DateTime string "$dts": probable Time::Format bug};
512             }
513              
514             my ($y,$mon,$d,$h,$min,$s,$tz) = ($1,$2,$3,$4,$5,$6,$7);
515             my ($d_only, $t_only);
516             my ($h12, $is_dst, $dow);
517             if (!defined $y)
518             {
519             # Time only. Set date to 1969-12-31.
520             $y = 1969;
521             $mon = 12;
522             $d = 31;
523             $h12 = $h == 0? 12
524             : $h > 12? $h - 12
525             : $h;
526             $is_dst = 0; # (it's the dead of winter!)
527             $dow = 3; # 12/31/1969 is Wednesday.
528             $t_only = 1;
529             }
530             if (!defined $h)
531             {
532             $h = 0;
533             $min = 0;
534             $s = 0;
535             $d_only = 1;
536             }
537              
538             if (!$t_only)
539             {
540             $h12 = $h == 0? 12
541             : $h > 12? $h - 12
542             : $h;
543              
544             # DST?
545             # If year is before 1970, use current year.
546             my $tmp_year = $y > 1969? $y : (localtime)[5]+1900;
547             my $ttime = timelocal(0, 0, 0, $d, $mon-1, $tmp_year);
548             my @t = localtime $ttime;
549             $is_dst = $t[8];
550             $dow = _dow($y, $mon, $d);
551             }
552              
553             # +0 is to force numeric (remove leading zeroes)
554             my @t = map {$_+0} ($s,$min,$h,$d,$mon,$y);
555             $h12 += 0;
556              
557             if ($tz && $tz eq 'Z')
558             {
559             $tz = 'UTC';
560             }
561             elsif (_have('POSIX'))
562             {
563             $tz = POSIX::strftime('%Z', @t, $dow, -1, $is_dst);
564             }
565              
566             return ($h12, $tz, @t, $dow, -1, $is_dst);
567             }
568              
569             sub decode_epoch
570             {
571             my $time = shift; # Assumed to be an epoch time integer
572              
573             my @t = localtime $time;
574             my $tz = _have('POSIX')? POSIX::strftime('%Z', @t) : '';
575             my $h = $t[2]; # Hour (24), Month index
576             $t[4]++;
577             $t[5] += 1900;
578             my $h12 = $h>12? $h-12 : ($h || 12);
579              
580             return ($h12, $tz, @t);
581             }
582              
583             # $int = dow ($year, $month, $day);
584             #
585             # Returns the day of the week (0=Sunday .. 6=Saturday). Uses Zeller's
586             # congruence, so it isn't subject to the unix 2038 limitation.
587             #
588             #---> $int = dow ($year, $month, $day);
589             sub _dow
590             {
591             my ($Y, $M, $D) = @_;
592              
593             $M -= 2;
594             if ($M < 1)
595             {
596             $M += 12;
597             $Y--;
598             }
599             my $C = int($Y/100);
600             $Y %= 100;
601              
602             return (int((26*$M - 2)/10) + $D + $Y + int($Y/4) + int($C/4) - 2*$C) % 7;
603             }
604              
605              
606             # The heart of the module. Didja ever see so many wicked regexes in a row?
607              
608             my %disam; # Disambiguator for 'm' format.
609             $disam{$_} = "{on}" foreach qw/yy d dd ?d/; # If year or day is nearby, it's 'month'
610             $disam{$_} = "{in}" foreach qw/h hh ?h H HH ?H s ss ?s/; # If hour or second is nearby, it's 'minute'
611             sub time_format_perlonly
612             {
613             my $fmt = shift;
614             my $time = _loctime(@_);
615              
616             # Remove \Q...\E sequences
617             my $rc;
618             if (index($fmt, '\Q') >= 0)
619             {
620             $rc = init_store($fmt);
621             $fmt =~ s/\\Q(.*?)(?:\\E|$)/remember($1)/seg;
622             }
623              
624             # "Guess" how to interpret ambiguous 'm'
625             $fmt =~ s/
626             (?<!\\) # Must not follow a backslash
627             (?=[ydhH]) # Must start with one of these
628             ( # $1 begins
629             ( # $2 begins. Capture:
630             yy # a year
631             | [dhH] # a day or hour
632             )
633             [^?m\\]? # Followed by something that's not part of a month
634             )
635             (?![?m]?m\{[io]n\}) # make sure it's not already unambiguous
636             (?!mon) # don't confuse "mon" with "m" "on"
637             ([?m]?m) # $3 is a month code
638             /$1$3$disam{$2}/gx;
639              
640             # Ambiguous 'm', part 2.
641             $fmt =~ s/(?<!\\) # ignore things that begin with backslash
642             ([?m]?m) # $1 is a month code
643             ( # $2 begins.
644             [^\\]? # 0 or 1 characters
645             (?=[?dsy]) # Next char must be one of these
646             ( # $3 begins. Capture:
647             \??[ds] # a day or a second
648             | yy # or a year
649             )
650             )/$1$disam{$3}$2/gx;
651              
652             # The Big Date/Time Pattern of Doom
653             $fmt =~ s/
654             (?<!\\) # Don't expand something preceded by backslash
655             (?=[dDy?hHsaApPMmWwutT]) # Jump to one of these characters
656             (
657             [Dd]ay|DAY # Weekday abbreviation
658             | yy(?:yy)? # Year
659             | [?m]?m\{[oi]n\} # Unambiguous month-minute codes
660             | th | TH # day suffix
661             | [?d]?d # Day
662             | [?h]?h # Hour (24)
663             | [?H]?H # Hour (12)
664             | [?s]?s # Second
665             | [apAP]\.?[mM]\.? # am and pm strings
666             | [Mm]on(?:th)?|MON(?:TH)? # Month names and abbrev
667             | [Ww]eekday|WEEKDAY # Weekday names
668             | mmm|uuuuuu # millisecond and microsecond
669             | tz # time zone
670             )/$time->{$1}/gx;
671              
672             # Simulate \U \L \u \l
673             $fmt =~ s/((?:\\[UL])+)((?:\\[ul])+)/$2$1/g;
674             $fmt =~ s/\\U(.*?)(?=\\[EULul]|$)/\U$1/gs;
675             $fmt =~ s/\\L(.*?)(?=\\[EULul]|$)/\L$1/gs;
676             $fmt =~ s/\\l(.)/\l$1/gs;
677             $fmt =~ s/\\u(.)/\u$1/gs;
678             $fmt =~ s/\\E//g;
679              
680             $fmt =~ tr/\\//d; # Remove extraneous backslashes.
681              
682             if (defined $rc) # Fixup \Q \E regions.
683             {
684             $fmt =~ s/$rc(..)/recall($1)/seg;
685             }
686             return $fmt;
687             }
688              
689             # Code for remembering/restoring \Q...\E regions.
690             # init_store finds a sigil character that's not used within the format string.
691             # remember stores a string in the next slot in @store, and returns a coded replacement.
692             # recall looks up and returns a string from @store.
693             {
694             my $rcode;
695             my @store;
696             my $stx;
697              
698             sub init_store
699             {
700             my $str = shift;
701             $stx = 0;
702             return $rcode = "\x01" unless index($str,"\x01") >= 0;
703              
704             for ($rcode="\x02"; $rcode<"\xFF"; $rcode=chr(1+ord $rcode))
705             {
706             return $rcode unless index($str, $rcode) >= 0;
707             }
708             _croak "Time::Format cannot process string: no unique characters left.";
709             }
710              
711             sub remember
712             {
713             my $enc;
714             do # Must not return a code that contains a backslash
715             {
716             $enc = pack 'S', $stx++;
717             } while index($enc, '\\') >= 0;
718              
719             $store[$stx-1] = shift;
720             return join '', map "\\$_", split //, "$rcode$enc"; # backslash-escape it!
721             }
722              
723             sub recall
724             {
725             return $store[unpack 'S', shift];
726             }
727             }
728              
729             __END__
730              
731             =head1 SYNOPSIS
732              
733             use Time::Format qw(%time %strftime %manip);
734              
735             $time{$format}
736             $time{$format, $unixtime}
737              
738             print "Today is $time{'yyyy/mm/dd'}\n";
739             print "Yesterday was $time{'yyyy/mm/dd', time-24*60*60}\n";
740             print "The time is $time{'hh:mm:ss'}\n";
741             print "Another time is $time{'H:mm am tz', $another_time}\n";
742             print "Timestamp: $time{'yyyymmdd.hhmmss.mmm'}\n";
743              
744             C<%time> also accepts Date::Manip strings and DateTime objects:
745              
746             $dm = Date::Manip::ParseDate('last monday');
747             print "Last monday was $time{'Month d, yyyy', $dm}";
748             $dt = DateTime->new (....);
749             print "Here's another date: $time{'m/d/yy', $dt}";
750              
751             It also accepts most ISO-8601 date/time strings:
752              
753             $t = '2005/10/31T17:11:09'; # date separator: / or - or .
754             $t = '2005-10-31 17.11.09'; # in-between separator: T or _ or space
755             $t = '20051031_171109'; # time separator: : or .
756             $t = '20051031171109'; # separators may be omitted
757             $t = '2005/10/31'; # date-only is okay
758             $t = '17:11:09'; # time-only is okay
759             # But not:
760             $t = '20051031'; # date-only without separators
761             $t = '171109'; # time-only without separators
762             # ...because those look like epoch time numbers.
763              
764             C<%strftime> works like POSIX's C<strftime>, if you like those C<%>-formats.
765              
766             $strftime{$format}
767             $strftime{$format, $unixtime}
768             $strftime{$format, $sec,$min,$hour, $mday,$mon,$year, $wday,$yday,$isdst}
769              
770             print "POSIXish: $strftime{'%A, %B %d, %Y', 0,0,0,12,11,95,2}\n";
771             print "POSIXish: $strftime{'%A, %B %d, %Y', 1054866251}\n";
772             print "POSIXish: $strftime{'%A, %B %d, %Y'}\n"; # current time
773              
774             C<%manip> works like Date::Manip's C<UnixDate> function.
775              
776             $manip{$format};
777             $manip{$format, $when};
778              
779             print "Date::Manip: $manip{'%m/%d/%Y'}\n"; # current time
780             print "Date::Manip: $manip{'%m/%d/%Y','last Tuesday'}\n";
781              
782             These can also be used as standalone functions:
783              
784             use Time::Format qw(time_format time_strftime time_manip);
785              
786             print "Today is ", time_format('yyyy/mm/dd', $some_time), "\n";
787             print "POSIXish: ", time_strftime('%A %B %d, %Y',$some_time), "\n";
788             print "Date::Manip: ", time_manip('%m/%d/%Y',$some_time), "\n";
789              
790             =head1 DESCRIPTION
791              
792             This module creates global pseudovariables which format dates and
793             times, according to formatting codes you pass to them in strings.
794              
795             The C<%time> formatting codes are designed to be easy to remember and
796             use, and to take up just as many characters as the output time value
797             whenever possible. For example, the four-digit year code is
798             "C<yyyy>", the three-letter month abbreviation is "C<Mon>".
799              
800             The nice thing about having a variable-like interface instead
801             of function calls is that the values can be used inside of strings (as
802             well as outside of strings in ordinary expressions). Dates are
803             frequently used within strings (log messages, output, data records,
804             etc.), so having the ability to interpolate them directly is handy.
805              
806             Perl allows arbitrary expressions within curly braces of a hash, even
807             when that hash is being interpolated into a string. This allows you
808             to do computations on the fly while formatting times and inserting
809             them into strings. See the "yesterday" example above.
810              
811             The format strings are designed with programmers in mind. What do you
812             need most frequently? 4-digit year, month, day, 24-based hour,
813             minute, second -- usually with leading zeroes. These six are the
814             easiest formats to use and remember in Time::Format: C<yyyy>, C<mm>,
815             C<dd>, C<hh>, C<mm>, C<ss>. Variants on these formats follow a simple
816             and consistent formula. This module is for everyone who is weary of
817             trying to remember I<strftime(3)>'s arcane codes, or of endlessly
818             writing C<$t[4]++; $t[5]+=1900> as you manually format times or dates.
819              
820             Note that C<mm> (and related codes) are used both for months and
821             minutes. This is a feature. C<%time> resolves the ambiguity by
822             examining other nearby formatting codes. If it's in the context of a
823             year or a day, "month" is assumed. If in the context of an hour or a
824             second, "minute" is assumed.
825              
826             The format strings are not meant to encompass every date/time need
827             ever conceived. But how often do you need the day of the year
828             (strftime's C<%j>) or the week number (strftime's C<%W>)?
829              
830             For capabilities that C<%time> does not provide, C<%strftime> provides
831             an interface to POSIX's C<strftime>, and C<%manip> provides an
832             interface to the Date::Manip module's C<UnixDate> function.
833              
834             If the companion module L<Time::Format_XS> is also installed,
835             Time::Format will detect and use it. This will result in a
836             significant speed increase for C<%time> and C<time_format>.
837              
838             =head1 VARIABLES
839              
840             =over 4
841              
842             =item time
843              
844             $time{$format}
845             $time{$format,$time_value};
846              
847             Formats a unix time number (seconds since the epoch), DateTime object,
848             stringified DateTime, Date::Manip string, or ISO-8601 string,
849             according to the specified format. If the time expression is omitted,
850             the current time is used. The format string may contain any of the
851             following:
852              
853             yyyy 4-digit year
854             yy 2-digit year
855              
856             m 1- or 2-digit month, 1-12
857             mm 2-digit month, 01-12
858             ?m month with leading space if < 10
859              
860             Month full month name, mixed-case
861             MONTH full month name, uppercase
862             month full month name, lowercase
863             Mon 3-letter month abbreviation, mixed-case
864             MON mon ditto, uppercase and lowercase versions
865              
866             d day number, 1-31
867             dd day number, 01-31
868             ?d day with leading space if < 10
869             th day suffix (st, nd, rd, or th)
870             TH uppercase suffix
871              
872             Weekday weekday name, mixed-case
873             WEEKDAY weekday name, uppercase
874             weekday weekday name, lowercase
875             Day 3-letter weekday name, mixed-case
876             DAY day ditto, uppercase and lowercase versions
877              
878             h hour, 0-23
879             hh hour, 00-23
880             ?h hour, 0-23 with leading space if < 10
881              
882             H hour, 1-12
883             HH hour, 01-12
884             ?H hour, 1-12 with leading space if < 10
885              
886             m minute, 0-59
887             mm minute, 00-59
888             ?m minute, 0-59 with leading space if < 10
889              
890             s second, 0-59
891             ss second, 00-59
892             ?s second, 0-59 with leading space if < 10
893             mmm millisecond, 000-999
894             uuuuuu microsecond, 000000-999999
895              
896             am a.m. The string "am" or "pm" (second form with periods)
897             pm p.m. same as "am" or "a.m."
898             AM A.M. same as "am" or "a.m." but uppercase
899             PM P.M. same as "AM" or "A.M."
900              
901             tz time zone abbreviation
902              
903             Millisecond and microsecond require Time::HiRes, otherwise they'll
904             always be zero. Timezone requires POSIX, otherwise it'll be the empty
905             string. The second codes (C<s>, C<ss>, C<?s>) can be 60 or 61 in rare
906             circumstances (leap seconds, if your system supports such).
907              
908             Anything in the format string other than the above patterns is left
909             intact. Any character preceded by a backslash is left alone and
910             not used for any part of a format code. See the L</QUOTING> section
911             for more details.
912              
913             For the most part, each of the above formatting codes takes up as much
914             space as the output string it generates. The exceptions are the codes
915             whose output is variable length: C<Weekday>, C<Month>, time zone, and
916             the single-character codes.
917              
918             The mixed-case "Month", "Mon", "Weekday", and "Day" codes return the
919             name of the month or weekday in the preferred case representation for
920             the locale currently in effect. Thus in an English-speaking locale,
921             the seventh month would be "July" (uppercase first letter, lowercase
922             rest); while in a French-speaking locale, it would be "juillet" (all
923             lowercase). See the L</QUOTING> section for ways to control the case
924             of month/weekday names.
925              
926             Note that the "C<mm>", "C<m>", and "C<?m>" formats are ambiguous.
927             C<%time> tries to guess whether you meant "month" or "minute" based on
928             nearby characters in the format string. Thus, a format of
929             "C<yyyy/mm/dd hh:mm:ss>" is correctly parsed as "year month day, hour
930             minute second". If C<%time> cannot determine whether you meant
931             "month" or "minute", it leaves the C<mm>, C<m>, or C<?m> untranslated.
932             To remove the ambiguity, you can use the following codes:
933              
934             m{on} month, 1-12
935             mm{on} month, 01-12
936             ?m{on} month, 1-12 with leading space if < 10
937              
938             m{in} minute, 0-59
939             mm{in} minute, 00-59
940             ?m{in} minute, 0-59 with leading space if < 10
941              
942             In other words, append "C<{on}>" or "C<{in}>" to make "C<m>", "C<mm>",
943             or "C<?m>" unambiguous.
944              
945             =item strftime
946              
947             $strftime{$format, $sec,$min,$hour, $mday,$mon,$year, $wday,$yday,$isdst}
948             $strftime{$format, $unixtime}
949             $strftime{$format}
950              
951             For those who prefer L<strftime|POSIX/strftime>'s weird % formats, or
952             who need POSIX compliance, or who need week numbers or other features
953             C<%time> does not provide.
954              
955             =item manip
956              
957             $manip{$format};
958             $manip{$format,$when};
959              
960             Provides an interface to the Date::Manip module's C<UnixDate>
961             function. This function is rather slow, but can parse a very wide
962             variety of date input. See the L<Date::Manip> module for details
963             about the inputs accepted.
964              
965             If you want to use the C<%time> codes, but need the input flexibility
966             of C<%manip>, you can use Date::Manip's C<ParseDate> function:
967              
968             print "$time{'yyyymmdd', ParseDate('last sunday')}";
969              
970             =back
971              
972             =head1 FUNCTIONS
973              
974             =over 4
975              
976             =item time_format
977              
978             time_format($format);
979             time_format($format, $unix_time);
980              
981             This is a function interface to C<%time>. It accepts the same
982             formatting codes and everything. This is provided for people who want
983             their function calls to I<look> like function calls, not hashes. :-)
984             The following two are equivalent:
985              
986             $x = $time{'yyyy/mm/dd'};
987             $x = time_format('yyyy/mm/dd');
988              
989             =item time_strftime
990              
991             time_strftime($format, $sec,$min,$hour, $mday,$mon,$year, $wday,$yday,$isdst);
992             time_strftime($format, $unixtime);
993             time_strftime($format);
994              
995             This is a function interface to C<%strftime>. It simply calls
996             POSIX::C<strftime>, but it does provide a bit of an advantage over
997             calling C<strftime> directly, in that you can pass the time as a unix
998             time (seconds since the epoch), or omit it in order to get the current
999             time.
1000              
1001             =item time_manip
1002              
1003             manip($format);
1004             manip($format,$when);
1005              
1006             This is a function interface to C<%manip>. It calls
1007             Date::Manip::C<UnixDate> under the hood. It does not provide much of
1008             an advantage over calling C<UnixDate> directly, except that you can
1009             omit the C<$when> parameter in order to get the current time.
1010              
1011             =back
1012              
1013             =head1 QUOTING
1014              
1015             This section applies to the format strings used by C<%time> and
1016             C<time_format> only.
1017              
1018             Sometimes it is necessary to suppress expansion of some format
1019             characters in a format string. For example:
1020              
1021             $time{'Hour: hh; Minute: mm{in}; Second: ss'};
1022              
1023             In the above expression, the "H" in "Hour" would be expanded,
1024             as would the "d" in "Second". The result would be something like:
1025              
1026             8our: 08; Minute: 10; Secon17: 30
1027              
1028             It would not be a good solution to break the above statement out
1029             into three calls to %time:
1030              
1031             "Hour: $time{hh}; Minute: $time{'mm{in}'}; Second: $time{ss}"
1032              
1033             because the time could change from one call to the next, which would
1034             be a problem when the numbers roll over (for example, a split second
1035             after 7:59:59).
1036              
1037             For this reason, you can escape individual format codes with a
1038             backslash:
1039              
1040             $time{'\Hour: hh; Minute: mm{in}; Secon\d: ss'};
1041              
1042             Note that with double-quoted (and qq//) strings, the backslash must be
1043             doubled, because Perl first interpolates the string:
1044              
1045             $time{"\\Hour: hh; Minute: mm{in}; Secon\\d: ss"};
1046              
1047             For added convenience, Time::Format simulates Perl's built-in \Q and
1048             \E inline quoting operators. Anything in a string between a \Q and \E
1049             will not be interpolated as any part of any formatting code:
1050              
1051             $time{'\QHour:\E hh; \QMinute:\E mm{in}; \QSecond:\E ss'};
1052              
1053             Again, within interpolated strings, the backslash must be doubled, or
1054             else Perl will interpret and remove the \Q...\E sequence before
1055             Time::Format gets it:
1056              
1057             $time{"\\QHour:\\E hh; \\QMinute:\\E mm{in}; \\QSecond\\E: ss"};
1058              
1059             Time::Format also recognizes and simulates the \U, \L, \u, and \l
1060             sequences. This is really only useful for finer control of the Month,
1061             Mon, Weekday, and Day formats. For example, in some locales, the
1062             month names are all-lowercase by convention. At the start of a
1063             sentence, you may want to ensure that the first character is
1064             uppercase:
1065              
1066             $time{'\uMonth \Qis the finest month of all.'};
1067              
1068             Again, be sure to use \Q, and be sure to double the backslashes in
1069             interpolated strings, otherwise you'll get something ugly like:
1070              
1071             July i37 ste fine37t july of all.
1072              
1073             =head1 EXAMPLES
1074              
1075             $time{'Weekday Month d, yyyy'} Thursday June 5, 2003
1076             $time{'Day Mon d, yyyy'} Thu Jun 5, 2003
1077             $time{'dd/mm/yyyy'} 05/06/2003
1078             $time{yymmdd} 030605
1079             $time{'yymmdd',time-86400} 030604
1080             $time{'dth of Month'} 5th of June
1081              
1082             $time{'H:mm:ss am'} 1:02:14 pm
1083             $time{'hh:mm:ss.uuuuuu'} 13:02:14.171447
1084              
1085             $time{'yyyy/mm{on}/dd hh:mm{in}:ss.mmm'} 2003/06/05 13:02:14.171
1086             $time{'yyyy/mm/dd hh:mm:ss.mmm'} 2003/06/05 13:02:14.171
1087              
1088             $time{"It's H:mm."} It'14 1:02. # OOPS!
1089             $time{"It'\\s H:mm."} It's 1:02. # Backslash fixes it.
1090             .
1091             .
1092             # Rename a file based on today's date:
1093             rename $file, "$file_$time{yyyymmdd}";
1094              
1095             # Rename a file based on its last-modify date:
1096             rename $file, "$file_$time{'yyyymmdd',(stat $file)[9]}";
1097              
1098             # stftime examples
1099             $strftime{'%A %B %d, %Y'} Thursday June 05, 2003
1100             $strftime{'%A %B %d, %Y',time+86400} Friday June 06, 2003
1101              
1102             # manip examples
1103             $manip{'%m/%d/%Y'} 06/05/2003
1104             $manip{'%m/%d/%Y','yesterday'} 06/04/2003
1105             $manip{'%m/%d/%Y','first monday in November 2000'} 11/06/2000
1106              
1107             =head1 INTERNATIONALIZATION
1108              
1109             If the I18N::Langinfo module is available, Time::Format will return
1110             weekday and month names in the language appropriate for the current
1111             locale. If not, English names will be used.
1112              
1113             Programmers in non-English locales may want to provide an alias to
1114             C<%time> in their own preferred language. This can be done by
1115             assigning C<\%time> to a typeglob:
1116              
1117             # French
1118             use Time::Format;
1119             use vars '%temps'; *temps = \%time;
1120             print "C'est aujourd'hui le $temps{'d Month'}\n";
1121              
1122             # German
1123             use Time::Format;
1124             use vars '%zeit'; *zeit = \%time;
1125             print "Heutiger Tag ist $zeit{'d.m.yyyy'}\n";
1126              
1127             =head1 EXPORTS
1128              
1129             The following symbols are exported into your namespace by default:
1130              
1131             %time
1132             time_format
1133              
1134             The following symbols are available for import into your namespace:
1135              
1136             %strftime
1137             %manip
1138             time_strftime
1139             time_manip
1140              
1141             The C<:all> tag will import all of these into your namespace.
1142             Example:
1143              
1144             use Time::Format ':all';
1145              
1146             =head1 BUGS
1147              
1148             The format string used by C<%time> must not have $; as a substring
1149             anywhere. $; (by default, ASCII character 28, or 1C hex) is used to
1150             separate values passed to the tied hash, and thus Time::Format will
1151             interpret your format string to be two or more arguments if it
1152             contains $;. The C<time_format> function does not have this
1153             limitation.
1154              
1155             =head1 REQUIREMENTS
1156              
1157             Time::Local
1158             I18N::Langinfo, if you want non-English locales to work.
1159             POSIX, if you choose to use %strftime or want the C<tz> format to work.
1160             Time::HiRes, if you want the C<mmm> and C<uuuuuu> time formats to work.
1161             Date::Manip, if you choose to use %manip.
1162              
1163             Time::Format_XS is optional but will make C<%time> and C<time_format>
1164             much faster. The version of Time::Format_XS installed must match
1165             the version of Time::Format installed; otherwise Time::Format will
1166             not use it (and will issue a warning).
1167              
1168             =head1 AUTHOR / COPYRIGHT
1169              
1170             Copyright (c) 2003-2019 by Eric J. Roode, ROODE I<-at-> cpan I<-dot-> org
1171              
1172             All rights reserved.
1173              
1174             To avoid my spam filter, please include "Perl", "module", or this
1175             module's name in the message's subject line, and/or GPG-sign your
1176             message.
1177              
1178             This module is copyrighted only to ensure proper attribution of
1179             authorship and to ensure that it remains available to all. This
1180             module is free, open-source software. This module may be freely used
1181             for any purpose, commercial, public, or private, provided that proper
1182             credit is given, and that no more-restrictive license is applied to
1183             derivative (not dependent) works.
1184              
1185             Substantial efforts have been made to ensure that this software meets
1186             high quality standards; however, no guarantee can be made that there
1187             are no undiscovered bugs, and no warranty is made as to suitability to
1188             any given use, including merchantability. Should this module cause
1189             your house to burn down, your dog to collapse, your heart-lung machine
1190             to fail, your spouse to desert you, or George Bush to be re-elected, I
1191             can offer only my sincere sympathy and apologies, and promise to
1192             endeavor to improve the software.
1193              
1194              
1195             =begin gpg
1196              
1197             -----BEGIN PGP SIGNATURE-----
1198              
1199             iF0EARECAB0WIQTSmjxiQX/QfjsCVJLChJhzmpBWqgUCXTtSTQAKCRDChJhzmpBW
1200             qqmjAKCO5fIeALvd5cOw6C+o+4nqamDxagCePM3JdKVIEYuSz9VOaTWiJGVbo54=
1201             =drPW
1202             -----END PGP SIGNATURE-----
1203              
1204             =end gpg