rails-diff-time 0.1.3 → 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/engine.rb +1 -1
- data/lib/rails/diff/time/helpers.rb +213 -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,32 +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 = {})
|
|
16
|
-
|
|
6
|
+
def diff_time(certain_time, element_name = "span", attributes = {}, auto_update: false)
|
|
7
|
+
return "" if certain_time.nil?
|
|
8
|
+
|
|
9
|
+
result = render "rails-diff-time/diff_time", locals: {
|
|
17
10
|
diff_time: diff_time_str(certain_time),
|
|
18
11
|
element_name: element_name,
|
|
19
|
-
attributes: attributes
|
|
12
|
+
attributes: attributes,
|
|
13
|
+
certain_time: certain_time,
|
|
14
|
+
auto_update: auto_update
|
|
20
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
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
private
|
|
24
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
|
+
|
|
25
223
|
def diff_time_str(certain_time)
|
|
26
224
|
now = ::Time.now
|
|
27
225
|
diff = certain_time - now
|
|
28
226
|
difference_in_seconds = diff.abs
|
|
29
227
|
|
|
30
|
-
# Display "now" if within 5 seconds
|
|
31
228
|
return "now" if difference_in_seconds <= 5
|
|
32
229
|
|
|
33
230
|
case difference_in_seconds
|
|
@@ -118,13 +315,12 @@ module RailsDiffTime
|
|
|
118
315
|
"#{time_str(seconds, "second")} #{ago_or_later(diff)}"
|
|
119
316
|
end
|
|
120
317
|
|
|
121
|
-
# Time unit constant methods
|
|
122
318
|
def year_in_seconds
|
|
123
|
-
365.25 * 24 * 3600
|
|
319
|
+
365.25 * 24 * 3600
|
|
124
320
|
end
|
|
125
321
|
|
|
126
322
|
def month_in_seconds
|
|
127
|
-
30 * 24 * 3600
|
|
323
|
+
30 * 24 * 3600
|
|
128
324
|
end
|
|
129
325
|
|
|
130
326
|
def week_in_seconds
|
|
@@ -143,7 +339,6 @@ module RailsDiffTime
|
|
|
143
339
|
60
|
|
144
340
|
end
|
|
145
341
|
|
|
146
|
-
# Threshold methods
|
|
147
342
|
def year_threshold
|
|
148
343
|
year_in_seconds
|
|
149
344
|
end
|
|
@@ -177,3 +372,4 @@ module RailsDiffTime
|
|
|
177
372
|
end
|
|
178
373
|
end
|
|
179
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: []
|