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 # ---------------------------------
36 rfc822 => "%a, %d %b %Y %T %z",
37 # ISO 8601 format (localtime, including time zone offset)
38 # Format is YYYY-MM-DDThh:mm:ssTZD per http://www.w3.org/TR/NOTE-datetime
39 iso8601 => "%Y-%m-%dT%T%z",
44 $now_rfc822 = format_date('rfc822', $now);
45 $now_iso8601 = format_date('iso8601', $now);
46 # debug(1, "now_rfc822: $now_rfc822");
47 # debug(1, "now_iso8601: $now_iso8601");
52 my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;
54 ($story_rfc822, $story_mtime_rfc822)
55 = get_story_dates('rfc822', $path, $filename);
56 ($story_iso8601, $story_mtime_iso8601)
57 = get_story_dates('iso8601', $path, $filename);
62 # Get the 'file' (publish/official) and 'mtime' formatted dates for the given story file
64 my ($format, $path, $filename) = @_;
65 my ($file_dt, $mtime_dt) = ('', '');
68 my $story_file = "$blosxom::datadir$path/$filename.$blosxom::file_extension";
69 my $timestamp = $blosxom::files{ $story_file };
70 # debug(2, "$path/$filename timestamp: $timestamp");
72 if (my $stat = stat( $story_file )) {
73 if (my $mtime = $stat->mtime) {
74 # debug(2, "$path/$filename mtime: = $mtime");
76 $mtime_dt = format_date($format, $mtime);
78 $timestamp ||= $mtime;
81 warn "storydate: cannot get mtime on story file '$story_file'\n";
85 warn "storydate: cannot stat story file '$story_file'\n";
88 $file_dt = format_date($format, $timestamp) if $timestamp;
90 return wantarray ? ( $file_dt, $mtime_dt ) : $file_dt;
94 my ($format, $time, $use_gmtime) = @_;
95 return unless $format;
98 if ($format =~ m/%/) {
99 $date = strftime($format, $time, $use_gmtime);
101 elsif ($strftime_formats{ $format }) {
102 $date = strftime($strftime_formats{ $format }, $time, $use_gmtime);
104 # Hack to handle the fact that ISO8601 dates require a : in the timezone, which strftime doesn't support
105 if ($format eq 'iso8601') {
106 $date =~ s/(\d)(\d{2})$/$1:$2/;
112 # strftime wrapper, using the first strftime() it finds in @strftime_modules
114 my $strftime_module = '';
116 my ($format, $time, $use_gmtime) = @_;
117 return unless $format && $time;
118 $use_gmtime = 0 unless defined $use_gmtime;
121 my $cache_key = "$time:$use_gmtime:$format";
122 return $cache{ $cache_key } if exists $cache{ $cache_key };
125 $strftime_module = $ENV{BLOSXOM_STORYDATE_STRFTIME_MODULE};
127 # Search for a strftime module, and load
128 if (! $strftime_module) {
129 for my $module (@strftime_modules) {
130 if (eval "require $module") {
131 $strftime_module = $module;
132 # debug(2, "strftime_module: $strftime_module");
136 if (! $strftime_module) {
137 warn "storydate: cannot find any suitable strftime module\n";
143 if ($strftime_module eq 'Time::Piece') {
144 my $t = $use_gmtime ? Time::Piece->gmtime($time) : Time::Piece->localtime($time);
146 # Seems to be a bug in Time::Piece %z handling - workaround
147 my $tz_offset = sprintf("%+03d%02d", int($t->tzoffset / 3600), ($t->tzoffset % 3600) / 60);
148 $format =~ s/%z/$tz_offset/g;
150 $datetime = $t->strftime( $format );
153 elsif ($strftime_module eq 'Date::Format') {
154 my @t = $use_gmtime ? gmtime($time) : localtime($time);
155 $datetime = Date::Format::strftime($format, \@t);
158 elsif ($strftime_module eq 'POSIX') {
159 my @t = $use_gmtime ? gmtime($time) : localtime($time);
160 $datetime = POSIX::strftime($format, @t);
163 $cache{ $cache_key } = $datetime if $datetime;
174 storydate - blosxom plugin to provide story dates in various formats
175 for use by other plugins
180 storydate is a blosxom plugin that provides story dates in various
181 formats for use by other plugins. It defines the following variables:
187 The official/publication date of the story in RFC822 format.
191 The official/publication date of the story in ISO8601 format.
193 =item $story_mtime_rfc822
195 The last modification time of the story in RFC822 format.
197 =item $story_mtime_iso8601
199 The last modification time of the story in ISO8601 format.
203 The current time in RFC822 format.
207 The current time in ISO8601 format.
211 In addition, storydate defines a few subroutines that might be useful
216 =item strftime($format, $time)
218 Returns $time, formatted according to the L<strftime(3)> format
219 $format. Requires one of the following perl modules be available to
220 provide a strftime() function: Time::Piece, Date::Format, or POSIX.
222 =item get_story_dates($format, $path, $filename)
224 Returns the publication date and the last modified date of the story
225 at "$path/$filename.$blosxom::file_extension", formatted according
226 to the L<strftime(3)> format $format.
233 storydate should be loaded early, before any story plugins that want
241 Blosxom: http://blosxom.sourceforge.net/
244 =head1 ACKNOWLEDGEMENTS
246 storydate is based on Frank Hecker's lastmodified2 plugin, which is
247 itself based on Bob Schumaker's lastmodified plugin.
249 The problem with lastmodified2 is that its HTTP header functionality
250 requires that it runs very late, which makes it useless for providing
251 dates to story plugins. storydate is basically just all the parts of
252 lastmodified2 that can be run early pulled out into a separate plugin.
257 Gavin Carr <gavin@openfusion.com.au>, http://www.openfusion.net/
262 Copyright 2007, Gavin Carr.
264 This plugin is licensed under the same terms as blosxom itself i.e.
266 Permission is hereby granted, free of charge, to any person obtaining a
267 copy of this software and associated documentation files (the "Software"),
268 to deal in the Software without restriction, including without limitation
269 the rights to use, copy, modify, merge, publish, distribute, sublicense,
270 and/or sell copies of the Software, and to permit persons to whom the
271 Software is furnished to do so, subject to the following conditions:
273 The above copyright notice and this permission notice shall be included
274 in all copies or substantial portions of the Software.
276 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
277 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
278 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
279 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
280 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
281 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
282 OTHER DEALINGS IN THE SOFTWARE.