30

I know that I can specify a variable date in the YAML frontmatter of a file and access its value with {{ page.date }}. This is cumbersome since one easily forgets to change the date when a file is updated. So how can I access a file's modification date?

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
Robert
  • 872
  • 3
  • 10
  • 15

5 Answers5

37

This is a relatively new plugin that does what you're looking for:

https://github.com/gjtorikian/jekyll-last-modified-at

(found it while searching Google for alternatives to the other answers in this thread)

Case
  • 927
  • 8
  • 6
  • 10
    Let's upvote this answer and star that project until GitHub adds that plugin to the whitelist. – Ciro Santilli OurBigBook.com Nov 26 '14 at 11:12
  • 1
    I had problems installing jekyll-last-modified-at. I tried gem update, gem install, bundle exec, bundle install and tried to include the gem in my config.yml but I couldn't solve this "Dependency Error: Yikes! It looks like you don't have jekyll-last-modified-at...." I use Github, so if this is not whitelisted then it isn't good for me anyway ;-) – Athanassios Jul 30 '16 at 12:24
17

From Jekyll 1.x there is a page.path that gives you the filename of the post or page being currently processed. Add the following filter (place e.g. in _plugins/myfilters.rb) to get the modification time of a given filename:

module Jekyll
  module MyFilters
    def file_date(input)
      File.mtime(input)
    end
  end
end

Liquid::Template.register_filter(Jekyll::MyFilters)

So now you can render the date on your posts and pages, e.g., as

{{ page.path | file_date | date_to_string }}
Juan A. Navarro
  • 10,595
  • 6
  • 48
  • 52
  • Unfortunately, this does not work for me because `page.path` is empty. I found [a post](http://stackoverflow.com/questions/13243469/how-can-a-jekyll-page-access-its-filename) that shows how to access it but this seems to work for posts only and not for other pages. – Robert Aug 19 '13 at 10:48
  • Hmm.. that's strange, I am using this precisely on pages, and it seems to be working fine. In case it matters, I'm using jekyll (1.1.2) and ruby (2.0.0p247). – Juan A. Navarro Aug 19 '13 at 14:30
  • Without the script that sets `page.path` I get `Liquid error: can't convert nil into String`. Using it I get `'generate': undefined method 'name'`. I am using ruby 1.9.3 and Jekyll 0.11.2 and it's not so easy to update ... – Robert Aug 21 '13 at 18:31
  • 1
    Well, yeah, it's going to be difficult unless you upgrade to some Jekyll 1.x. Sorry. – Juan A. Navarro Aug 22 '13 at 08:18
  • 1
    Just to add: If, like me, you move your site's source into a subdirectory, you need to prepend that directory to the path that comes from `page.path` (it's only source-relative), like so: `{{ page.path | prepend: "/" | prepend: site.source | file_date | date_to_string }}` – tamouse Feb 14 '15 at 19:29
  • I had problems installing jekyll-last-modified-at. I tried gem update, gem install, bundle exec, bundle install and tried to include the gem in my config.yml but I couldn't solve this "Dependency Error: Yikes! It looks like you don't have jekyll-last-modified-at...." Adding a filter it was much easier and it works fine, thank you Juan – Athanassios Jul 30 '16 at 12:22
  • Won't work on GitHub pages because they disable custom plugins for security reasons. – SeanFromIT Jul 08 '18 at 18:21
  • Thanks for this plugin! I'm using it in a sitemap as `{{ page.path | file_date | date_to_xmlschema }}` – knee-cola Jul 24 '18 at 11:24
8

Based on krlmlr's post, I wrote a pre-commit script to update modification time of the date: field in YAML front matter of the modified files.

#!/bin/sh
# Contents of .git/hooks/pre-commit

git diff --cached --name-status | grep "^M" | while read a b; do
  cat $b | sed "/---.*/,/---.*/s/^date:.*$/date: $(date -u "+%Y-%m-%d %T %Z")/" > tmp
  mv tmp $b
  git add $b
done

It is working fine for me. I actually use update: field to indicate the modified time, and date: field to indicate the creation time.

seki
  • 91
  • 1
  • 4
  • wfm using gh-pages! Had to add {% unless page.nodate %} {{ page.date | date: "%b %-d, %Y" }}{% endunless %} to my docpage.html in _layouts and add date: to the front matter of each file. What a nice Christmas present it was to find this. – catpaws Dec 24 '15 at 23:13
  • 1
    Works like a charm! Only thing I changed was the date format. I am using `date "+%Y-%m-%d %T %z"` which matches the (current) default Jekyll date format. – Sebastián Barschkis Apr 22 '16 at 09:54
4

I don't think it's possible to do this without using the YAML frontmatter. Note, however, that specifying date in the frontmatter actually overrides the date given in the post's filename.

So if you have a file 2013-02-19-my-post.md and in its frontmatter you have date: 2013-02-20, the frontmatter takes precedence, and the post's date is 2013-02-20.

If you want to keep track of when a post is modified, I'm afraid there's no way to do this without using a custom field in your frontmatter. Call it modified-date or something. Yes, it is a bit tedious. I have a TextExpander snippet that automatically outputs current date/time in the proper format, which is handy.

Andrew Clark
  • 721
  • 7
  • 15
  • Is it not possible for posts or in general? For posts I don't see the need to get their modification date, since the date encoded in the file name is fine (I rarely change posts). However, for all other Markdown files Jekyll is processing, I don't have that date and encode it in the YAML frontmatter. Since these files change frequently, I would like to get their modification date automatically. – Robert Feb 21 '13 at 08:23
  • 1
    The feature you describe is not built into Jekyll, for either posts or pages. I suppose in theory you could write a [Jekyll plugin](https://github.com/mojombo/jekyll/wiki/Plugins) which utilizes Ruby's `File.mtime`, but that seems like more trouble than it's worth. Plus, there could be some unintended consequences. What if, for instance, you want to edit a page's frontmatter without updating its modification date? I think a custom variable is the best way to go. – Andrew Clark Feb 22 '13 at 03:12
4

If you're using Git, you can install a pre-commit hook that automatically updates the date field in the front matter of modified files. I was very surprised to learn that a pre-commit hook can indeed change the contents of the commit! You only have to manually install a pre-commit hook into each clone of the repository -- the following rough draft works for me for updating the overall modification time of the entire website:

#!/bin/sh
# Contents of .git/hooks/pre-commit

set -e
set -x

sed -i "s/^date:.*$/date: $(TZ=UTC date "+%Y-%m-%d %H:%M:%S %Z")/" _config.yml
git add _config.yml

The _config.yml is expected to have a field "date", its contents will be replaced by each commit. It can be then accessed via {{ site.date }}. Example:

date: 2015-04-10 10:51:37 UTC

The script can be generalized to update only those pages or posts that have changed (query via git diff-index --cached) -- I don't have the time to implement this but I'd be interested to learn if a neater solution pops out eventually.

krlmlr
  • 25,056
  • 14
  • 120
  • 217