File Coverage

blib/lib/Time/F.pm
Criterion Covered Total %
statement 47 55 85.4
branch 17 36 47.2
condition 3 5 60.0
subroutine 9 9 100.0
pod 1 1 100.0
total 77 106 72.6


line stmt bran cond sub pod time code
1 10     10   60 use strict;
  10         21  
  10         278  
2 10     10   48 use warnings;
  10         20  
  10         536  
3             package Time::F;
4             $Time::F::VERSION = '0.024';
5             # ABSTRACT: Formatting times.
6              
7 10     10   56 use Carp qw/ croak /;
  10         19  
  10         573  
8 10     10   54 use Exporter qw/ import /;
  10         20  
  10         262  
9 10     10   49 use Function::Parameters qw/ :strict /;
  10         17  
  10         65  
10              
11 10     10   4682 use Time::C::Util qw/ get_fmt_tok get_locale /;
  10         25  
  10         484  
12 10     10   54 use Time::P;
  10         21  
  10         1272  
13              
14             our @EXPORT = qw/ strftime /;
15              
16              
17             my %formatter; %formatter = (
18             '%A' => fun ($t, $l) { get_locale(weekdays => $l)->[$t->day_of_week() % 7]; },
19             '%a' => fun ($t, $l) { get_locale(weekdays_abbr => $l)->[$t->day_of_week() % 7]; },
20             '%B' => fun ($t, $l) { get_locale(months => $l)->[$t->month() - 1]; },
21             '%b' => fun ($t, $l) { get_locale(months_abbr => $l)->[$t->month() - 1]; },
22             '%C' => fun ($t, $l) { sprintf '%02d', substr($t->year, -4, 2) + 0; },
23             '%-C' => fun ($t, $l) { substr($t->year, -4, 2) + 0; },
24             '%c' => fun ($t, $l) { strftime($t, get_locale(datetime => $l), locale => $l); },
25             '%D' => fun ($t, $l) { strftime($t, '%m/%d/%y', locale => $l); },
26             '%d' => fun ($t, $l) { sprintf '%02d', $t->day; },
27             '%-d' => fun ($t, $l) { $t->day; },
28             '%EC' => fun ($t, $l) { strftime($t, _fmt_era(C => $t, get_locale(era => $l)), locale => $l); },
29             '%Ec' => fun ($t, $l) { strftime($t, get_locale(era_datetime => $l), locale => $l); },
30             '%EX' => fun ($t, $l) { strftime($t, get_locale(era_time => $l), locale => $l); },
31             '%Ex' => fun ($t, $l) { strftime($t, get_locale(era_date => $l), locale => $l); },
32             '%EY' => fun ($t, $l) { strftime($t, _fmt_era(Y => $t, get_locale(era => $l)), locale => $l); },
33             '%Ey' => fun ($t, $l) { strftime($t, _fmt_era(y => $t, get_locale(era => $l)), locale => $l); },
34             '%e' => fun ($t, $l) { sprintf '%2d', $t->day; },
35             '%-e' => fun ($t, $l) { $t->day; },
36             '%F' => fun ($t, $l) { strftime($t, '%Y-%m-%d', locale => $l); },
37             '%G' => fun ($t, $l) { sprintf '%04d', $t->clone->day_of_week(4)->year; },
38             '%-G' => fun ($t, $l) { $t->clone->day_of_week(4)->year; },
39             '%g' => fun ($t, $l) { sprintf '%02d', substr($formatter{'%G'}->($t, $l), -2); },
40             '%-g' => fun ($t, $l) { substr($formatter{'%G'}->($t, $l), -2) + 0; },
41             '%H' => fun ($t, $l) { sprintf '%02d', $t->hour; },
42             '%-H' => fun ($t, $l) { $t->hour; },
43             '%h' => fun ($t, $l) { $formatter{'%b'}->($t, $l); },
44             '%I' => fun ($t, $l) { my $I = $t->hour % 12; sprintf '%02d', $I ? $I : 12; },
45             '%-I' => fun ($t, $l) { my $I = $t->hour % 12; $I ? $I : 12; },
46             '%j' => fun ($t, $l) { sprintf '%03d', $t->day_of_year; },
47             '%-j' => fun ($t, $l) { $t->day_of_year; },
48             '%k' => fun ($t, $l) { sprintf '%2d', $t->hour; },
49             '%-k' => fun ($t, $l) { $t->hour; },
50             '%l' => fun ($t, $l) { my $I = $t->hour % 12; sprintf '%2d', $I ? $I : 12; },
51             '%-l' => fun ($t, $l) { my $I = $t->hour % 12; $I ? $I : 12; },
52             '%M' => fun ($t, $l) { sprintf '%02d', $t->minute; },
53             '%-M' => fun ($t, $l) { $t->minute; },
54             '%m' => fun ($t, $l) { sprintf '%02d', $t->month; },
55             '%-m' => fun ($t, $l) { $t->month; },
56             '%n' => fun ($t, $l) { "\n"; },
57             '%OC' => fun ($t, $l) {
58             my @d = @{ get_locale(digits => $l) };
59             my $n = $formatter{'%C'}->($t, $l);
60             return $n if @d == 0;
61             croak "Not enough digits in alt_digits for $l to represent %OC." if @d < 100;
62             return $d[$n];
63             },
64             '%Od' => fun ($t, $l) {
65             my @d = @{ get_locale(digits => $l) };
66             my $n = $formatter{'%d'}->($t, $l);
67             return $n if @d == 0;
68             croak "Not enough digits in alt_digits for $l to represent %Od." if @d < 32;
69             return $d[$n];
70             },
71             '%Oe' => fun ($t, $l) {
72             my @d = @{ get_locale(digits => $l) };
73             my $n = $formatter{'%e'}->($t, $l);
74             return $n if @d == 0;
75             croak "Not enough digits in alt_digits for $l to represent %Oe." if @d < 32;
76             return $d[$n];
77             },
78             '%OH' => fun ($t, $l) {
79             my @d = @{ get_locale(digits => $l) };
80             my $n = $formatter{'%H'}->($t, $l);
81             return $n if @d == 0;
82             croak "Not enough digits in alt_digits for $l to represent %OH." if @d < 24;
83             return $d[$n];
84             },
85             '%OI' => fun ($t, $l) {
86             my @d = @{ get_locale(digits => $l) };
87             my $n = $formatter{'%I'}->($t, $l);
88             return $n if @d == 0;
89             croak "Not enough digits in alt_digits for $l to represent %OI." if @d < 13;
90             return$d[$n];
91             },
92             '%Om' => fun ($t, $l) {
93             my @d = @{ get_locale(digits => $l) };
94             my $n = $formatter{'%m'}->($t, $l);
95             return $n if @d == 0;
96             croak "Not enough digits in alt_digits for $l to represent %Om." if @d < 13;
97             return $d[$n];
98             },
99             '%OM' => fun ($t, $l) {
100             my @d = @{ get_locale(digits => $l) };
101             my $n = $formatter{'%M'}->($t, $l);
102             return $n if @d == 0;
103             croak "Not enough digits in alt_digits for $l to represent %OM." if @d < 60;
104             return $d[$n];
105             },
106             '%Op' => fun ($t, $l) { $formatter{'%p'}->($t, $l); }, # one %c spec in my_MM locale erroneously says %Op instead of %p
107             '%OS' => fun ($t, $l) {
108             my @d = @{ get_locale(digits => $l) };
109             my $n = $formatter{'%S'}->($t, $l);
110             return $n if @d == 0;
111             croak "Not enough digits in alt_digits for $l to represent %OS." if @d < 60;
112             return $d[$n];
113             },
114             '%OU' => fun ($t, $l) {
115             my @d = @{ get_locale(digits => $l) };
116             my $n = $formatter{'%U'}->($t, $l);
117             return $n if @d == 0;
118             croak "Not enough digits in alt_digits for $l to represent %OU." if @d < 54;
119             return @d > 31 ? $d[$n] : $n;
120             },
121             '%Ou' => fun ($t, $l) {
122             my @d = @{ get_locale(digits => $l) };
123             my $n = $formatter{'%u'}->($t, $l);
124             return $n if @d == 0;
125             croak "Not enough digits in alt_digits for $l to represent %Ou." if @d < 8;
126             return $d[$n];
127             },
128             '%OV' => fun ($t, $l) {
129             my @d = @{ get_locale(digits => $l) };
130             my $n = $formatter{'%V'}->($t, $l);
131             return $n if @d == 0;
132             croak "Not enough digits in alt_digits for $l to represent %OV." if @d < 54;
133             return $d[$n];
134             },
135             '%OW' => fun ($t, $l) {
136             my @d = @{ get_locale(digits => $l) };
137             my $n = $formatter{'%W'}->($t, $l);
138             return $n if @d == 0;
139             croak "Not enough digits in alt_digits for $l to represent %OW." if @d < 54;
140             return @d > 31 ? $d[$n] : $n;
141             },
142             '%Ow' => fun ($t, $l) {
143             my @d = @{ get_locale(digits => $l) };
144             my $n = $formatter{'%w'}->($t, $l);
145             return $n if @d == 0;
146             croak "Not enough digits in alt_digits for $l to represent %Ow." if @d < 7;
147             return $d[$n];
148             },
149             '%Oy' => fun ($t, $l) {
150             my @d = @{ get_locale(digits => $l) };
151             my $n = $formatter{'%y'}->($t, $l);
152             return $n if @d == 0;
153             croak "Not enough digits in alt_digits for $l to represent %Oy." if @d < 100;
154             return $d[$n];
155             },
156             '%P' => fun ($t, $l) { $formatter{'%p'}->($t, $l); }, # a few %r specs in some locales erroneously say %P instead of %p (wal_ET, ur_PK, pa_PK, iw_IL, he_IL, en_GB, dv_MV, cy_GB)
157             '%p' => fun ($t, $l) { get_locale(am_pm => $l)->[not $t->hour < 12]; },
158             '%X' => fun ($t, $l) { strftime($t, get_locale(time => $l), locale => $l); },
159             '%x' => fun ($t, $l) { strftime($t, get_locale(date => $l), locale => $l); },
160             '%R' => fun ($t, $l) { strftime($t, '%H:%M', locale => $l); },
161             '%r' => fun ($t, $l) { strftime($t, get_locale(time_ampm => $l), locale => $l); },
162             '%S' => fun ($t, $l) { sprintf '%02d', $t->second; },
163             '%-S' => fun ($t, $l) { $t->second; },
164             '%s' => fun ($t, $l) { $t->epoch; },
165             '%T' => fun ($t, $l) { strftime($t, '%H:%M:%S', locale => $l); },
166             '%t' => fun ($t, $l) { "\t"; },
167             '%U' => fun ($t, $l) {
168             my $t2 = $t->clone->day_of_year(1);
169             $t2->day++ while $t2->day_of_week != 7;
170             if ($t2->day_of_year > $t->day_of_year) { return "00"; }
171             sprintf '%02d', int(($t->day_of_year - $t2->day_of_year) / 7) + 1;
172             },
173             '%-U' => fun ($t, $l) {
174             my $t2 = $t->clone->day_of_year(1);
175             $t2->day++ while $t2->day_of_week != 7;
176             if ($t2->day_of_year > $t->day_of_year) { return "0"; }
177             int(($t->day_of_year - $t2->day_of_year) / 7) + 1;
178             },
179             '%u' => fun ($t, $l) { $t->day_of_week; },
180             '%V' => fun ($t, $l) { sprintf '%02d', $t->week; },
181             '%-V' => fun ($t, $l) { $t->week; },
182             '%v' => fun ($t, $l) { strftime($t, '%e-%b-%Y', locale => $l); },
183             '%W' => fun ($t, $l) {
184             my $t2 = $t->clone->day_of_year(1);
185             $t2->day++ while $t2->day_of_week != 1;
186             if ($t2->day_of_year > $t->day_of_year) { return "00"; }
187             sprintf '%02d', int(($t->day_of_year - $t2->day_of_year) / 7) + 1;
188             },
189             '%-W' => fun ($t, $l) {
190             my $t2 = $t->clone->day_of_year(1);
191             $t2->day++ while $t2->day_of_week != 1;
192             if ($t2->day_of_year > $t->day_of_year) { return "0"; }
193             int(($t->day_of_year - $t2->day_of_year) / 7) + 1;
194             },
195             '%w' => fun ($t, $l) { $t->day_of_week == 7 ? 0 : $t->day_of_week; },
196             '%Y' => fun ($t, $l) { sprintf '%04d', $t->year; },
197             '%-Y' => fun ($t, $l) { $t->year; },
198             '%y' => fun ($t, $l) { sprintf '%02d', substr $t->year, -2; },
199             '%-y' => fun ($t, $l) { substr $t->year, -2; },
200             '%Z' => fun ($t, $l) { $t->tz; },
201             '%z' => fun ($t, $l) { my $z = $t->offset; sprintf '%s%02s%02s', ($z > 0 ? '-' : '+'), (($z - ($z % 60)) / 60), ($z % 60); },
202             '%%' => fun ($t, $l) { '%'; },
203             );
204              
205              
206 351 50 66 351 1 1079 fun strftime ($t, $fmt, :$locale = 'C') {
  351 50       1114  
  351 100       910  
  351 50       899  
  351         965  
  351         541  
207 351         544 my $str = '';
208 351         525 my $pos = 0;
209 351         1080 while (defined(my $tok = get_fmt_tok($fmt, $pos))) {
210 2118 100       5588 if (exists $formatter{$tok}) {
    50          
211 1065   50     2467 $str .= $formatter{$tok}->($t, $locale) // '';
212             } elsif ($tok =~ m/^%/) {
213 0         0 croak "Unsupported format specifier: $tok"
214             } else {
215 1053         2695 $str .= $tok;
216             }
217             }
218              
219 351         1149 return $str;
220             }
221              
222 3 50   3   10 fun _fmt_era ($E, $t, $eras) {
  3 50       9  
  3         9  
  3         7  
223 3         6 foreach my $era (grep defined, @{ $eras }) {
  3         15  
224 3         23 my @fields = split /:/, $era;
225 3         14 my %s = strptime($fields[2], "%-Y/%m/%d");
226 3 50       12 $s{year}++ if $s{year} < 1;
227 3 50       12 if ($t->year > $s{year}) {
    0          
228 3 100       13 return $fields[5] if $E eq 'Y';
229 2 100       14 return $fields[4] if $E eq 'C';
230 1 50       7 return $fields[1] + $t->year - $s{year} if $E eq 'y';
231             } elsif ($t->year == $s{year}) {
232 0           require Time::C;
233 0           my $s = Time::C->mktime(%s);
234 0 0         if ($t->epoch >= $s->epoch) {
235 0 0         return $fields[5] if $E eq 'Y';
236 0 0         return $fields[4] if $E eq 'C';
237 0 0         return $fields[1] + $t->year - $s{year} if $E eq 'y';
238             }
239             }
240             }
241 0           return "%$E";
242             }
243              
244             1;
245              
246             __END__