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
14 # Uncomment next line to enable debug output (don't uncomment debug() lines)
15 #use Blosxom::Debug debug_level => 1;
17 # --- Configuration variables -----
19 # Perl modules to use for strftime, in search order
20 my @strftime_modules = qw(Time::Piece Date::Format POSIX);
22 # ---------------------------------
39 rfc822 => "%a, %d %b %Y %T %z",
40 # ISO 8601 format (localtime, including time zone offset)
41 # Format is YYYY-MM-DDThh:mm:ssTZD per http://www.w3.org/TR/NOTE-datetime
42 iso8601 => "%Y-%m-%dT%T%z",
47 $now_rfc822 = format_date('rfc822', $now);
48 $now_iso8601 = format_date('iso8601', $now);
49 # debug(1, "now_rfc822: $now_rfc822");
50 # debug(1, "now_iso8601: $now_iso8601");
55 my ($pkg, $files, $others) = @_;
57 # Find the latest publish date in our stories
59 for (values %$files) {
60 $latest_ts = $_ if $_ > $latest_ts;
63 # Format the 'latest' variables
64 $latest_rfc822 = format_date('rfc822', $latest_ts);
65 $latest_iso8601 = format_date('iso8601', $latest_ts);
71 my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
73 ($story_rfc822, $story_mtime_rfc822)
74 = get_story_dates('rfc822', $path, $filename);
75 ($story_iso8601, $story_mtime_iso8601)
76 = get_story_dates('iso8601', $path, $filename);
81 # Get the 'file' (publish/official) and 'mtime' formatted dates for the given story file
83 my ($format, $path, $filename) = @_;
84 my ($file_dt, $mtime_dt) = ('', '');
87 my $story_file = "$blosxom::datadir$path/$filename.$blosxom::file_extension";
88 my $timestamp = $blosxom::files{ $story_file };
89 # debug(2, "$path/$filename timestamp: $timestamp");
91 if (my $stat = stat( $story_file )) {
92 if (my $mtime = $stat->mtime) {
93 # debug(2, "$path/$filename mtime: = $mtime");
95 $mtime_dt = format_date($format, $mtime);
97 $timestamp ||= $mtime;
100 warn "storydate: cannot get mtime on story file '$story_file'\n";
104 warn "storydate: cannot stat story file '$story_file'\n";
107 $file_dt = format_date($format, $timestamp) if $timestamp;
109 return wantarray ? ( $file_dt, $mtime_dt ) : $file_dt;
113 my ($format, $time, $use_gmtime) = @_;
114 return unless $format;
117 if ($format =~ m/%/) {
118 $date = strftime($format, $time, $use_gmtime);
120 elsif ($strftime_formats{ $format }) {
121 $date = strftime($strftime_formats{ $format }, $time, $use_gmtime);
123 # Hack to handle the fact that ISO8601 dates require a : in the timezone, which strftime doesn't support
124 if ($format eq 'iso8601') {
125 $date =~ s/(\d)(\d{2})$/$1:$2/;
131 # strftime wrapper, using the first strftime() it finds in @strftime_modules
133 my $strftime_module = '';
135 my ($format, $time, $use_gmtime) = @_;
136 return unless $format && $time;
137 $use_gmtime = 0 unless defined $use_gmtime;
140 my $cache_key = "$time:$use_gmtime:$format";
141 return $cache{ $cache_key } if exists $cache{ $cache_key };
144 $strftime_module = $ENV{BLOSXOM_STORYDATE_STRFTIME_MODULE};
146 # Search for a strftime module, and load
147 if (! $strftime_module) {
148 for my $module (@strftime_modules) {
149 if (eval "require $module") {
150 $strftime_module = $module;
151 # debug(2, "strftime_module: $strftime_module");
155 if (! $strftime_module) {
156 warn "storydate: cannot find any suitable strftime module\n";
162 if ($strftime_module eq 'Time::Piece') {
163 my $t = $use_gmtime ? Time::Piece->gmtime($time) : Time::Piece->localtime($time);
165 # Seems to be a bug in Time::Piece %z handling - workaround
166 my $tz_offset = sprintf("%+03d%02d", int($t->tzoffset / 3600), ($t->tzoffset % 3600) / 60);
167 $format =~ s/%z/$tz_offset/g;
169 $datetime = $t->strftime( $format );
172 elsif ($strftime_module eq 'Date::Format') {
173 my @t = $use_gmtime ? gmtime($time) : localtime($time);
174 $datetime = Date::Format::strftime($format, \@t);
177 elsif ($strftime_module eq 'POSIX') {
178 my @t = $use_gmtime ? gmtime($time) : localtime($time);
179 $datetime = POSIX::strftime($format, @t);
182 $cache{ $cache_key } = $datetime if $datetime;
193 storydate - blosxom plugin to provide story dates in various formats
194 for use by other plugins
199 storydate is a blosxom plugin that provides story dates in various
200 formats for use by other plugins. It defines the following variables:
206 The official/publication date of the story in RFC822 format.
210 The official/publication date of the story in ISO8601 format.
212 =item $story_mtime_rfc822
214 The last modification time of the story in RFC822 format.
216 =item $story_mtime_iso8601
218 The last modification time of the story in ISO8601 format.
222 The current time in RFC822 format.
226 The current time in ISO8601 format.
230 The latest story publication date, in RFC822 format.
232 =item $latest_iso8601
234 The latest story publication date, in ISO8601 format.
238 In addition, storydate defines a few subroutines that might be useful
243 =item strftime($format, $time)
245 Returns $time, formatted according to the L<strftime(3)> format
246 $format. Requires one of the following perl modules be available to
247 provide a strftime() function: Time::Piece, Date::Format, or POSIX.
249 =item get_story_dates($format, $path, $filename)
251 Returns the publication date and the last modified date of the story
252 at "$path/$filename.$blosxom::file_extension", formatted according
253 to the L<strftime(3)> format $format.
260 storydate should be loaded early, before any story plugins that want
268 Blosxom: http://blosxom.sourceforge.net/
271 =head1 ACKNOWLEDGEMENTS
273 storydate is based on Frank Hecker's lastmodified2 plugin, which is
274 itself based on Bob Schumaker's lastmodified plugin.
276 The problem with lastmodified2 is that its HTTP header functionality
277 requires that it runs very late, which makes it useless for providing
278 dates to story plugins. storydate is basically just all the parts of
279 lastmodified2 that can be run early pulled out into a separate plugin.
284 Gavin Carr <gavin@openfusion.com.au>, http://www.openfusion.net/
289 Copyright 2007, Gavin Carr.
291 This plugin is licensed under the same terms as blosxom itself i.e.
293 Permission is hereby granted, free of charge, to any person obtaining a
294 copy of this software and associated documentation files (the "Software"),
295 to deal in the Software without restriction, including without limitation
296 the rights to use, copy, modify, merge, publish, distribute, sublicense,
297 and/or sell copies of the Software, and to permit persons to whom the
298 Software is furnished to do so, subject to the following conditions:
300 The above copyright notice and this permission notice shall be included
301 in all copies or substantial portions of the Software.
303 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
304 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
305 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
306 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
307 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
308 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
309 OTHER DEALINGS IN THE SOFTWARE.