rails-diff-time 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/views/rails-diff-time/_diff_time.html.erb +12 -6
- data/lib/rails/diff/time/helpers.rb +211 -17
- data/lib/rails/diff/time/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9748702954e4f33f487e7ad5a8c657b89bbcc9966cfe384f0791fb2c60428b6e
|
|
4
|
+
data.tar.gz: dcd1fee4443c63efeab7d4acc4742a2e3dd9e042ec0ce4fae7a8c6fd68809e51
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3690429964d2704bf55479a1fae0083f46924a7098d3e24aa81899f3a0cebfe3f83feca3ae8ccf854e16928fae4799ce88e559561a49dc67d178d0aabb5c4aaf
|
|
7
|
+
data.tar.gz: ca7e1e72f9d52fa0da0fcceaa28921f73b90453098beea0ae7723c1bf6287cc94826a588a7bd182790871477ce6905e7a8bc20aef35fe83e39b32d663212d575
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
<%
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
element_name ||= locals[:element_name] || "span"
|
|
3
|
+
diff_time = locals[:diff_time]
|
|
4
|
+
attributes ||= locals[:attributes] || {}
|
|
5
|
+
certain_time = locals[:certain_time]
|
|
6
|
+
auto_update = locals[:auto_update]
|
|
7
|
+
|
|
8
|
+
if auto_update
|
|
9
|
+
attributes[:data] ||= {}
|
|
10
|
+
attributes[:data][:diff_time_target] = "display"
|
|
11
|
+
attributes[:data][:certain_time] = certain_time.iso8601
|
|
12
|
+
end
|
|
5
13
|
%>
|
|
6
|
-
|
|
7
|
-
<%= content_tag(_element_name.to_sym, _diff_time, _attributes) %>
|
|
8
|
-
<% end %>
|
|
14
|
+
<%= content_tag(element_name.to_sym, diff_time, attributes) %>
|
|
@@ -2,34 +2,229 @@
|
|
|
2
2
|
|
|
3
3
|
module RailsDiffTime
|
|
4
4
|
# Helper methods for displaying time differences in a human-readable format.
|
|
5
|
-
#
|
|
6
|
-
# This module provides methods to format time differences as relative strings
|
|
7
|
-
# (e.g., "2 hours ago", "3 days later") and integrates with Rails views.
|
|
8
|
-
# The helpers can be used directly in templates or through the provided
|
|
9
|
-
# render helper method.
|
|
10
|
-
#
|
|
11
|
-
# @example Usage in a Rails view
|
|
12
|
-
# <%= diff_time(user.created_at) %>
|
|
13
|
-
# <%= diff_time(event.start_time, "div", class: "timestamp") %>
|
|
14
5
|
module Helpers
|
|
15
|
-
def diff_time(certain_time, element_name = "span", attributes = {})
|
|
6
|
+
def diff_time(certain_time, element_name = "span", attributes = {}, auto_update: false)
|
|
16
7
|
return "" if certain_time.nil?
|
|
17
8
|
|
|
18
|
-
render "rails-diff-time/diff_time", locals: {
|
|
9
|
+
result = render "rails-diff-time/diff_time", locals: {
|
|
19
10
|
diff_time: diff_time_str(certain_time),
|
|
20
11
|
element_name: element_name,
|
|
21
|
-
attributes: attributes
|
|
12
|
+
attributes: attributes,
|
|
13
|
+
certain_time: certain_time,
|
|
14
|
+
auto_update: auto_update
|
|
22
15
|
}
|
|
16
|
+
|
|
17
|
+
# If auto_update is enabled and the script has not been included yet
|
|
18
|
+
if auto_update && !@_diff_time_script_included
|
|
19
|
+
@_diff_time_script_included = true
|
|
20
|
+
result = result + diff_time_script_tag
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
result
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
private
|
|
26
27
|
|
|
28
|
+
def diff_time_script_tag
|
|
29
|
+
javascript_tag do
|
|
30
|
+
<<~JAVASCRIPT.html_safe
|
|
31
|
+
(function() {
|
|
32
|
+
'use strict';
|
|
33
|
+
|
|
34
|
+
class DiffTimeUpdater {
|
|
35
|
+
constructor() {
|
|
36
|
+
this.updateInterval = 60000;
|
|
37
|
+
this.elements = [];
|
|
38
|
+
this.timerId = null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
init() {
|
|
42
|
+
this.findElements();
|
|
43
|
+
if (this.elements.length > 0) {
|
|
44
|
+
this.startAutoUpdate();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
findElements() {
|
|
49
|
+
this.elements = Array.from(
|
|
50
|
+
document.querySelectorAll('[data-diff-time-target="display"]')
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
startAutoUpdate() {
|
|
55
|
+
if (this.timerId) clearInterval(this.timerId);
|
|
56
|
+
this.timerId = setInterval(() => this.updateAll(), this.updateInterval);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
updateAll() {
|
|
60
|
+
this.elements.forEach(element => this.updateElement(element));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
updateElement(element) {
|
|
64
|
+
const certainTimeStr = element.dataset.certainTime;
|
|
65
|
+
if (!certainTimeStr) return;
|
|
66
|
+
const certainTime = new Date(certainTimeStr);
|
|
67
|
+
const diffTimeStr = this.calculateDiffTime(certainTime);
|
|
68
|
+
element.textContent = diffTimeStr;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
calculateDiffTime(certainTime) {
|
|
72
|
+
const now = new Date();
|
|
73
|
+
const diff = certainTime - now;
|
|
74
|
+
const differenceInSeconds = Math.abs(diff) / 1000;
|
|
75
|
+
|
|
76
|
+
if (differenceInSeconds <= 5) return "now";
|
|
77
|
+
|
|
78
|
+
const isLater = diff > 0;
|
|
79
|
+
|
|
80
|
+
if (differenceInSeconds >= this.yearInSeconds()) {
|
|
81
|
+
return this.formatYears(differenceInSeconds, isLater);
|
|
82
|
+
} else if (differenceInSeconds >= this.monthInSeconds()) {
|
|
83
|
+
return this.formatMonths(differenceInSeconds, isLater);
|
|
84
|
+
} else if (differenceInSeconds >= this.weekInSeconds()) {
|
|
85
|
+
return this.formatWeeks(differenceInSeconds, isLater);
|
|
86
|
+
} else if (differenceInSeconds >= this.dayInSeconds()) {
|
|
87
|
+
return this.formatDays(differenceInSeconds, isLater);
|
|
88
|
+
} else if (differenceInSeconds >= this.hourInSeconds()) {
|
|
89
|
+
return this.formatHours(differenceInSeconds, isLater);
|
|
90
|
+
} else if (differenceInSeconds >= this.minuteInSeconds()) {
|
|
91
|
+
return this.formatMinutes(differenceInSeconds, isLater);
|
|
92
|
+
} else {
|
|
93
|
+
return this.formatSeconds(differenceInSeconds, isLater);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
formatYears(seconds, isLater) {
|
|
98
|
+
const years = Math.floor(seconds / this.yearInSeconds());
|
|
99
|
+
let remaining = seconds - (years * this.yearInSeconds());
|
|
100
|
+
let result = this.timeStr(years, "year");
|
|
101
|
+
|
|
102
|
+
if (remaining >= this.monthInSeconds()) {
|
|
103
|
+
const months = Math.floor(remaining / this.monthInSeconds());
|
|
104
|
+
remaining -= months * this.monthInSeconds();
|
|
105
|
+
result += ` ${this.timeStr(months, "month")}`;
|
|
106
|
+
|
|
107
|
+
if (remaining >= this.dayInSeconds()) {
|
|
108
|
+
const days = Math.floor(remaining / this.dayInSeconds());
|
|
109
|
+
result += ` ${this.timeStr(days, "day")}`;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return `${result} ${this.agoOrLater(isLater)}`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
formatMonths(seconds, isLater) {
|
|
116
|
+
const months = Math.floor(seconds / this.monthInSeconds());
|
|
117
|
+
const remaining = seconds - (months * this.monthInSeconds());
|
|
118
|
+
let result = this.timeStr(months, "month");
|
|
119
|
+
|
|
120
|
+
if (remaining >= this.dayInSeconds()) {
|
|
121
|
+
const days = Math.floor(remaining / this.dayInSeconds());
|
|
122
|
+
result += ` ${this.timeStr(days, "day")}`;
|
|
123
|
+
}
|
|
124
|
+
return `${result} ${this.agoOrLater(isLater)}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
formatWeeks(seconds, isLater) {
|
|
128
|
+
const weeks = Math.floor(seconds / this.weekInSeconds());
|
|
129
|
+
return `${this.timeStr(weeks, "week")} ${this.agoOrLater(isLater)}`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
formatDays(seconds, isLater) {
|
|
133
|
+
const days = Math.floor(seconds / this.dayInSeconds());
|
|
134
|
+
return `${this.timeStr(days, "day")} ${this.agoOrLater(isLater)}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
formatHours(seconds, isLater) {
|
|
138
|
+
const hours = Math.floor(seconds / this.hourInSeconds());
|
|
139
|
+
const remaining = seconds - (hours * this.hourInSeconds());
|
|
140
|
+
let result = this.timeStr(hours, "hour");
|
|
141
|
+
|
|
142
|
+
if (remaining >= this.minuteInSeconds()) {
|
|
143
|
+
const minutes = Math.floor(remaining / this.minuteInSeconds());
|
|
144
|
+
result += ` ${this.timeStr(minutes, "minute")}`;
|
|
145
|
+
}
|
|
146
|
+
return `${result} ${this.agoOrLater(isLater)}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
formatMinutes(seconds, isLater) {
|
|
150
|
+
const minutes = Math.floor(seconds / this.minuteInSeconds());
|
|
151
|
+
const remaining = seconds - (minutes * this.minuteInSeconds());
|
|
152
|
+
let result = this.timeStr(minutes, "minute");
|
|
153
|
+
|
|
154
|
+
if (remaining > 0) {
|
|
155
|
+
const secs = Math.floor(remaining);
|
|
156
|
+
result += ` ${this.timeStr(secs, "second")}`;
|
|
157
|
+
}
|
|
158
|
+
return `${result} ${this.agoOrLater(isLater)}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
formatSeconds(seconds, isLater) {
|
|
162
|
+
const secs = Math.floor(seconds);
|
|
163
|
+
return `${this.timeStr(secs, "second")} ${this.agoOrLater(isLater)}`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
yearInSeconds() { return 365.25 * 24 * 3600; }
|
|
167
|
+
monthInSeconds() { return 30 * 24 * 3600; }
|
|
168
|
+
weekInSeconds() { return 7 * 24 * 3600; }
|
|
169
|
+
dayInSeconds() { return 24 * 3600; }
|
|
170
|
+
hourInSeconds() { return 3600; }
|
|
171
|
+
minuteInSeconds() { return 60; }
|
|
172
|
+
|
|
173
|
+
agoOrLater(isLater) { return isLater ? "later" : "ago"; }
|
|
174
|
+
|
|
175
|
+
timeStr(count, singular) {
|
|
176
|
+
const plural = singular + "s";
|
|
177
|
+
return `${count} ${count === 1 ? singular : plural}`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
destroy() {
|
|
181
|
+
if (this.timerId) {
|
|
182
|
+
clearInterval(this.timerId);
|
|
183
|
+
this.timerId = null;
|
|
184
|
+
}
|
|
185
|
+
this.elements = [];
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
let updater = null;
|
|
190
|
+
|
|
191
|
+
function initUpdater() {
|
|
192
|
+
if (updater) updater.destroy();
|
|
193
|
+
updater = new DiffTimeUpdater();
|
|
194
|
+
updater.init();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (document.readyState === 'loading') {
|
|
198
|
+
document.addEventListener('DOMContentLoaded', initUpdater);
|
|
199
|
+
} else {
|
|
200
|
+
initUpdater();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
document.addEventListener('turbolinks:load', initUpdater);
|
|
204
|
+
document.addEventListener('turbo:load', initUpdater);
|
|
205
|
+
|
|
206
|
+
document.addEventListener('turbolinks:before-cache', function() {
|
|
207
|
+
if (updater) updater.destroy();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
document.addEventListener('turbo:before-cache', function() {
|
|
211
|
+
if (updater) updater.destroy();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
window.RailsDiffTime = {
|
|
215
|
+
updater: updater,
|
|
216
|
+
DiffTimeUpdater: DiffTimeUpdater
|
|
217
|
+
};
|
|
218
|
+
})();
|
|
219
|
+
JAVASCRIPT
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
27
223
|
def diff_time_str(certain_time)
|
|
28
224
|
now = ::Time.now
|
|
29
225
|
diff = certain_time - now
|
|
30
226
|
difference_in_seconds = diff.abs
|
|
31
227
|
|
|
32
|
-
# Display "now" if within 5 seconds
|
|
33
228
|
return "now" if difference_in_seconds <= 5
|
|
34
229
|
|
|
35
230
|
case difference_in_seconds
|
|
@@ -120,13 +315,12 @@ module RailsDiffTime
|
|
|
120
315
|
"#{time_str(seconds, "second")} #{ago_or_later(diff)}"
|
|
121
316
|
end
|
|
122
317
|
|
|
123
|
-
# Time unit constant methods
|
|
124
318
|
def year_in_seconds
|
|
125
|
-
365.25 * 24 * 3600
|
|
319
|
+
365.25 * 24 * 3600
|
|
126
320
|
end
|
|
127
321
|
|
|
128
322
|
def month_in_seconds
|
|
129
|
-
30 * 24 * 3600
|
|
323
|
+
30 * 24 * 3600
|
|
130
324
|
end
|
|
131
325
|
|
|
132
326
|
def week_in_seconds
|
|
@@ -145,7 +339,6 @@ module RailsDiffTime
|
|
|
145
339
|
60
|
|
146
340
|
end
|
|
147
341
|
|
|
148
|
-
# Threshold methods
|
|
149
342
|
def year_threshold
|
|
150
343
|
year_in_seconds
|
|
151
344
|
end
|
|
@@ -179,3 +372,4 @@ module RailsDiffTime
|
|
|
179
372
|
end
|
|
180
373
|
end
|
|
181
374
|
end
|
|
375
|
+
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-diff-time
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- dhq_boiler
|
|
@@ -10,8 +10,10 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
description: A Rails gem that provides helper methods to display time differences
|
|
13
|
-
in a human-readable format (e.g., '2 hours ago', '3 days later').
|
|
14
|
-
|
|
13
|
+
in a human-readable format (e.g., '2 hours ago', '3 days later'). Features include
|
|
14
|
+
auto-updating timestamps every minute without page reload, no JavaScript imports
|
|
15
|
+
required, and seamless integration with Rails views. Supports various time units
|
|
16
|
+
from seconds to years.
|
|
15
17
|
email:
|
|
16
18
|
- dhq_boiler@live.jp
|
|
17
19
|
executables: []
|
|
@@ -53,5 +55,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
53
55
|
requirements: []
|
|
54
56
|
rubygems_version: 3.6.9
|
|
55
57
|
specification_version: 4
|
|
56
|
-
summary: Rails helper for displaying human-readable time differences
|
|
58
|
+
summary: Rails helper for displaying human-readable time differences with auto-update
|
|
57
59
|
test_files: []
|