<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># Copyright (c) 1995-2009 Graham Barr. This program is free
# software; you can redistribute it and/or modify it under the same terms
# as Perl itself.

package Date::Format;

use     strict;
use     vars qw(@EXPORT @ISA $VERSION);
require Exporter;

$VERSION = "2.24";
@ISA     = qw(Exporter);
@EXPORT  = qw(time2str strftime ctime asctime);

sub time2str ($;$$)
{
 Date::Format::Generic-&gt;time2str(@_);
}

sub strftime ($\@;$)
{
 Date::Format::Generic-&gt;strftime(@_);
}

sub ctime ($;$)
{
 my($t,$tz) = @_;
 Date::Format::Generic-&gt;time2str("%a %b %e %T %Y\n", $t, $tz); 
}

sub asctime (\@;$)
{
 my($t,$tz) = @_;
 Date::Format::Generic-&gt;strftime("%a %b %e %T %Y\n", $t, $tz); 
}

##
##
##

package Date::Format::Generic;

use vars qw($epoch $tzname);
use Time::Zone;
use Time::Local;

sub ctime
{
 my($me,$t,$tz) = @_;
 $me-&gt;time2str("%a %b %e %T %Y\n", $t, $tz); 
}

sub asctime
{
 my($me,$t,$tz) = @_;
 $me-&gt;strftime("%a %b %e %T %Y\n", $t, $tz); 
}

sub _subs
{
 my $fn;
 $_[1] =~ s/
		%(O?[%a-zA-Z])
	   /
                ($_[0]-&gt;can("format_$1") || sub { $1 })-&gt;($_[0]);
	   /sgeox;

 $_[1];
}

sub strftime 
{
 my($pkg,$fmt,$time);

 ($pkg,$fmt,$time,$tzname) = @_;

 my $me = ref($pkg) ? $pkg : bless [];

 if(defined $tzname)
  {
   $tzname = uc $tzname;

   $tzname = sprintf("%+05d",$tzname)
	unless($tzname =~ /\D/);

   $epoch = timegm(@{$time}[0..5]);

   @$me = gmtime($epoch + tz_offset($tzname) - tz_offset());
  }
 else
  {
   @$me = @$time;
   undef $epoch;
  }

 _subs($me,$fmt);
}

sub time2str
{
 my($pkg,$fmt,$time);

 ($pkg,$fmt,$time,$tzname) = @_;

 my $me = ref($pkg) ? $pkg : bless [], $pkg;

 $epoch = $time;

 if(defined $tzname)
  {
   $tzname = uc $tzname;

   $tzname = sprintf("%+05d",$tzname)
	unless($tzname =~ /\D/);

   $time += tz_offset($tzname);
   @$me = gmtime($time);
  }
 else
  {
   @$me = localtime($time);
  }
 $me-&gt;[9] = $time;
 _subs($me,$fmt);
}

my(@DoW,@MoY,@DoWs,@MoYs,@AMPM,%format,@Dsuf);

@DoW = qw(Sunday Monday Tuesday Wednesday Thursday Friday Saturday);

@MoY = qw(January February March April May June
          July August September October November December);

@DoWs = map { substr($_,0,3) } @DoW;
@MoYs = map { substr($_,0,3) } @MoY;

@AMPM = qw(AM PM);

@Dsuf = (qw(th st nd rd th th th th th th)) x 3;
@Dsuf[11,12,13] = qw(th th th);
@Dsuf[30,31] = qw(th st);

%format = ('x' =&gt; "%m/%d/%y",
           'C' =&gt; "%a %b %e %T %Z %Y",
           'X' =&gt; "%H:%M:%S",
          );

my @locale;
my $locale = "/usr/share/lib/locale/LC_TIME/default";
local *LOCALE;

if(open(LOCALE,"$locale"))
 {
  chop(@locale = &lt;LOCALE&gt;);
  close(LOCALE);

  @MoYs = @locale[0 .. 11];
  @MoY  = @locale[12 .. 23];
  @DoWs = @locale[24 .. 30];
  @DoW  = @locale[31 .. 37];
  @format{"X","x","C"} =  @locale[38 .. 40];
  @AMPM = @locale[41 .. 42];
 }

sub wkyr {
    my($wstart, $wday, $yday) = @_;
    $wday = ($wday + 7 - $wstart) % 7;
    return int(($yday - $wday + 13) / 7 - 1);
}

##
## these 6 formatting routins need to be *copied* into the language
## specific packages
##

my @roman = ('',qw(I II III IV V VI VII VIII IX));
sub roman {
  my $n = shift;

  $n =~ s/(\d)$//;
  my $r = $roman[ $1 ];

  if($n =~ s/(\d)$//) {
    (my $t = $roman[$1]) =~ tr/IVX/XLC/;
    $r = $t . $r;
  }
  if($n =~ s/(\d)$//) {
    (my $t = $roman[$1]) =~ tr/IVX/CDM/;
    $r = $t . $r;
  }
  if($n =~ s/(\d)$//) {
    (my $t = $roman[$1]) =~ tr/IVX/M../;
    $r = $t . $r;
  }
  $r;
}

sub format_a { $DoWs[$_[0]-&gt;[6]] }
sub format_A { $DoW[$_[0]-&gt;[6]] }
sub format_b { $MoYs[$_[0]-&gt;[4]] }
sub format_B { $MoY[$_[0]-&gt;[4]] }
sub format_h { $MoYs[$_[0]-&gt;[4]] }
sub format_p { $_[0]-&gt;[2] &gt;= 12 ?  $AMPM[1] : $AMPM[0] }
sub format_P { lc($_[0]-&gt;[2] &gt;= 12 ?  $AMPM[1] : $AMPM[0]) }

sub format_d { sprintf("%02d",$_[0]-&gt;[3]) }
sub format_e { sprintf("%2d",$_[0]-&gt;[3]) }
sub format_H { sprintf("%02d",$_[0]-&gt;[2]) }
sub format_I { sprintf("%02d",$_[0]-&gt;[2] % 12 || 12)}
sub format_j { sprintf("%03d",$_[0]-&gt;[7] + 1) }
sub format_k { sprintf("%2d",$_[0]-&gt;[2]) }
sub format_l { sprintf("%2d",$_[0]-&gt;[2] % 12 || 12)}
sub format_L { $_[0]-&gt;[4] + 1 }
sub format_m { sprintf("%02d",$_[0]-&gt;[4] + 1) }
sub format_M { sprintf("%02d",$_[0]-&gt;[1]) }
sub format_q { sprintf("%01d",int($_[0]-&gt;[4] / 3) + 1) }
sub format_s { 
   $epoch = timelocal(@{$_[0]}[0..5])
	unless defined $epoch;
   sprintf("%d",$epoch) 
}
sub format_S { sprintf("%02d",$_[0]-&gt;[0]) }
sub format_U { wkyr(0, $_[0]-&gt;[6], $_[0]-&gt;[7]) }
sub format_w { $_[0]-&gt;[6] }
sub format_W { wkyr(1, $_[0]-&gt;[6], $_[0]-&gt;[7]) }
sub format_y { sprintf("%02d",$_[0]-&gt;[5] % 100) }
sub format_Y { sprintf("%04d",$_[0]-&gt;[5] + 1900) }

sub format_Z {
 my $o = tz_local_offset(timelocal(@{$_[0]}[0..5]));
 defined $tzname ? $tzname : uc tz_name($o, $_[0]-&gt;[8]);
}

sub format_z {
 my $t = timelocal(@{$_[0]}[0..5]);
 my $o = defined $tzname ? tz_offset($tzname, $t) : tz_offset(undef,$t);
 sprintf("%+03d%02d", int($o / 3600), int(abs($o) % 3600) / 60);
}

sub format_c { &amp;format_x . " " . &amp;format_X }
sub format_D { &amp;format_m . "/" . &amp;format_d . "/" . &amp;format_y  }      
sub format_r { &amp;format_I . ":" . &amp;format_M . ":" . &amp;format_S . " " . &amp;format_p  }   
sub format_R { &amp;format_H . ":" . &amp;format_M }
sub format_T { &amp;format_H . ":" . &amp;format_M . ":" . &amp;format_S }
sub format_t { "\t" }
sub format_n { "\n" }
sub format_o { sprintf("%2d%s",$_[0]-&gt;[3],$Dsuf[$_[0]-&gt;[3]]) }
sub format_x { my $f = $format{'x'}; _subs($_[0],$f); }
sub format_X { my $f = $format{'X'}; _subs($_[0],$f); }
sub format_C { my $f = $format{'C'}; _subs($_[0],$f); }

sub format_Od { roman(format_d(@_)) }
sub format_Oe { roman(format_e(@_)) }
sub format_OH { roman(format_H(@_)) }
sub format_OI { roman(format_I(@_)) }
sub format_Oj { roman(format_j(@_)) }
sub format_Ok { roman(format_k(@_)) }
sub format_Ol { roman(format_l(@_)) }
sub format_Om { roman(format_m(@_)) }
sub format_OM { roman(format_M(@_)) }
sub format_Oq { roman(format_q(@_)) }
sub format_Oy { roman(format_y(@_)) }
sub format_OY { roman(format_Y(@_)) }

sub format_G { int(($_[0]-&gt;[9] - 315993600) / 604800) }

1;
__END__

=head1 NAME

Date::Format - Date formating subroutines

=head1 SYNOPSIS

	use Date::Format;
	
	@lt = localtime(time);
	
	print time2str($template, time);
	print strftime($template, @lt);
	
	print time2str($template, time, $zone);
	print strftime($template, @lt, $zone);
	
	print ctime(time);
	print asctime(@lt);
	
	print ctime(time, $zone);
	print asctime(@lt, $zone);

=head1 DESCRIPTION

This module provides routines to format dates into ASCII strings. They
correspond to the C library routines C&lt;strftime&gt; and C&lt;ctime&gt;.

=over 4

=item time2str(TEMPLATE, TIME [, ZONE])

C&lt;time2str&gt; converts C&lt;TIME&gt; into an ASCII string using the conversion
specification given in C&lt;TEMPLATE&gt;. C&lt;ZONE&gt; if given specifies the zone
which the output is required to be in, C&lt;ZONE&gt; defaults to your current zone.


=item strftime(TEMPLATE, TIME [, ZONE])

C&lt;strftime&gt; is similar to C&lt;time2str&gt; with the exception that the time is
passed as an array, such as the array returned by C&lt;localtime&gt;.

=item ctime(TIME [, ZONE])

C&lt;ctime&gt; calls C&lt;time2str&gt; with the given arguments using the
conversion specification C&lt;"%a %b %e %T %Y\n"&gt;

=item asctime(TIME [, ZONE])

C&lt;asctime&gt; calls C&lt;time2str&gt; with the given arguments using the
conversion specification C&lt;"%a %b %e %T %Y\n"&gt;

=back

=head1 MULTI-LANGUAGE SUPPORT

Date::Format is capable of formating into several languages by creating
a language specific object and calling methods, see L&lt;Date::Language&gt;

	my $lang = Date::Language-&gt;new('German');
	$lang-&gt;time2str("%a %b %e %T %Y\n", time);

I am open to suggestions on this.

=head1 CONVERSION SPECIFICATION

Each conversion specification  is  replaced  by  appropriate
characters   as   described  in  the  following  list.   The
appropriate  characters  are  determined  by   the   LC_TIME
category of the program's locale.

	%%	PERCENT
	%a	day of the week abbr
	%A	day of the week
	%b	month abbr
	%B 	month
	%c	MM/DD/YY HH:MM:SS
	%C 	ctime format: Sat Nov 19 21:05:57 1994
	%d 	numeric day of the month, with leading zeros (eg 01..31)
	%e 	like %d, but a leading zero is replaced by a space (eg  1..32)
	%D 	MM/DD/YY
	%G	GPS week number (weeks since January 6, 1980)
	%h 	month abbr
	%H 	hour, 24 hour clock, leading 0's)
	%I 	hour, 12 hour clock, leading 0's)
	%j 	day of the year
	%k 	hour
	%l 	hour, 12 hour clock
	%L 	month number, starting with 1
	%m 	month number, starting with 01
	%M 	minute, leading 0's
	%n 	NEWLINE
	%o	ornate day of month -- "1st", "2nd", "25th", etc.
	%p 	AM or PM 
	%P 	am or pm (Yes %p and %P are backwards :)
	%q	Quarter number, starting with 1
	%r 	time format: 09:05:57 PM
	%R 	time format: 21:05
	%s	seconds since the Epoch, UCT
	%S 	seconds, leading 0's
	%t 	TAB
	%T 	time format: 21:05:57
	%U 	week number, Sunday as first day of week
	%w 	day of the week, numerically, Sunday == 0
	%W 	week number, Monday as first day of week
	%x 	date format: 11/19/94
	%X 	time format: 21:05:57
	%y	year (2 digits)
	%Y	year (4 digits)
	%Z 	timezone in ascii. eg: PST
	%z	timezone in format -/+0000

C&lt;%d&gt;, C&lt;%e&gt;, C&lt;%H&gt;, C&lt;%I&gt;, C&lt;%j&gt;, C&lt;%k&gt;, C&lt;%l&gt;, C&lt;%m&gt;, C&lt;%M&gt;, C&lt;%q&gt;,
C&lt;%y&gt; and C&lt;%Y&gt; can be output in Roman numerals by prefixing the letter
with C&lt;O&gt;, e.g. C&lt;%OY&gt; will output the year as roman numerals.

=head1 LIMITATION

The functions in this module are limited to the time range that can be
represented by the time_t data type, i.e. 1901-12-13 20:45:53 GMT to
2038-01-19 03:14:07 GMT.

=head1 AUTHOR

Graham Barr &lt;gbarr@pobox.com&gt;

=head1 COPYRIGHT

Copyright (c) 1995-2009 Graham Barr. This program is free
software; you can redistribute it and/or modify it under the same terms
as Perl itself.

=cut


</pre></body></html>