File Coverage

blib/lib/Time/Normalize.pm
Criterion Covered Total %
statement 205 223 91.9
branch 158 184 85.8
condition 42 60 70.0
subroutine 26 29 89.6
pod 15 18 83.3
total 446 514 86.7


line stmt bran cond sub pod time code
1             =for gpg
2             -----BEGIN PGP SIGNED MESSAGE-----
3             Hash: SHA1
4            
5             =head1 NAME
6            
7             Time::Normalize - Convert time and date values into standardized components.
8            
9             =head1 VERSION
10            
11             This is version 0.09 of Time::Normalize, April 23, 2014.
12            
13             =cut
14            
15 10     10   24273 use strict;
  10         24  
  10         766  
16             package Time::Normalize;
17             $Time::Normalize::VERSION = '0.09';
18 10     10   59 use Carp;
  10         26  
  10         795  
19            
20 10     10   80 use Exporter;
  10         18  
  10         510  
21 10     10   58 use vars qw/@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS/;
  10         17  
  10         55247  
22             @ISA = qw/Exporter/;
23             @EXPORT = qw/normalize_hms normalize_time normalize_ymd normalize_gmtime
24             normalize_month normalize_year normalize_ym
25             normalize_ymd3 normalize_ym3
26             normalize_ymdhms normalize_rct
27             /;
28             @EXPORT_OK = (@EXPORT, qw(mon_name mon_abbr day_name day_abbr days_in is_leap));
29             %EXPORT_TAGS = (all => \@EXPORT_OK);
30            
31             # Is POSIX available?
32             eval {require POSIX };
33             my $have_posix = $@? 0 : 1;
34            
35             # Delay loading Carp until needed
36             sub _croak
37             {
38 91     91   584 require Carp;
39 91         13828 goto &Carp::croak;
40             }
41            
42             # Most error messages in this module look very similar.
43             # This standardizes them:
44             sub _bad
45             {
46 61     61   109 my ($what, $value) = @_;
47 61 100       153 $value = '(undefined)' if !defined $value;
48 61         220 _croak qq{Time::Normalize: Invalid $what: "$value"};
49             }
50            
51             # Current locale.
52             my $locale;
53            
54             # Month names; Month names abbrs, Weekday names, Weekday name abbrs.
55             # *All Mixed-Case!*
56             our (@Mon_Name, @Mon_Abbr, @Day_Name, @Day_Abbr);
57             # Lookup: string-month => numeric-month (also string-day => numeric-day)
58             our %number_of;
59             # We need english-only names to parse R::C::t's 'mail' format.
60             my $mail_month_number;
61             our $use_mail_months;
62            
63             # Current year and century. Used for guessing century of two-digit years.
64             my $current_year = (localtime)[5] + 1900;
65             my ($current_century, $current_yy) = $current_year =~ /(\d\d)(\d\d)/;
66            
67             # Number of days in each (1-based) month (except February).
68             my @num_days_in = qw(0 31 29 31 30 31 30 31 31 30 31 30 31);
69            
70             sub days_in
71             {
72 152 100   152 1 1675 _croak "Too few arguments to days_in" if @_ < 2;
73 151 100       307 _croak "Too many arguments to days_in" if @_ > 2;
74 150         299 my ($m,$y) = @_;
75 150 100       557 _croak qq{Non-integer month "$m" for days_in} if $m !~ /\A\s* \d+ \s*\z/x;
76 149 50 33     680 _bad('month', $m) if $m < 1 || $m > 12;
77 149 100       742 return $num_days_in[$m] if $m != 2;
78            
79             # February
80 16 100       40 return is_leap($y)? 29 : 28;
81             }
82            
83             # Is a leap year?
84             sub is_leap
85             {
86 24 100   24 1 1097 _croak "Too few arguments to is_leap" if @_ < 1;
87 23 100       58 _croak "Too many arguments to is_leap" if @_ > 1;
88 22         33 my $year = shift;
89 22   66     244 return !($year%4) && ( ($year%100) || !($year%400) );
90             }
91            
92             # Quickie function to pad a number with a leading 0.
93 486 100   486   1557 sub _lead0 { $_[0] > 9? $_[0]+0 : '0'.($_[0]+0)}
94            
95             # Compute day of week, using Zeller's congruence
96             sub _dow
97             {
98 95     95   150 my ($Y, $M, $D) = @_;
99            
100 95         138 $M -= 2;
101 95 100       205 if ($M < 1)
102             {
103 17         20 $M += 12;
104 17         28 $Y--;
105             }
106 95         215 my $C = int($Y/100);
107 95         132 $Y %= 100;
108            
109 95         345 return (int((26*$M - 2)/10) + $D + $Y + int($Y/4) + int($C/4) - 2*$C) % 7;
110             }
111            
112            
113             # Internal function to initialize locale info.
114             sub _setup_locale
115             {
116             # Do nothing if locale has not changed since %names was set up.
117 392     392   450 my $locale_in_use;
118 392 50       1707 $locale_in_use = $have_posix? POSIX::setlocale(POSIX::LC_TIME()) : 'no posix; use defaults';
119 392 50       835 $locale_in_use = q{} if !defined $locale_in_use;
120            
121             # No changes needed
122 392 100 66     1986 return if defined $locale && $locale eq $locale_in_use;
123            
124 8         21 $locale = $locale_in_use;
125            
126             eval
127 8         17 {
128 8         78 require I18N::Langinfo;
129 8         304 I18N::Langinfo->import ('langinfo');
130 8         253 @Mon_Name = map langinfo($_), (
131             I18N::Langinfo::MON_1(),
132             I18N::Langinfo::MON_2(),
133             I18N::Langinfo::MON_3(),
134             I18N::Langinfo::MON_4(),
135             I18N::Langinfo::MON_5(),
136             I18N::Langinfo::MON_6(),
137             I18N::Langinfo::MON_7(),
138             I18N::Langinfo::MON_8(),
139             I18N::Langinfo::MON_9(),
140             I18N::Langinfo::MON_10(),
141             I18N::Langinfo::MON_11(),
142             I18N::Langinfo::MON_12(),
143             );
144 8         237 @Mon_Abbr = map langinfo($_), (
145             I18N::Langinfo::ABMON_1(),
146             I18N::Langinfo::ABMON_2(),
147             I18N::Langinfo::ABMON_3(),
148             I18N::Langinfo::ABMON_4(),
149             I18N::Langinfo::ABMON_5(),
150             I18N::Langinfo::ABMON_6(),
151             I18N::Langinfo::ABMON_7(),
152             I18N::Langinfo::ABMON_8(),
153             I18N::Langinfo::ABMON_9(),
154             I18N::Langinfo::ABMON_10(),
155             I18N::Langinfo::ABMON_11(),
156             I18N::Langinfo::ABMON_12(),
157             );
158 8         131 @Day_Name = map langinfo($_), (
159             I18N::Langinfo::DAY_1(),
160             I18N::Langinfo::DAY_2(),
161             I18N::Langinfo::DAY_3(),
162             I18N::Langinfo::DAY_4(),
163             I18N::Langinfo::DAY_5(),
164             I18N::Langinfo::DAY_6(),
165             I18N::Langinfo::DAY_7(),
166             );
167 8         234 @Day_Abbr = map langinfo($_), (
168             I18N::Langinfo::ABDAY_1(),
169             I18N::Langinfo::ABDAY_2(),
170             I18N::Langinfo::ABDAY_3(),
171             I18N::Langinfo::ABDAY_4(),
172             I18N::Langinfo::ABDAY_5(),
173             I18N::Langinfo::ABDAY_6(),
174             I18N::Langinfo::ABDAY_7(),
175             );
176             # make the month arrays 1-based:
177 8         29 for (\@Mon_Name, \@Mon_Abbr)
178             {
179 16         63 unshift @$_, 'n/a';
180             }
181             };
182 8 50       49 if ($@) # If internationalization didn't work for some reason, go with English.
183             {
184 0         0 @Mon_Name = qw(n/a January February March April May June July August September October November December);
185 0         0 @Mon_Abbr = map substr($_,0,3), @Mon_Name;
186 0         0 @Day_Name = qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday);
187 0         0 @Day_Abbr = map substr($_,0,3), @Day_Name;
188             }
189            
190 8         24 %number_of = ();
191 8         92 for (1..12)
192             {
193 96         360 $number_of{uc $Mon_Name[$_]} = $number_of{uc $Mon_Abbr[$_]} = $_;
194             }
195             # This module doesn't use reverse DOW lookups, but someone might want it.
196 8         26 for (0..6)
197             {
198 56         245 $number_of{uc $Day_Name[$_]} = $number_of{uc $Day_Abbr[$_]} = $_;
199             }
200             }
201            
202             sub _init_mail_months
203             {
204 1     1   5 my @abbrs = qw(n/a Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
205 1         2 %$mail_month_number = ();
206 1         3 for (1..12)
207             {
208 12         20 $mail_month_number->{uc $abbrs[$_]} = $_;
209             }
210             }
211            
212             my %ap_from_ampm = (a => 'a', am => 'a', 'a.m.' => 'a', p => 'p', pm => 'p', 'p.m.' => 'p');
213             sub normalize_hms
214             {
215 73 100   73 1 48719 _croak "Too few arguments to normalize_hms" if @_ < 2;
216 72 100       168 _croak "Too many arguments to normalize_hms" if @_ > 4;
217 71         121 my ($inh, $inm, $ins, $ampm) = @_;
218 71         86 my ($hour24, $hour12, $minute, $second);
219 0         0 my $ap;
220            
221             # First, normalize am/pm indicator
222 71 100 66     301 if (defined $ampm && length $ampm)
223             {
224 43         119 $ap = $ap_from_ampm{lc $ampm};
225 43 100       111 _bad ('am/pm indicator', $ampm) if !defined $ap;
226             }
227            
228             # Check that the hour is in bounds
229 67 100       312 _bad('hour', $inh) if $inh !~ /\A\s* \d+ \s*\z/x;
230 65 100       131 if (defined $ap)
231             {
232             # Range is from 1 to 12
233 39 100 100     177 _bad('hour', $inh) if $inh < 1 || $inh > 12;
234 36         55 $hour12 = 0 + $inh;
235 36 100       70 $hour24 = $hour12 == 12? 0 : $hour12;
236 36 100       92 $hour24 += 12 if $ap eq 'p';
237             }
238             else
239             {
240             # Range is from 0 to 23
241 26 100 66     170 _bad('hour', $inh) if $inh < 0 || $inh > 23;
242 24         37 $hour24 = $inh;
243 24 100       74 $hour12 = $hour24 > 12? $hour24 - 12 : $hour24 == 0? 12 : 0 + $hour24;
    100          
244 24 100       57 $ap = $hour24 < 12? 'a' : 'p';
245             }
246 60         118 $hour24 = _lead0($hour24);
247            
248             # Minute check: Numeric, range 0 to 59.
249 60 100 66     485 _bad('minute', $inm) if $inm !~ /\A\s* \d+ \s*\z/x || $inm < 0 || $inm > 59;
      100        
250 57         97 $minute = _lead0($inm);
251            
252             # Second check: Numeric, range 0 to 59.
253 57 100 100     228 if (defined $ins && length $ins) # second is optional!
254             {
255 44 100 66     330 _bad('second', $ins) if $ins !~ /\A\s* \d+ \s*\z/x || $ins < 0 || $ins > 59;
      100        
256 41         67 $second = $ins;
257             }
258             else
259             {
260 13         22 $second = 0;
261             }
262 54         110 $second = _lead0($second);
263            
264 54         112 my $sec_since_midnight = $second + 60 * ($minute + 60 * $hour24);
265 54 100       374 return wantarray? ($hour24, $minute, $second, $hour12, $ap, $sec_since_midnight)
266             : {
267             h12 => $hour12,
268             h24 => $hour24,
269             hour => $hour24,
270             min => $minute,
271             sec => $second,
272             ampm => $ap,
273             since_midnight => $sec_since_midnight,
274             };
275             }
276            
277             sub normalize_ymd
278             {
279 118 100   118 1 55460 _croak "Too few arguments to normalize_ymd" if @_ < 3;
280 117 100       431 _croak "Too many arguments to normalize_ymd" if @_ > 3;
281 116         189 my ($iny, $inm, $ind) = @_;
282 116         146 my ($year, $month, $day);
283            
284 116         218 _setup_locale();
285            
286             # First, check year.
287 116         246 $year = normalize_year($iny);
288            
289             # Decode the month.
290 113         218 $month = normalize_month($inm);
291            
292             # Day: Numeric and within range for the given month/year
293 108 100 33     910 _bad('day', $ind)
      66        
294             if $ind !~ /\A\s* \d+ \s*\z/x || $ind < 1 || $ind > days_in($month, $year);
295 95         203 $day = _lead0($ind);
296            
297 95         238 my $dow = _dow($year, $month, $day);
298            
299 95 100       720 return ($year, $month, $day,
300             $dow, $Day_Name[$dow], $Day_Abbr[$dow],
301             $Mon_Name[$month], $Mon_Abbr[$month])
302             if wantarray;
303            
304             return
305             {
306 22         254 year => $year, mon => $month, day => $day,
307             dow => $dow,
308             dow_name => $Day_Name[$dow],
309             dow_abbr => $Day_Abbr[$dow],
310             mon_name => $Mon_Name[$month],
311             mon_abbr => $Mon_Abbr[$month],
312             };
313             }
314            
315             sub normalize_ymdhms
316             {
317 14 100   14 1 29113 _croak "Too few arguments to normalize_ymdhms" if @_ < 5;
318 13 100       41 _croak "Too many arguments to normalize_ymdhms" if @_ > 7;
319 12         29 my ($iny, $inmon, $ind, $inhr, $inmin, $insec, $inampm) = @_;
320            
321 12         32 my $date = normalize_ymd($iny, $inmon, $ind);
322 12         35 my $time = normalize_hms($inhr, $inmin, $insec, $inampm);
323            
324 12 100       87 return ($date->{year}, $date->{mon}, $date->{day},
325             $time->{hour}, $time->{min}, $time->{sec})
326             if wantarray;
327            
328 6         94 return { %$date, %$time };
329             }
330            
331             # Normalize values returned from Regexp::Common::time
332             sub normalize_rct
333             {
334 15     15 1 19511 my ($type, @values) = @_;
335 15         29 $type =~ tr/24//d;
336 15         28 $type = lc $type;
337            
338             # First element is "whole match", which is useless here.
339 15         16 shift @values;
340            
341 15         16 my ($yr, $mo, $dy, $hr, $mn, $sc, $tz, $am);
342            
343             # How we proceed depends on which pattern captured the values.
344 15 100       94 if ($type eq 'iso')
    100          
    100          
    100          
    100          
    100          
    100          
345             {
346 2         3 ($yr, $mo, $dy, $hr, $mn, $sc) = @values;
347 2         4 return normalize_ymdhms($yr, $mo, $dy, $hr, $mn, $sc);
348             }
349             elsif ($type eq 'mail')
350             {
351 2         6 ($dy, $mo, $yr, $hr, $mn, $sc) = @values;
352 2         3 local $use_mail_months = 1;
353 2         4 return normalize_ymdhms($yr, $mo, $dy, $hr, $mn, $sc);
354             }
355             elsif ($type eq 'american')
356             {
357 2         4 ($mo, $dy, $yr) = @values;
358 2         7 $yr =~ s/\A'//; # "american" year might have leading apostrophe
359 2         5 return normalize_ymd($yr, $mo, $dy);
360             }
361             elsif ($type eq 'ymd')
362             {
363 2         3 ($yr, $mo, $dy) = @values;
364 2         5 return normalize_ymd($yr, $mo, $dy);
365             }
366             elsif ($type eq 'mdy')
367             {
368 2         4 ($mo, $dy, $yr) = @values;
369 2         4 return normalize_ymd($yr, $mo, $dy);
370             }
371             elsif ($type eq 'dmy')
372             {
373 2         4 ($dy, $mo, $yr) = @values;
374 2         4 return normalize_ymd($yr, $mo, $dy);
375             }
376             elsif ($type eq 'hms')
377             {
378 2         4 ($hr, $mn, $sc, $am) = @values;
379 2         6 return normalize_hms($hr, $mn, $sc, $am);
380             }
381             else
382             {
383 1         6 _croak qq{Unknown Regexp::Common::time pattern: "$type"};
384             }
385             }
386            
387             # Like normalize_ymd, but only returns the Y, M, and D values.
388             # So you can do: $date = join '/' => normalize_ymd3 ($input_yr, $input_mo, $input_dy);
389             sub normalize_ymd3
390             {
391 3 100   3 0 4968 _croak "Too few arguments to normalize_ymd3" if @_ < 3;
392 2 100       9 _croak "Too many arguments to normalize_ymd3" if @_ > 3;
393 1         5 my @ymd = normalize_ymd(@_);
394 1         7 return @ymd[0,1,2];
395             }
396            
397             # Like normalize_ym, but only returns the Y, M, and D values.
398             # So you can do: $date = join '/' => normalize_ym3 ($input_yr, $input_mo);
399             sub normalize_ym3
400             {
401 0 0   0 0 0 _croak "Too few arguments to normalize_ym3" if @_ < 3;
402 0 0       0 _croak "Too many arguments to normalize_ym3" if @_ > 3;
403 0         0 my @ymd = normalize_ym(@_);
404 0         0 return @ymd[0,1,2];
405             }
406            
407             # Like normalize_hms, but only returns the H, M, and S values.
408             # So you can do: $time = join ':' => normalize_hms3 ($input_hr, $input_min, $input_sec);
409             sub normalize_hms3
410             {
411 0 0   0 0 0 _croak "Too few arguments to normalize_hms3" if @_ < 2;
412 0 0       0 _croak "Too many arguments to normalize_hms3" if @_ > 4;
413 0         0 my @hms = normalize_hms(@_);
414 0         0 return @hms[0,1,2];
415             }
416            
417             sub normalize_month
418             {
419 238 100   238 1 63649 _croak "Too few arguments to normalize_month" if @_ < 1;
420 237 100       565 _croak "Too many arguments to normalize_month" if @_ > 1;
421 236         396 _setup_locale;
422 236         330 my $inm = shift;
423 236         409 my $month;
424            
425 236 100       446 _bad('month', $inm) if !defined $inm;
426            
427             # Decode the month.
428 235 100       951 if ($inm =~ /\A\s* \d+ \s*\z/x)
429             {
430             # Numeric. Simple 1-12 check.
431 136 100 100     606 _bad('month', $inm) if $inm < 1 || $inm > 12;
432 130         203 $month = $inm;
433             }
434             else
435             {
436             # Might be a character month name
437 99 100       179 if ($use_mail_months)
438             {
439 2 100       7 _init_mail_months if !defined $mail_month_number;
440 2         3 $month = $mail_month_number->{uc $inm};
441             }
442             else
443             {
444 97         242 $month = $number_of{uc $inm};
445             }
446 99 100       205 _bad('month', $inm) if !defined $month;
447             }
448 220         421 return _lead0($month);
449             }
450            
451             sub normalize_year
452             {
453 161 50   161 1 9416 _croak "Too few arguments to normalize_year" if @_ < 1;
454 161 50       367 _croak "Too many arguments to normalize_year" if @_ > 1;
455 161         251 my $iny = shift;
456            
457 161 100       658 if ($iny =~ /\A\s* \d{4} \s*\z/x)
458             {
459             # Four-digit year. Good.
460 124         554 return sprintf '%04d', $iny+0;
461             }
462            
463 37 100       157 if ($iny =~ /\A\s* \d{2} \s*\z/x)
464             {
465             # Two-digit year. Guess the century.
466            
467             # If curr yy is <= 50, current century numbers are 0 - yy+50
468 28 50       71 if ($current_yy <= 50)
469             {
470 28 100       115 return $iny + 100 * ($iny <= $current_yy+50? $current_century : $current_century-1);
471             }
472             # If curr yy is > 50, current century numbers are yy-50 - 99
473             else
474             {
475 0 0       0 return $iny + 100 * ($iny <= $current_yy-50? $current_century+1 : $current_century);
476             }
477             }
478            
479 9         26 _bad('year', $iny);
480             }
481            
482             sub normalize_ym
483             {
484 38 100   38 1 64699 _croak "Too few arguments to normalize_ym" if @_ < 2;
485 37 100       95 _croak "Too many arguments to normalize_ym" if @_ > 2;
486 36         54 my ($iny, $inm) = @_;
487            
488 36         81 my ($year, $month) = (normalize_year($iny), normalize_month($inm));
489 28         64 my $day = days_in ($month, $year);
490 28         68 return normalize_ymd($year, $month, $day);
491             }
492            
493            
494             sub normalize_time
495             {
496 0 0   0 1 0 _croak "Too many arguments to normalize_time" if @_ > 1;
497 0 0 0     0 _bad ('time', $_[0]) if @_ == 1 && $_[0] !~ /\A\s* \d+ \s*\z/x;
498 0 0       0 my @t = @_? localtime($_[0]) : localtime;
499 0         0 return _normalize_gm_and_local_times(@t);
500             }
501            
502             sub normalize_gmtime
503             {
504 2 50   2 1 843 _croak "Too many arguments to normalize_gmtime" if @_ > 1;
505 2 50 33     29 _bad ('time', $_[0]) if @_ == 1 && $_[0] !~ /\A\s* \d+ \s*\z/x;
506 2 50       31 my @t = @_? gmtime($_[0]) : gmtime;
507 2         8 return _normalize_gm_and_local_times(@t);
508             }
509            
510             sub _normalize_gm_and_local_times
511             {
512 2     2   6 my @t = @_;
513            
514 2         7 _setup_locale();
515            
516 2 100       6 if (wantarray)
517             {
518 1         5 my ($h24, $min, $sec, $h12, $ap, $ssm) = normalize_hms ($t[2], $t[1], $t[0]);
519 1         5 my ($y4, $mon, $day, $dow, $dow_name, $dow_abbr, $mon_name, $mon_abbr)
520             = normalize_ymd ($t[5] + 1900, $t[4] + 1, $t[3]);
521            
522 1         10 return ($sec, $min, $h24,
523             $day, $mon, $y4,
524             $dow, $t[7], $t[8],
525             $h12, $ap, $ssm,
526             $dow_name, $dow_abbr,
527             $mon_name, $mon_abbr);
528             }
529            
530             # Scalar. Return hashref.
531 1         4 my $hms_href = normalize_hms ($t[2], $t[1], $t[0]);
532 1         11 my $ymd_href = normalize_ymd ($t[5] + 1900, $t[4] + 1, $t[3]);
533 1         15 return { %$hms_href, %$ymd_href, yday => $t[7], isdst => $t[8] };
534             }
535            
536             sub mon_name
537             {
538 17 100   17 1 4759 _croak "Too many arguments to mon_name" if @_ > 1;
539 16 100       38 _croak "Too few arguments to mon_name" if @_ < 1;
540 15         20 my $mon = shift;
541 15 100       73 _croak qq{Non-integer month "$mon" for mon_name} if $mon !~ /\A\s* \d+ \s*\z/x;
542 14 100 100     69 _bad('month', $mon) if $mon < 1 || $mon > 12;
543            
544 12         22 _setup_locale;
545 12         51 return $Mon_Name[$mon];
546             }
547            
548             sub mon_abbr
549             {
550 17 100   17 1 1976 _croak "Too many arguments to mon_abbr" if @_ > 1;
551 16 100       36 _croak "Too few arguments to mon_abbr" if @_ < 1;
552 15         20 my $mon = shift;
553 15 100       67 _croak qq{Non-integer month "$mon" for mon_abbr} if $mon !~ /\A\s* \d+ \s*\z/x;
554 14 100 100     57 _bad('month', $mon) if $mon < 1 || $mon > 12;
555            
556 12         22 _setup_locale;
557 12         51 return $Mon_Abbr[$mon];
558             }
559            
560             sub day_name
561             {
562 11 100   11 1 1581 _croak "Too many arguments to day_name" if @_ > 1;
563 10 100       25 _croak "Too few arguments to day_name" if @_ < 1;
564 9         12 my $day = shift;
565 9 100       46 _croak qq{Non-integer weekday "$day" for day_name} if $day !~ /\A\s* \d+ \s*\z/x;
566 8 100 66     42 _bad('weekday-number', $day) if $day < 0 || $day > 6;
567            
568 7         14 _setup_locale;
569 7         29 return $Day_Name[$day];
570             }
571            
572             sub day_abbr
573             {
574 11 100   11 1 1527 _croak "Too many arguments to day_abbr" if @_ > 1;
575 10 100       24 _croak "Too few arguments to day_abbr" if @_ < 1;
576 9         15 my $day = shift;
577 9 100       49 _croak qq{Non-integer weekday "$day" for day_abbr} if $day !~ /\A\s* \d+ \s*\z/x;
578 8 100 66     46 _bad('weekday-number', $day) if $day < 0 || $day > 6;
579            
580 7         15 _setup_locale;
581 7         35 return $Day_Abbr[$day];
582             }
583            
584             1;
585             __END__