Skip to content

Instantly share code, notes, and snippets.

@Zegnat
Created September 25, 2011 10:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zegnat/1240467 to your computer and use it in GitHub Desktop.
Save Zegnat/1240467 to your computer and use it in GitHub Desktop.
A plugin for Jekyll 0.11.0 to allow different types of datestamps for blog posts.

ISO 8601 datestamp support for Jekyll

About

Jekyll is a static site generator with blogging capabilities. For blogging it looks for files starting with a datestamp. In its original form, Jekyll only supports hyphen separated calendar dates (YEAR-MONTH-DAY).

This plugin file tries to implement ISO 8601 datestamps and give you a little more freedom when stamping your posts and building your permalinks with dates.

Installation

Drop the postdates.rb file in your _plugins directory. If you do not have one already you can create it in the site source directory. For more information, check out the plugins page on the Jekyll wiki.

Compatibility note

This plugin works by rewriting the post processing and url generation of Jekyll completely. (Also called monkey patching.) This means the plugin is neither forward nor backward compatible. It might be, but it is better to have no illusions about it.

Please only use this with Jekyll 0.11.0. You can run jekyll --version if you want to find out what version of Jekyll you have installed.

Supported timestamps

  • Calendar dates: YEAR-MONTH-DAY, YEARMONTHDAY
    • YEAR: 4 or more digits, ± allowed but ignored
    • MONTH: 2 digits,
    • DAY: 2 digits
  • Ordinal dates: YEAR-DAY, YEARDAY
    • YEAR: 4 or more digits, ± allowed but ignored
    • DAY: 3 digits

Notes

  1. ISO 8601 allows for negative years to be used, to assign dates to events that happened BCE. This plugin does parse datestamps beginning with - but ignores it’s meaning. This means blog posts dated -2011-01-01 will equal blog posts from 2011-01-01. Just don’t blog into the past.

    Note that the less often used but valid + is also accepted and ignored.

  2. ISO 8601 requires either a + or - in front of expanded year notations (ie. 02011 should be +02011). In actual use however, mostly promoted by the Long Now Foundation (more here), the + is almost always left out. It is therefore not required by this plugin.

  3. ISO 8601 allows both ordinal and calendar dates to be written without separators. It also allows for years of over 4 digits on both. This means there are many possible conflicts. 20110101 could be 2011-01-01 or 20110-101. This plugin does not try to fix this.

Supported permalink variables

  • longnow: same as year but padded up to a length of 5 digits. Example: 02011.
  • yday: the ordinal date. Example: 012.
  • i_yday: the ordinal date without leading zeroes. Example: 12.

Todo

  • Week dates
  • Try to move permalink additions out of the url method, a little less monkey patching.
  • Liquid tags for ordinal date and padded years.
STDERR.puts 'Running with ISO 8601 datestamp support'
module Jekyll
class Post
# A new way of recognising posts.
remove_const(:MATCHER)
MATCHER = /^(.+\/)*(?:\+|-)?(\d{4,})(?:(?:(?:-(0[1-9]|1[012])-|(0[1-9]|1[012]))(0[1-9]|[12][0-9]|3[01]))|(?:-?(00[1-9]|0[1-9]\d|[12]\d\d|3[0-5]\d|36[0-6])))-(.*)(\.[^.]+)$/
# Processing the new dates.
def process(name)
m, cats, year, month1, month2, day, orday, slug, ext = *name.match(MATCHER)
if orday
date = (Date.ordinal(year.to_i,orday.to_i)).to_s
else
date = year+"-"+(month1||month2)+"-"+day
end
self.date = Time.parse(date)
self.slug = slug
self.ext = ext
rescue ArgumentError
raise FatalException.new("Post #{name} does not have a valid date.")
end
# Modifying the permalink processing.
def url
return @url if @url
url = if permalink
permalink
else
{
"longnow" => "%05d" % date.strftime("%Y"),
"year" => date.strftime("%Y"),
"month" => date.strftime("%m"),
"day" => date.strftime("%d"),
"yday" => date.strftime("%j"),
"title" => CGI.escape(slug),
"i_month" => date.strftime("%m").to_i.to_s,
"i_day" => date.strftime("%d").to_i.to_s,
"i_yday" => date.strftime("%j").to_i.to_s,
"categories" => categories.join('/'),
"output_ext" => self.output_ext
}.inject(template) { |result, token|
result.gsub(/:#{Regexp.escape token.first}/, token.last)
}.gsub(/\/\//, "/")
end
# sanitize url
@url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
@url += "/" if url =~ /\/$/
@url
end
end
end
^
(.+\/)* # Directories for categories
(?:\+|-)? # Optional and ignored + or -
(\d{4,}) # Year, expressed with at least four digits
(?:
(?:
(?:
-(0[1-9]|1[012])- # Calendar month (01 to 12) with - separators
|
(0[1-9]|1[012]) # Calendar month (01 to 12) without - separators
)
(0[1-9]|[12][0-9]|3[01]) # Calendar day (01 to 31)
)
|
(?:
-? # Optional - separator
(00[1-9]|0[1-9]\d|[12]\d\d|3[0-5]\d|36[0-6]) # Ordinal day (001 to 366)
)
)
-(.*) # Slug, after required - separator
(\.[^.]+) # File extension, starting with .
$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment