1 # Blosxom Plugin: storydate
2 # Author(s): Gavin Carr <gavin@openfusion.com.au>
3 # (based on work by Frank Hecker <hecker@hecker.org>
4 # and Bob Schumaker <cobblers@pobox.com>)
6 # Documentation: See the bottom of this file or type: perldoc storydate
15 # Uncomment next line to enable debug output (don't uncomment debug() lines)
16 #use Blosxom::Debug debug_level => 1;
18 # --- Configuration variables -----
22 # Perl modules to use for strftime, in search order
23 $config{strftime_modules} = [ qw(Time::Piece Date::Format POSIX) ];
25 # ---------------------------------
42 rfc822 => "%a, %d %b %Y %T %z",
43 # ISO 8601 format (localtime, including time zone offset)
44 # Format is YYYY-MM-DDThh:mm:ssTZD per http://www.w3.org/TR/NOTE-datetime
45 iso8601 => "%Y-%m-%dT%T%z",
50 $now_rfc822 = format_date('rfc822', $now);
51 $now_iso8601 = format_date('iso8601', $now);
52 # debug(1, "now_rfc822: $now_rfc822");
53 # debug(1, "now_iso8601: $now_iso8601");
58 my ($pkg, $files, $others) = @_;
60 # Find the latest publish date in our stories
62 for (values %$files) {
63 $latest_ts = $_ if $_ > $latest_ts;
66 # Format the 'latest' variables
67 $latest_rfc822 = format_date('rfc822', $latest_ts);
68 $latest_iso8601 = format_date('iso8601', $latest_ts);
74 my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
76 ($story_rfc822, $story_mtime_rfc822)
77 = get_story_dates('rfc822', $path, $filename);
78 ($story_iso8601, $story_mtime_iso8601)
79 = get_story_dates('iso8601', $path, $filename);
84 # Get the 'file' (publish/official) and 'mtime' formatted dates for the given story file
86 my ($format, $path, $filename) = @_;
87 my ($file_dt, $mtime_dt) = ('', '');
90 my $story_file = "$blosxom::datadir$path/$filename.$blosxom::file_extension";
91 my $timestamp = $blosxom::files{ $story_file };
92 # debug(2, "$path/$filename timestamp: $timestamp");
94 if (my $stat = stat( $story_file )) {
95 if (my $mtime = $stat->mtime) {
96 # debug(2, "$path/$filename mtime: = $mtime");
98 $mtime_dt = format_date($format, $mtime);
100 $timestamp ||= $mtime;
103 warn "storydate: cannot get mtime on story file '$story_file'\n";
107 warn "storydate: cannot stat story file '$story_file'\n";
110 $file_dt = format_date($format, $timestamp) if $timestamp;
112 return wantarray ? ( $file_dt, $mtime_dt ) : $file_dt;
116 my ($format, $time, $use_gmtime) = @_;
117 return unless $format;
120 if ($format =~ m/%/) {
121 $date = strftime($format, $time, $use_gmtime);
123 elsif ($strftime_formats{ $format }) {
124 $date = strftime($strftime_formats{ $format }, $time, $use_gmtime);
126 # Hack to handle the fact that ISO8601 dates require a : in the timezone, which strftime doesn't support
127 if ($format eq 'iso8601') {
128 $date =~ s/(\d)(\d{2})$/$1:$2/;
134 # strftime wrapper, using the first strftime() it finds in 'strftime_modules'
136 my $strftime_module = '';
138 my ($format, $time, $use_gmtime) = @_;
139 return unless $format && $time;
140 $use_gmtime = 0 unless defined $use_gmtime;
143 my $cache_key = "$time:$use_gmtime:$format";
144 return $cache{ $cache_key } if exists $cache{ $cache_key };
147 $strftime_module = $ENV{BLOSXOM_STORYDATE_STRFTIME_MODULE};
149 # Search for a strftime module, and load
150 if (! $strftime_module) {
151 for my $module (@{$config{strftime_modules}}) {
152 if (eval "require $module") {
153 $strftime_module = $module;
154 # debug(2, "strftime_module: $strftime_module");
158 if (! $strftime_module) {
159 warn "storydate: cannot find any suitable strftime module\n";
165 if ($strftime_module eq 'Time::Piece') {
166 my $t = $use_gmtime ? Time::Piece->gmtime($time) : Time::Piece->localtime($time);
168 # Seems to be a bug in Time::Piece %z handling - workaround
169 my $tz_offset = sprintf("%+03d%02d", int($t->tzoffset / 3600), ($t->tzoffset % 3600) / 60);
170 $format =~ s/%z/$tz_offset/g;
172 $datetime = $t->strftime( $format );
175 elsif ($strftime_module eq 'Date::Format') {
176 my @t = $use_gmtime ? gmtime($time) : localtime($time);
177 $datetime = Date::Format::strftime($format, \@t);
180 elsif ($strftime_module eq 'POSIX') {
181 my @t = $use_gmtime ? gmtime($time) : localtime($time);
182 $datetime = POSIX::strftime($format, @t);
185 $cache{ $cache_key } = $datetime if $datetime;
196 storydate - blosxom plugin to provide story dates in various formats
197 for use by other plugins
202 storydate is a blosxom plugin that provides story dates in various
203 formats for use by other plugins. It defines the following variables:
209 The official/publication date of the story in RFC822 format.
213 The official/publication date of the story in ISO8601 format.
215 =item $story_mtime_rfc822
217 The last modification time of the story in RFC822 format.
219 =item $story_mtime_iso8601
221 The last modification time of the story in ISO8601 format.
225 The current time in RFC822 format.
229 The current time in ISO8601 format.
233 The latest story publication date, in RFC822 format.
235 =item $latest_iso8601
237 The latest story publication date, in ISO8601 format.
241 In addition, storydate defines a few subroutines that might be useful
246 =item strftime($format, $time)
248 Returns $time, formatted according to the L<strftime(3)> format
249 $format. Requires one of the following perl modules be available to
250 provide a strftime() function: Time::Piece, Date::Format, or POSIX.
252 =item get_story_dates($format, $path, $filename)
254 Returns the publication date and the last modified date of the story
255 at "$path/$filename.$blosxom::file_extension", formatted according
256 to the L<strftime(3)> format $format.
263 storydate should be loaded early, before any story plugins that want
271 Blosxom: http://blosxom.sourceforge.net/
274 =head1 ACKNOWLEDGEMENTS
276 storydate is based on Frank Hecker's lastmodified2 plugin, which is
277 itself based on Bob Schumaker's lastmodified plugin.
279 The problem with lastmodified2 is that its HTTP header functionality
280 requires that it runs very late, which makes it useless for providing
281 dates to story plugins. storydate is basically just all the parts of
282 lastmodified2 that can be run early pulled out into a separate plugin.
287 Gavin Carr <gavin@openfusion.com.au>, http://www.openfusion.net/
292 Copyright 2007, Gavin Carr.
294 This plugin is licensed under the same terms as blosxom itself i.e.
296 Permission is hereby granted, free of charge, to any person obtaining a
297 copy of this software and associated documentation files (the "Software"),
298 to deal in the Software without restriction, including without limitation
299 the rights to use, copy, modify, merge, publish, distribute, sublicense,
300 and/or sell copies of the Software, and to permit persons to whom the
301 Software is furnished to do so, subject to the following conditions:
303 The above copyright notice and this permission notice shall be included
304 in all copies or substantial portions of the Software.
306 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
307 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
308 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
309 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
310 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
311 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
312 OTHER DEALINGS IN THE SOFTWARE.