Path: blob/main/_plugins/jekyll-duration.rb
1677 views
# frozen_string_literal: true12module Jekyll3module Filters45# This module contains a filter for converting a duration string into a human readable string.6module DurationFilter7##8# This function converts a duration string into a human readable string.9# Params:10# +duration+:: The duration string to convert (e.g. 1H30M, RFC 3339 formatted minus the leading P/T)11# Returns:12# +String+:: The human readable string13#14# Example:15# {{ "T1H30M" | duration_to_human }}16# => "1 hour 30 minutes"17def duration_to_human(duration)18seconds = parse_rfc3339(duration)19if seconds.nil?20return duration21end22return fmt_duration(seconds)23end2425def fmt_duration(seconds)26d = resolve_hms(seconds)2728# Otherwise append english terms for the various parts29duration_parts = []3031hour = 'hour'32hours = 'hours'33minutes = 'minutes'34if @context.registers[:page]&.key?('lang') && (@context.registers[:page]['lang'] != 'en')35lang = @context.registers[:page]['lang']36hour = @context.registers[:site].data['lang'][lang]['hour']37hours = @context.registers[:site].data['lang'][lang]['hours']38minutes = @context.registers[:site].data['lang'][lang]['minutes']39end4041# Hours42if d[:hours] > 043if d[:hours] == 144duration_parts.push("#{d[:hours]} " + hour)45else46duration_parts.push("#{d[:hours]} " + hours)47end48end4950# Minutes - assuming no one uses `1 minute`51duration_parts.push("#{d[:minutes]} " + minutes) if d[:minutes] > 05253# Hopefully no one uses seconds54duration_parts.push("#{d[:seconds]} seconds") if d[:seconds] > 05556duration_parts.join(' ')57end5859##60# Sum the durations correctly for multiple RFC3339 formatted durations.61# Params:62# +s+:: The RFC3339 formatted duration string63# Returns:64# +d+:: a number of seconds65def parse_rfc3339(s)66if s == 067return 068end6970# Match the different parts of the string, must match entire string or it71# will fail.72match = /^T?(?:([0-9]*)[Hh])*(?:([0-9]*)[Mm])*(?:([0-9.]*)[Ss])*$/.match(s)7374# If it doesn't match, pass through unedited so we don't cause unexpected75# issues.76if match.nil?77Jekyll.logger.debug "[GTN/Durations]:", "Could not parse time: #{s}"78return nil79end8081return match[1].to_i * 3600 + match[2].to_i * 60 + match[3].to_i82end8384##85# Turn a count of seconds into hours/minutes/seconds.86# Params:87# +Int+:: A number of seconds88# Returns:89# +Hash+:: A hash with keys for hours, minutes, and seconds90#91# Example:92# resolve_hms(5400)93# => { hours: 1, minutes: 30, seconds: 0 }94def resolve_hms(seconds)95# Normalize the total96minutes = seconds / 6097seconds = seconds % 6098hours = minutes / 6099minutes = minutes % 60100101{ hours: hours, minutes: minutes, seconds: seconds }102end103104##105# Sum the durations correctly for multiple RFC3339 formatted durations.106# Params:107# +materials+:: The GTN material objects108# Returns:109# +String+:: The human total duration110def sum_duration(materials)111Jekyll.logger.debug "[GTN/Durations]: sum durations with #{materials.length} materials."112total = 0113materials.each do |material|114if ! material['time_estimation'].nil?115Jekyll.logger.debug " [GTN/Durations]: #{material['time_estimation']} #{material['title']} -> #{parse_rfc3339(material['time_estimation'])}"116total += parse_rfc3339(material['time_estimation'])117end118end119fmt_duration(total)120end121end122end123end124125Liquid::Template.register_filter(Jekyll::Filters::DurationFilter)126127128