From 81c25b9502e7354196035908ce48a421a201dbe7 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Sat, 30 Nov 2013 02:37:58 +0100 Subject: [PATCH] relative time --- _src/_layouts/link.html | 2 +- _src/_layouts/photo.html | 2 +- _src/_layouts/post.html | 4 +- _src/_plugins/timeago.rb | 109 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 _src/_plugins/timeago.rb diff --git a/_src/_layouts/link.html b/_src/_layouts/link.html index e2a4a63e..4f827621 100644 --- a/_src/_layouts/link.html +++ b/_src/_layouts/link.html @@ -28,7 +28,7 @@ layout: base

by

-

{{ page.date | date_to_string }}

+

{{ page.date | timeago }}

diff --git a/_src/_layouts/photo.html b/_src/_layouts/photo.html index 7702e836..631584c3 100644 --- a/_src/_layouts/photo.html +++ b/_src/_layouts/photo.html @@ -23,7 +23,7 @@ layout: base {{ page.categories | category_links }}

by

-

{{ page.date | date_to_string }}

+

{{ page.date | timeago }}

diff --git a/_src/_layouts/post.html b/_src/_layouts/post.html index 4ee0912a..9329203e 100644 --- a/_src/_layouts/post.html +++ b/_src/_layouts/post.html @@ -23,9 +23,9 @@ layout: base {{ page.categories | category_links }}

-

{{ page.date | date_to_string }}

+

{{ page.date | timeago }}

{% if page.moddate %} -

updated: {{ page.moddate | date_to_string }}

+

updated: {{ page.moddate | timeago }}

{% endif %}
diff --git a/_src/_plugins/timeago.rb b/_src/_plugins/timeago.rb new file mode 100644 index 00000000..17b50dcf --- /dev/null +++ b/_src/_plugins/timeago.rb @@ -0,0 +1,109 @@ +# +# jekyll-timeago +# +# https://github.com/markets/jekyll-timeago +# + +module Jekyll + module Timeago + + DAYS_PER = { + :days => 1, + :weeks => 7, + :months => 31, + :years => 365, + } + + # Max level of detail + # years > months > weeks > days + # 1 year and 7 months and 2 weeks and 6 days + MAX_DEPTH_LEVEL = 4 + + # Default level of detail + # 1 month and 5 days, 3 weeks and 2 days, 2 years and 6 months + DEFAULT_DEPTH_LEVEL = 2 + + def timeago(input, depth = DEFAULT_DEPTH_LEVEL) + unless depth_allowed?(depth) + raise "Invalid depth level: #{depth.inspect}" + end + + unless input.is_a?(Date) || input.is_a?(Time) + raise "Invalid input type: #{input.inspect}" + end + + days_passed = (Date.today - Date.parse(input.to_s)).to_i + time_ago_to_now(days_passed, depth) + end + + private + + # Days passed to time ago sentence + def time_ago_to_now(days_passed, depth) + return "today" if days_passed == 0 + return "yesterday" if days_passed == 1 + return "tomorrow" if days_passed == -1 + + future = days_passed < 0 + slots = build_time_ago_slots(days_passed.abs, depth) + sentence = to_sentence(slots) + + if future + "in #{sentence}" + else + "#{sentence} ago" + end + end + + # Builds time ranges: ['1 month', '5 days'] + # - days_passed: integer in absolute + # - depth: level of detail + # - current_slots: built time slots + def build_time_ago_slots(days_passed, depth, current_slots = []) + return current_slots if depth == 0 || days_passed == 0 + + time_range = days_to_time_range(days_passed) + days = DAYS_PER[time_range] + num_elems = days_passed / days + range_type = if num_elems == 1 + time_range.to_s[0...-1] # singularize + else + time_range.to_s + end + + current_slots << "#{num_elems} #{range_type}" + pending_days = days_passed - (num_elems*days) + build_time_ago_slots(pending_days, depth - 1, current_slots) + end + + # Number of days to minimum period time which can be grouped + def days_to_time_range(days_passed) + case days_passed.abs + when 0...7 + :days + when 7...31 + :weeks + when 31...365 + :months + else + :years + end + end + + # Validate if allowed level of detail + def depth_allowed?(depth) + (1..MAX_DEPTH_LEVEL).include?(depth) + end + + # Array to sentence: ['1 month', '1 week', '5 days'] => "1 month, 1 week and 5 days" + def to_sentence(slots) + if slots.length == 1 + slots[0] + else + "#{slots[0...-1].join(', ')} and #{slots[-1]}" + end + end + end +end + +Liquid::Template.register_filter(Jekyll::Timeago) \ No newline at end of file