1 #============================================================= -*-Perl-*-
3 # Template::Plugin::Date
7 # Plugin to generate formatted date strings.
10 # Thierry-Michel Barral <kktos@electron-libre.com>
11 # Andy Wardley <abw@wardley.org>
14 # Copyright (C) 2000-2007 Thierry-Michel Barral, Andy Wardley.
16 # This module is free software; you can redistribute it and/or
17 # modify it under the same terms as Perl itself.
19 #============================================================================
21 package Template::Plugin::Date;
25 use base 'Template::Plugin';
30 our $FORMAT = '%H:%M:%S %d-%b-%Y'; # default strftime() format
31 our @LOCALE_SUFFIX = qw( .ISO8859-1 .ISO_8859-15 .US-ASCII .UTF-8 );
34 #------------------------------------------------------------------------
36 #------------------------------------------------------------------------
39 my ($class, $context, $params) = @_;
41 $params ? %$params : ()
46 #------------------------------------------------------------------------
49 # Call time() to return the current system time in seconds since the epoch.
50 #------------------------------------------------------------------------
57 #------------------------------------------------------------------------
60 # format($time, $format)
61 # format($time, $format, $locale)
62 # format($time, $format, $locale, $gmt_flag)
63 # format(\%named_params);
65 # Returns a formatted time/date string for the specified time, $time,
66 # (or the current system time if unspecified) using the $format, $locale,
67 # and $gmt values specified as arguments or internal values set defined
68 # at construction time). Specifying a Perl-true value for $gmt will
69 # override the local time zone and force the output to be for GMT.
70 # Any or all of the arguments may be specified as named parameters which
71 # get passed as a hash array reference as the final argument.
72 # ------------------------------------------------------------------------
76 my $params = ref($_[$#_]) eq 'HASH' ? pop(@_) : { };
77 my $time = shift(@_) || $params->{ time } || $self->{ time }
79 my $format = @_ ? shift(@_)
80 : ($params->{ format } || $self->{ format } || $FORMAT);
81 my $locale = @_ ? shift(@_)
82 : ($params->{ locale } || $self->{ locale });
83 my $gmt = @_ ? shift(@_)
84 : ($params->{ gmt } || $self->{ gmt });
87 if ($time =~ /^\d+$/) {
88 # $time is now in seconds since epoch
90 @date = (gmtime($time))[0..6];
93 @date = (localtime($time))[0..6];
97 # if $time is numeric, then we assume it's seconds since the epoch
98 # otherwise, we try to parse it as either a 'Y:M:D H:M:S' or a
99 # 'H:M:S D:M:Y' string
101 my @parts = (split(/(?:\/| |:|-)/, $time));
104 if (length($parts[0]) == 4) {
105 # year is first; assume 'Y:M:D H:M:S'
106 @date = @parts[reverse 0..5];
109 # year is last; assume 'H:M:S D:M:Y'
110 @date = @parts[2,1,0,3..5];
115 return (undef, Template::Exception->new('date',
116 "bad time/date string: " .
117 "expects 'h:m:s d:m:y' got: '$time'"));
119 $date[4] -= 1; # correct month number 1-12 to range 0-11
120 $date[5] -= 1900; # convert absolute year to years since 1900
121 $time = &POSIX::mktime(@date);
125 # format the date in a specific locale, saving and subsequently
126 # restoring the current locale.
127 my $old_locale = &POSIX::setlocale(&POSIX::LC_ALL);
129 # some systems expect locales to have a particular suffix
130 for my $suffix ('', @LOCALE_SUFFIX) {
131 my $try_locale = $locale.$suffix;
132 my $setlocale = &POSIX::setlocale(&POSIX::LC_ALL, $try_locale);
133 if (defined $setlocale && $try_locale eq $setlocale) {
134 $locale = $try_locale;
138 $datestr = &POSIX::strftime($format, @date);
139 &POSIX::setlocale(&POSIX::LC_ALL, $old_locale);
142 $datestr = &POSIX::strftime($format, @date);
150 eval { require "Date/Calc.pm" };
151 $self->throw("failed to load Date::Calc: $@") if $@;
152 return Template::Plugin::Date::Calc->new('no context');
157 eval { require "Date/Manip.pm" };
158 $self->throw("failed to load Date::Manip: $@") if $@;
159 return Template::Plugin::Date::Manip->new('no context');
165 die (Template::Exception->new('date', join(', ', @_)));
169 package Template::Plugin::Date::Calc;
170 use base qw( Template::Plugin );
171 use vars qw( $AUTOLOAD );
172 *throw = \&Template::Plugin::Date::throw;
176 my $method = $AUTOLOAD;
179 return if $method eq 'DESTROY';
181 my $sub = \&{"Date::Calc::$method"};
182 $self->throw("no such Date::Calc method: $method")
188 package Template::Plugin::Date::Manip;
189 use base qw( Template::Plugin );
190 use vars qw( $AUTOLOAD );
191 *throw = \&Template::Plugin::Date::throw;
195 my $method = $AUTOLOAD;
198 return if $method eq 'DESTROY';
200 my $sub = \&{"Date::Manip::$method"};
201 $self->throw("no such Date::Manip method: $method")
214 Template::Plugin::Date - Plugin to generate formatted date strings
220 # use current time and default format
223 # specify time as seconds since epoch
224 # or as a 'h:m:s d-m-y' or 'y-m-d h:m:s' string
225 [% date.format(960973980) %]
226 [% date.format('4:20:36 21/12/2000') %]
227 [% date.format('2000/12/21 4:20:36') %]
230 [% date.format(mytime, '%H:%M:%S') %]
233 [% date.format(date.now, '%a %d %b %y', 'en_GB') %]
236 [% date.format(mytime, format = '%H:%M:%S') %]
237 [% date.format(locale = 'en_GB') %]
238 [% date.format(time = date.now,
242 # specify default format to plugin
243 [% USE date(format = '%H:%M:%S', locale = 'de_DE') %]
250 The C<Date> plugin provides an easy way to generate formatted time and date
251 strings by delegating to the C<POSIX> C<strftime()> routine.
253 The plugin can be loaded via the familiar USE directive.
257 This creates a plugin object with the default name of 'C<date>'. An alternate
258 name can be specified as such:
260 [% USE myname = date %]
262 The plugin provides the C<format()> method which accepts a time value, a
263 format string and a locale name. All of these parameters are optional
264 with the current system time, default format ('C<%H:%M:%S %d-%b-%Y>') and
265 current locale being used respectively, if undefined. Default values
266 for the time, format and/or locale may be specified as named parameters
267 in the C<USE> directive.
269 [% USE date(format = '%a %d-%b-%Y', locale = 'fr_FR') %]
271 When called without any parameters, the C<format()> method returns a string
272 representing the current system time, formatted by C<strftime()> according
273 to the default format and for the default locale (which may not be the
274 current one, if locale is set in the C<USE> directive).
278 The plugin allows a time/date to be specified as seconds since the epoch,
279 as is returned by C<time()>.
281 File last modified: [% date.format(filemod_time) %]
283 The time/date can also be specified as a string of the form C<h:m:s d/m/y>
284 or C<y/m/d h:m:s>. Any of the characters : / - or space may be used to
287 [% USE day = date(format => '%A', locale => 'en_GB') %]
288 [% day.format('4:20:00 9-13-2000') %]
294 A format string can also be passed to the C<format()> method, and a locale
295 specification may follow that.
297 [% date.format(filemod, '%d-%b-%Y') %]
298 [% date.format(filemod, '%d-%b-%Y', 'en_GB') %]
300 A fourth parameter allows you to force output in GMT, in the case of
301 seconds-since-the-epoch input:
303 [% date.format(filemod, '%d-%b-%Y', 'en_GB', 1) %]
305 Note that in this case, if the local time is not GMT, then also specifying
306 'C<%Z>' (time zone) in the format parameter will lead to an extremely
309 Any or all of these parameters may be named. Positional parameters
310 should always be in the order C<($time, $format, $locale)>.
312 [% date.format(format => '%H:%M:%S') %]
313 [% date.format(time => filemod, format => '%H:%M:%S') %]
314 [% date.format(mytime, format => '%H:%M:%S') %]
315 [% date.format(mytime, format => '%H:%M:%S', locale => 'fr_FR') %]
316 [% date.format(mytime, format => '%H:%M:%S', gmt => 1) %]
319 The C<now()> method returns the current system time in seconds since the
322 [% date.format(date.now, '%A') %]
324 The C<calc()> method can be used to create an interface to the C<Date::Calc>
325 module (if installed on your system).
327 [% calc = date.calc %]
328 [% calc.Monday_of_Week(22, 2001).join('/') %]
330 The C<manip()> method can be used to create an interface to the C<Date::Manip>
331 module (if installed on your system).
333 [% manip = date.manip %]
334 [% manip.UnixDate("Noon Yesterday","%Y %b %d %H:%M") %]
338 Thierry-Michel Barral wrote the original plugin.
340 Andy Wardley provided some minor
341 fixups/enhancements, a test script and documentation.
343 Mark D. Mills cloned C<Date::Manip> from the C<Date::Calc> sub-plugin.
347 Copyright (C) 2000-2007 Thierry-Michel Barral, Andy Wardley.
349 This module is free software; you can redistribute it and/or
350 modify it under the same terms as Perl itself.
354 L<Template::Plugin>, L<POSIX>