Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
galaxyproject
GitHub Repository: galaxyproject/training-material
Path: blob/main/_plugins/jekyll-duration.rb
1677 views
1
# frozen_string_literal: true
2
3
module Jekyll
4
module Filters
5
6
# This module contains a filter for converting a duration string into a human readable string.
7
module DurationFilter
8
##
9
# This function converts a duration string into a human readable string.
10
# Params:
11
# +duration+:: The duration string to convert (e.g. 1H30M, RFC 3339 formatted minus the leading P/T)
12
# Returns:
13
# +String+:: The human readable string
14
#
15
# Example:
16
# {{ "T1H30M" | duration_to_human }}
17
# => "1 hour 30 minutes"
18
def duration_to_human(duration)
19
seconds = parse_rfc3339(duration)
20
if seconds.nil?
21
return duration
22
end
23
return fmt_duration(seconds)
24
end
25
26
def fmt_duration(seconds)
27
d = resolve_hms(seconds)
28
29
# Otherwise append english terms for the various parts
30
duration_parts = []
31
32
hour = 'hour'
33
hours = 'hours'
34
minutes = 'minutes'
35
if @context.registers[:page]&.key?('lang') && (@context.registers[:page]['lang'] != 'en')
36
lang = @context.registers[:page]['lang']
37
hour = @context.registers[:site].data['lang'][lang]['hour']
38
hours = @context.registers[:site].data['lang'][lang]['hours']
39
minutes = @context.registers[:site].data['lang'][lang]['minutes']
40
end
41
42
# Hours
43
if d[:hours] > 0
44
if d[:hours] == 1
45
duration_parts.push("#{d[:hours]} " + hour)
46
else
47
duration_parts.push("#{d[:hours]} " + hours)
48
end
49
end
50
51
# Minutes - assuming no one uses `1 minute`
52
duration_parts.push("#{d[:minutes]} " + minutes) if d[:minutes] > 0
53
54
# Hopefully no one uses seconds
55
duration_parts.push("#{d[:seconds]} seconds") if d[:seconds] > 0
56
57
duration_parts.join(' ')
58
end
59
60
##
61
# Sum the durations correctly for multiple RFC3339 formatted durations.
62
# Params:
63
# +s+:: The RFC3339 formatted duration string
64
# Returns:
65
# +d+:: a number of seconds
66
def parse_rfc3339(s)
67
if s == 0
68
return 0
69
end
70
71
# Match the different parts of the string, must match entire string or it
72
# will fail.
73
match = /^T?(?:([0-9]*)[Hh])*(?:([0-9]*)[Mm])*(?:([0-9.]*)[Ss])*$/.match(s)
74
75
# If it doesn't match, pass through unedited so we don't cause unexpected
76
# issues.
77
if match.nil?
78
Jekyll.logger.debug "[GTN/Durations]:", "Could not parse time: #{s}"
79
return nil
80
end
81
82
return match[1].to_i * 3600 + match[2].to_i * 60 + match[3].to_i
83
end
84
85
##
86
# Turn a count of seconds into hours/minutes/seconds.
87
# Params:
88
# +Int+:: A number of seconds
89
# Returns:
90
# +Hash+:: A hash with keys for hours, minutes, and seconds
91
#
92
# Example:
93
# resolve_hms(5400)
94
# => { hours: 1, minutes: 30, seconds: 0 }
95
def resolve_hms(seconds)
96
# Normalize the total
97
minutes = seconds / 60
98
seconds = seconds % 60
99
hours = minutes / 60
100
minutes = minutes % 60
101
102
{ hours: hours, minutes: minutes, seconds: seconds }
103
end
104
105
##
106
# Sum the durations correctly for multiple RFC3339 formatted durations.
107
# Params:
108
# +materials+:: The GTN material objects
109
# Returns:
110
# +String+:: The human total duration
111
def sum_duration(materials)
112
Jekyll.logger.debug "[GTN/Durations]: sum durations with #{materials.length} materials."
113
total = 0
114
materials.each do |material|
115
if ! material['time_estimation'].nil?
116
Jekyll.logger.debug " [GTN/Durations]: #{material['time_estimation']} #{material['title']} -> #{parse_rfc3339(material['time_estimation'])}"
117
total += parse_rfc3339(material['time_estimation'])
118
end
119
end
120
fmt_duration(total)
121
end
122
end
123
end
124
end
125
126
Liquid::Template.register_filter(Jekyll::Filters::DurationFilter)
127
128