dotiw 3.1.1 → 5.2.0
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 +5 -5
- data/.github/workflows/ruby.yml +45 -0
- data/.gitignore +2 -1
- data/.rspec +2 -0
- data/Appraisals +19 -0
- data/CHANGELOG.md +31 -6
- data/Gemfile +2 -0
- data/MIT-LICENSE +1 -1
- data/README.markdown +147 -62
- data/Rakefile +3 -1
- data/dotiw.gemspec +17 -17
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails_4.gemfile +9 -0
- data/gemfiles/rails_5.0.gemfile +9 -0
- data/gemfiles/rails_5.1.gemfile +9 -0
- data/gemfiles/rails_5.2.gemfile +9 -0
- data/gemfiles/rails_6.0.gemfile +9 -0
- data/lib/dotiw.rb +32 -13
- data/lib/dotiw/action_view/helpers/date_helper.rb +25 -0
- data/lib/dotiw/locale/ar.yml +104 -0
- data/lib/dotiw/locale/da.yml +35 -0
- data/lib/dotiw/locale/de.yml +36 -1
- data/lib/dotiw/locale/en.yml +35 -0
- data/lib/dotiw/locale/es.yml +36 -1
- data/lib/dotiw/locale/fr.yml +35 -0
- data/lib/dotiw/locale/id.yml +35 -0
- data/lib/dotiw/locale/it.yml +35 -0
- data/lib/dotiw/locale/ja.yml +35 -0
- data/lib/dotiw/locale/ko.yml +48 -0
- data/lib/dotiw/locale/nb.yml +36 -1
- data/lib/dotiw/locale/nl.yml +35 -0
- data/lib/dotiw/locale/pl.yml +42 -0
- data/lib/dotiw/locale/pt-BR.yml +35 -0
- data/lib/dotiw/locale/ru.yml +37 -0
- data/lib/dotiw/locale/sv.yml +48 -0
- data/lib/dotiw/locale/vi.yml +48 -0
- data/lib/dotiw/locale/zh-CN.yml +48 -0
- data/lib/dotiw/locale/zh-TW.yml +60 -0
- data/lib/dotiw/methods.rb +99 -0
- data/lib/dotiw/time_hash.rb +39 -33
- data/lib/dotiw/version.rb +2 -2
- data/spec/lib/dotiw_spec.rb +256 -157
- data/spec/lib/i18n/ar.yml +2 -0
- data/spec/lib/i18n/da.yml +2 -0
- data/spec/lib/i18n/de.yml +2 -0
- data/spec/lib/i18n/en.yml +2 -0
- data/spec/lib/i18n/es.yml +3 -0
- data/spec/lib/i18n/fr.yml +2 -0
- data/spec/lib/i18n/id.yml +2 -0
- data/spec/lib/i18n/it.yml +3 -0
- data/spec/lib/i18n/ja.yml +2 -0
- data/spec/lib/i18n/ko.yml +2 -0
- data/spec/lib/i18n/nb.yml +2 -0
- data/spec/lib/i18n/nl.yml +2 -0
- data/spec/lib/i18n/pl.yml +2 -0
- data/spec/lib/i18n/pt-BR.yml +2 -0
- data/spec/lib/i18n/ru.yml +5 -0
- data/spec/lib/i18n/sv.yml +2 -0
- data/spec/lib/i18n/vi.yml +22 -0
- data/spec/lib/i18n/zh-CN.yml +2 -0
- data/spec/lib/i18n/zh-TW.yml +2 -0
- data/spec/spec_helper.rb +2 -9
- metadata +98 -18
- data/.travis.yml +0 -11
- data/lib/dotiw/action_view_ext/helpers/date_helper.rb +0 -103
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
vi:
|
|
2
|
+
datetime:
|
|
3
|
+
dotiw:
|
|
4
|
+
seconds:
|
|
5
|
+
one: 1 giây
|
|
6
|
+
other: "%{count} giây"
|
|
7
|
+
minutes:
|
|
8
|
+
one: 1 phút
|
|
9
|
+
other: "%{count} phút"
|
|
10
|
+
hours:
|
|
11
|
+
one: 1 giờ
|
|
12
|
+
other: "%{count} giờ"
|
|
13
|
+
days:
|
|
14
|
+
one: 1 ngày
|
|
15
|
+
other: "%{count} ngày"
|
|
16
|
+
weeks:
|
|
17
|
+
one: 1 tuần
|
|
18
|
+
other: "%{count} tuần"
|
|
19
|
+
months:
|
|
20
|
+
one: 1 tháng
|
|
21
|
+
other: "%{count} tháng"
|
|
22
|
+
years:
|
|
23
|
+
one: 1 năm
|
|
24
|
+
other: "%{count} năm"
|
|
25
|
+
less_than_x: "ít hơn %{distance}"
|
|
26
|
+
dotiw_compact:
|
|
27
|
+
seconds:
|
|
28
|
+
one: 1 giây
|
|
29
|
+
other: "%{count}giây"
|
|
30
|
+
minutes:
|
|
31
|
+
one: 1 phút
|
|
32
|
+
other: "%{count}phút"
|
|
33
|
+
hours:
|
|
34
|
+
one: 1 giờ
|
|
35
|
+
other: "%{count}giờ"
|
|
36
|
+
days:
|
|
37
|
+
one: 1 ngày
|
|
38
|
+
other: "%{count}ngày"
|
|
39
|
+
weeks:
|
|
40
|
+
one: 1 tuần
|
|
41
|
+
other: "%{count}tuần"
|
|
42
|
+
months:
|
|
43
|
+
one: 1 tháng
|
|
44
|
+
other: "%{count}tháng"
|
|
45
|
+
years:
|
|
46
|
+
one: 1 năm
|
|
47
|
+
other: "%{count}năm"
|
|
48
|
+
less_than_x: "< %{distance}"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
zh-CN:
|
|
2
|
+
datetime:
|
|
3
|
+
dotiw:
|
|
4
|
+
seconds:
|
|
5
|
+
one: 1 秒
|
|
6
|
+
other: "%{count} 秒"
|
|
7
|
+
minutes:
|
|
8
|
+
one: 1 分钟
|
|
9
|
+
other: "%{count} 分钟"
|
|
10
|
+
hours:
|
|
11
|
+
one: 1 小时
|
|
12
|
+
other: "%{count} 小时"
|
|
13
|
+
days:
|
|
14
|
+
one: 1 天
|
|
15
|
+
other: "%{count} 天"
|
|
16
|
+
weeks:
|
|
17
|
+
one: 1 周
|
|
18
|
+
other: "%{count} 周"
|
|
19
|
+
months:
|
|
20
|
+
one: 1 月
|
|
21
|
+
other: "%{count} 月"
|
|
22
|
+
years:
|
|
23
|
+
one: 1 年
|
|
24
|
+
other: "%{count} 年"
|
|
25
|
+
less_than_x: "小于 %{distance}"
|
|
26
|
+
dotiw_compact:
|
|
27
|
+
seconds:
|
|
28
|
+
one: 1秒
|
|
29
|
+
other: "%{count}秒"
|
|
30
|
+
minutes:
|
|
31
|
+
one: 1分钟
|
|
32
|
+
other: "%{count}分钟"
|
|
33
|
+
hours:
|
|
34
|
+
one: 1小时
|
|
35
|
+
other: "%{count}小时"
|
|
36
|
+
days:
|
|
37
|
+
one: 1天
|
|
38
|
+
other: "%{count}天"
|
|
39
|
+
weeks:
|
|
40
|
+
one: 1周
|
|
41
|
+
other: "%{count}周"
|
|
42
|
+
months:
|
|
43
|
+
one: 1月
|
|
44
|
+
other: "%{count}月"
|
|
45
|
+
years:
|
|
46
|
+
one: 1年
|
|
47
|
+
other: "%{count}年"
|
|
48
|
+
less_than_x: "小于 %{distance}"
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
zh-TW:
|
|
2
|
+
datetime:
|
|
3
|
+
dotiw:
|
|
4
|
+
seconds:
|
|
5
|
+
one: 1 秒
|
|
6
|
+
other: "%{count} 秒"
|
|
7
|
+
minutes:
|
|
8
|
+
one: 1 分鐘
|
|
9
|
+
other: "%{count} 分鐘"
|
|
10
|
+
hours:
|
|
11
|
+
one: 1 小時
|
|
12
|
+
other: "%{count} 小時"
|
|
13
|
+
days:
|
|
14
|
+
one: 1 天
|
|
15
|
+
other: "%{count} 天"
|
|
16
|
+
weeks:
|
|
17
|
+
one: 1 週
|
|
18
|
+
other: "%{count} 週"
|
|
19
|
+
months:
|
|
20
|
+
one: 1 月
|
|
21
|
+
other: "%{count} 月"
|
|
22
|
+
years:
|
|
23
|
+
one: 1 年
|
|
24
|
+
other: "%{count} 年"
|
|
25
|
+
less_than_x: "小於 %{distance}"
|
|
26
|
+
dotiw_compact:
|
|
27
|
+
seconds:
|
|
28
|
+
one: 1秒
|
|
29
|
+
other: "%{count}秒"
|
|
30
|
+
minutes:
|
|
31
|
+
one: 1分鐘
|
|
32
|
+
other: "%{count}分鐘"
|
|
33
|
+
hours:
|
|
34
|
+
one: 1小時
|
|
35
|
+
other: "%{count}小時"
|
|
36
|
+
days:
|
|
37
|
+
one: 1天
|
|
38
|
+
other: "%{count}天"
|
|
39
|
+
weeks:
|
|
40
|
+
one: 1週
|
|
41
|
+
other: "%{count}週"
|
|
42
|
+
months:
|
|
43
|
+
one: 1月
|
|
44
|
+
other: "%{count}月"
|
|
45
|
+
years:
|
|
46
|
+
one: 1年
|
|
47
|
+
other: "%{count}年"
|
|
48
|
+
less_than_x: "小於%{distance}"
|
|
49
|
+
words_connector: ""
|
|
50
|
+
two_words_connector: ""
|
|
51
|
+
last_word_connector: ""
|
|
52
|
+
about_x_years:
|
|
53
|
+
one: 約1年
|
|
54
|
+
any: "約%{count}年"
|
|
55
|
+
over_x_years:
|
|
56
|
+
one: "大於1年"
|
|
57
|
+
other: "大於%{count}年"
|
|
58
|
+
almost_x_years:
|
|
59
|
+
one: 將近1年
|
|
60
|
+
any: "將近%{count}年"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DOTIW
|
|
4
|
+
module Methods
|
|
5
|
+
extend self
|
|
6
|
+
|
|
7
|
+
def distance_of_time_in_words_hash(from_time, to_time, options = {})
|
|
8
|
+
from_time = from_time.to_time if !from_time.is_a?(Time) && from_time.respond_to?(:to_time)
|
|
9
|
+
to_time = to_time.to_time if !to_time.is_a?(Time) && to_time.respond_to?(:to_time)
|
|
10
|
+
|
|
11
|
+
DOTIW::TimeHash.new(nil, from_time, to_time, options).to_hash
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def distance_of_time(seconds, options = {})
|
|
15
|
+
options[:include_seconds] ||= true
|
|
16
|
+
_display_time_in_words DOTIW::TimeHash.new(seconds, nil, nil, options_with_scope(options)).to_hash, options
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def distance_of_time_in_words(from_time, to_time = 0, include_seconds_or_options = {}, options = {})
|
|
20
|
+
if include_seconds_or_options.is_a?(Hash)
|
|
21
|
+
options = include_seconds_or_options
|
|
22
|
+
else
|
|
23
|
+
options[:include_seconds] ||= !!include_seconds_or_options
|
|
24
|
+
end
|
|
25
|
+
return distance_of_time(from_time, options) if to_time == 0
|
|
26
|
+
|
|
27
|
+
options = options_with_scope(options)
|
|
28
|
+
hash = distance_of_time_in_words_hash(from_time, to_time, options)
|
|
29
|
+
_display_time_in_words(hash, options)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def time_ago_in_words(from_time, include_seconds_or_options = {})
|
|
33
|
+
distance_of_time_in_words(from_time, Time.current, include_seconds_or_options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def options_with_scope(options)
|
|
39
|
+
options.merge!({:scope => DOTIW::DEFAULT_I18N_SCOPE_COMPACT}) if options.delete(:compact)
|
|
40
|
+
options
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def _display_time_in_words(hash, options = {})
|
|
44
|
+
options.reverse_merge!(
|
|
45
|
+
include_seconds: false
|
|
46
|
+
).symbolize_keys!
|
|
47
|
+
|
|
48
|
+
include_seconds = options.delete(:include_seconds)
|
|
49
|
+
hash.delete(:seconds) if !include_seconds && hash[:minutes]
|
|
50
|
+
|
|
51
|
+
options[:except] = Array.wrap(options[:except]).map!(&:to_sym) if options[:except]
|
|
52
|
+
options[:only] = Array.wrap(options[:only]).map!(&:to_sym) if options[:only]
|
|
53
|
+
|
|
54
|
+
# Remove all the values that are nil or excluded. Keep the required ones.
|
|
55
|
+
hash.delete_if do |key, value|
|
|
56
|
+
value.nil? || value.zero? ||
|
|
57
|
+
options[:except]&.include?(key) ||
|
|
58
|
+
(options[:only] && !options[:only].include?(key))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
i18n_scope = options.delete(:scope) || DOTIW::DEFAULT_I18N_SCOPE
|
|
62
|
+
if hash.empty?
|
|
63
|
+
fractions = DOTIW::TimeHash::TIME_FRACTIONS
|
|
64
|
+
fractions &= options[:only] if options[:only]
|
|
65
|
+
fractions -= options[:except] if options[:except]
|
|
66
|
+
|
|
67
|
+
I18n.with_options locale: options[:locale], scope: i18n_scope do |locale|
|
|
68
|
+
# e.g. try to format 'less than 1 days', fallback to '0 days'
|
|
69
|
+
return locale.translate :less_than_x,
|
|
70
|
+
distance: locale.translate(fractions.first, count: 1),
|
|
71
|
+
default: locale.translate(fractions.first, count: 0)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
output = []
|
|
76
|
+
I18n.with_options locale: options[:locale], scope: i18n_scope do |locale|
|
|
77
|
+
output = hash.map { |key, value| locale.t(key, count: value) }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
options.delete(:except)
|
|
81
|
+
options.delete(:only)
|
|
82
|
+
highest_measures = options.delete(:highest_measures)
|
|
83
|
+
highest_measures = 1 if options.delete(:highest_measure_only)
|
|
84
|
+
output = output[0...highest_measures] if highest_measures
|
|
85
|
+
|
|
86
|
+
options[:words_connector] ||= I18n.translate :"#{i18n_scope}.words_connector",
|
|
87
|
+
default: :'support.array.words_connector',
|
|
88
|
+
locale: options[:locale]
|
|
89
|
+
options[:two_words_connector] ||= I18n.translate :"#{i18n_scope}.two_words_connector",
|
|
90
|
+
default: :'support.array.two_words_connector',
|
|
91
|
+
locale: options[:locale]
|
|
92
|
+
options[:last_word_connector] ||= I18n.translate :"#{i18n_scope}.last_word_connector",
|
|
93
|
+
default: :'support.array.last_word_connector',
|
|
94
|
+
locale: options[:locale]
|
|
95
|
+
|
|
96
|
+
output.to_sentence(options)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end # DOTIW
|
data/lib/dotiw/time_hash.rb
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module DOTIW
|
|
4
4
|
class TimeHash
|
|
5
|
-
TIME_FRACTIONS = [
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def initialize(distance, from_time
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
TIME_FRACTIONS = %i[seconds minutes hours days weeks months years].freeze
|
|
6
|
+
|
|
7
|
+
attr_reader :distance, :smallest, :largest, :from_time, :to_time
|
|
8
|
+
|
|
9
|
+
def initialize(distance, from_time, to_time = nil, options = {})
|
|
10
|
+
@output = {}
|
|
11
|
+
@options = options
|
|
12
|
+
@distance = distance
|
|
13
|
+
@from_time = from_time || Time.current
|
|
14
|
+
@to_time = to_time || (@to_time_not_given = true && @from_time + distance.seconds)
|
|
15
|
+
@smallest, @largest = [@from_time, @to_time].minmax
|
|
16
|
+
@to_time += 1.hour if @to_time_not_given && smallest.dst? && !largest.dst?
|
|
17
|
+
@to_time -= 1.hour if @to_time_not_given && !smallest.dst? && largest.dst?
|
|
18
|
+
@smallest, @largest = [@from_time, @to_time].minmax
|
|
19
|
+
@distance ||= begin
|
|
20
20
|
d = largest - smallest
|
|
21
|
-
d -= 1.hour if
|
|
22
|
-
d += 1.hour if !
|
|
21
|
+
d -= 1.hour if smallest.dst? && !largest.dst?
|
|
22
|
+
d += 1.hour if !smallest.dst? && largest.dst?
|
|
23
23
|
d
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -30,16 +30,16 @@ module DOTIW
|
|
|
30
30
|
output
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
attr_reader :options, :output
|
|
35
36
|
|
|
36
37
|
def build_time_hash
|
|
37
38
|
if accumulate_on = options.delete(:accumulate_on)
|
|
38
39
|
accumulate_on = accumulate_on.to_sym
|
|
39
|
-
if accumulate_on == :years
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
TIME_FRACTIONS.index(accumulate_on).downto(0) { |i| self.send("build_#{TIME_FRACTIONS[i]}") }
|
|
40
|
+
return build_time_hash if accumulate_on == :years
|
|
41
|
+
|
|
42
|
+
TIME_FRACTIONS.index(accumulate_on).downto(0) { |i| send("build_#{TIME_FRACTIONS[i]}") }
|
|
43
43
|
else
|
|
44
44
|
while distance > 0
|
|
45
45
|
if distance < 1.minute
|
|
@@ -63,23 +63,23 @@ module DOTIW
|
|
|
63
63
|
|
|
64
64
|
def build_seconds
|
|
65
65
|
output[:seconds] = distance.to_i
|
|
66
|
-
|
|
66
|
+
@distance = 0
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def build_minutes
|
|
70
|
-
output[:minutes],
|
|
70
|
+
output[:minutes], @distance = distance.divmod(1.minute.to_i)
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def build_hours
|
|
74
|
-
output[:hours],
|
|
74
|
+
output[:hours], @distance = distance.divmod(1.hour.to_i)
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def build_days
|
|
78
|
-
output[:days],
|
|
78
|
+
output[:days], @distance = distance.divmod(1.day.to_i) unless output[:days]
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def build_weeks
|
|
82
|
-
output[:weeks],
|
|
82
|
+
output[:weeks], @distance = distance.divmod(1.week.to_i) unless output[:weeks]
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def build_months
|
|
@@ -97,7 +97,7 @@ module DOTIW
|
|
|
97
97
|
days = largest.day - smallest.day
|
|
98
98
|
|
|
99
99
|
weeks, days = days.divmod(7)
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
# Will otherwise incorrectly say one more day if our range goes over a day.
|
|
102
102
|
days -= 1 if largest.hour < smallest.hour
|
|
103
103
|
|
|
@@ -110,7 +110,7 @@ module DOTIW
|
|
|
110
110
|
if weeks < 0
|
|
111
111
|
# Convert the last month to a week and add to total
|
|
112
112
|
months -= 1
|
|
113
|
-
last_month = largest.advance(:
|
|
113
|
+
last_month = largest.advance(months: -1)
|
|
114
114
|
days_in_month = Time.days_in_month(last_month.month, last_month.year)
|
|
115
115
|
weeks += days_in_month / 7
|
|
116
116
|
days += days_in_month % 7
|
|
@@ -118,6 +118,12 @@ module DOTIW
|
|
|
118
118
|
days -= 7
|
|
119
119
|
weeks += 1
|
|
120
120
|
end
|
|
121
|
+
|
|
122
|
+
if weeks == -1
|
|
123
|
+
months -= 1
|
|
124
|
+
weeks = 4
|
|
125
|
+
days -= 4
|
|
126
|
+
end
|
|
121
127
|
end
|
|
122
128
|
|
|
123
129
|
if months < 0
|
|
@@ -131,9 +137,9 @@ module DOTIW
|
|
|
131
137
|
output[:weeks] = weeks
|
|
132
138
|
output[:days] = days
|
|
133
139
|
|
|
134
|
-
total_days,
|
|
140
|
+
total_days, @distance = distance.abs.divmod(1.day.to_i)
|
|
135
141
|
|
|
136
|
-
[total_days,
|
|
142
|
+
[total_days, @distance]
|
|
137
143
|
end
|
|
138
144
|
end # TimeHash
|
|
139
145
|
end # DOTIW
|
data/lib/dotiw/version.rb
CHANGED
data/spec/lib/dotiw_spec.rb
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
|
-
describe
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
describe 'A better distance_of_time_in_words' do
|
|
6
|
+
if defined?(ActionView)
|
|
7
|
+
include ActionView::Helpers::DateHelper
|
|
8
|
+
include ActionView::Helpers::TextHelper
|
|
9
|
+
include ActionView::Helpers::NumberHelper
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
require 'action_controller'
|
|
12
|
+
else
|
|
13
|
+
include DOTIW::Methods
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
START_TIME = '01-08-2009'.to_time
|
|
11
17
|
|
|
12
18
|
before do
|
|
13
19
|
I18n.locale = :en
|
|
@@ -15,57 +21,57 @@ describe "A better distance_of_time_in_words" do
|
|
|
15
21
|
allow(Time.zone).to receive(:now).and_return(START_TIME)
|
|
16
22
|
end
|
|
17
23
|
|
|
18
|
-
describe
|
|
19
|
-
|
|
20
|
-
[0.5.minutes, "30 seconds"],
|
|
21
|
-
[4.5.minutes, "4 minutes and 30 seconds"],
|
|
22
|
-
[5.minutes.to_i, "5 minutes"],
|
|
23
|
-
[10.minutes.to_i, "10 minutes"],
|
|
24
|
-
[1.hour.to_i, "1 hour"],
|
|
25
|
-
[1.hour + 30.seconds, "1 hour and 30 seconds"],
|
|
26
|
-
[4.weeks.to_i, "4 weeks"],
|
|
27
|
-
[4.weeks + 2.days, "4 weeks and 2 days"],
|
|
28
|
-
[24.weeks.to_i, "5 months, 2 weeks, and 1 day"]
|
|
29
|
-
]
|
|
30
|
-
fragments.each do |number, result|
|
|
24
|
+
describe '#distance_of_time' do
|
|
25
|
+
[
|
|
26
|
+
[0.5.minutes, "30 seconds", "30s"],
|
|
27
|
+
[4.5.minutes, "4 minutes and 30 seconds", "4m30s"],
|
|
28
|
+
[5.minutes.to_i, "5 minutes", "5m"],
|
|
29
|
+
[10.minutes.to_i, "10 minutes", "10m"],
|
|
30
|
+
[1.hour.to_i, "1 hour", "1h"],
|
|
31
|
+
[1.hour + 30.seconds, "1 hour and 30 seconds", "1h30s"],
|
|
32
|
+
[4.weeks.to_i, "4 weeks", "4w"],
|
|
33
|
+
[4.weeks + 2.days, "4 weeks and 2 days", "4w2d"],
|
|
34
|
+
[24.weeks.to_i, "5 months, 2 weeks, and 1 day", "5mo2w1d"]
|
|
35
|
+
].each do |number, result, compact_result|
|
|
31
36
|
it "#{number} == #{result}" do
|
|
32
37
|
expect(distance_of_time(number)).to eq(result)
|
|
38
|
+
expect(distance_of_time(number, compact: true)).to eq(compact_result)
|
|
33
39
|
end
|
|
34
40
|
end
|
|
35
41
|
|
|
36
|
-
describe
|
|
37
|
-
it
|
|
38
|
-
expect(distance_of_time(1.2.minute, except: 'seconds')).to eq(
|
|
39
|
-
expect(distance_of_time(2.5.hours + 30.seconds, except: 'seconds')).to eq(
|
|
42
|
+
describe 'with options' do
|
|
43
|
+
it 'except:seconds should skip seconds' do
|
|
44
|
+
expect(distance_of_time(1.2.minute, except: 'seconds')).to eq('1 minute')
|
|
45
|
+
expect(distance_of_time(2.5.hours + 30.seconds, except: 'seconds')).to eq('2 hours and 30 minutes')
|
|
40
46
|
end
|
|
41
47
|
|
|
42
|
-
it
|
|
48
|
+
it 'except:seconds has higher precedence than include_seconds:true' do
|
|
43
49
|
expect(distance_of_time(1.2.minute, include_seconds: true, except: 'seconds')).to eq('1 minute')
|
|
44
50
|
end
|
|
45
51
|
end
|
|
46
|
-
|
|
47
52
|
end
|
|
48
53
|
|
|
49
|
-
describe
|
|
50
|
-
describe
|
|
51
|
-
|
|
52
|
-
[:years, :months, :weeks, :days, :minutes, :seconds].each do |name|
|
|
54
|
+
describe '#distance_of_time_in_words_hash' do
|
|
55
|
+
describe 'giving correct numbers of' do
|
|
56
|
+
%i[years months weeks days minutes seconds].each do |name|
|
|
53
57
|
describe name do
|
|
54
|
-
it
|
|
58
|
+
it 'exactly' do
|
|
55
59
|
hash = distance_of_time_in_words_hash(START_TIME, START_TIME + 1.send(name))
|
|
56
60
|
expect(hash[name]).to eq(1)
|
|
57
61
|
end
|
|
58
62
|
|
|
59
|
-
it
|
|
63
|
+
it 'two' do
|
|
60
64
|
hash = distance_of_time_in_words_hash(START_TIME, START_TIME + 2.send(name))
|
|
61
65
|
expect(hash[name]).to eq(2)
|
|
62
66
|
end
|
|
63
67
|
end
|
|
64
68
|
end
|
|
65
69
|
|
|
66
|
-
it
|
|
67
|
-
hash = distance_of_time_in_words_hash(
|
|
68
|
-
|
|
70
|
+
it 'should be happy with lots of measurements' do
|
|
71
|
+
hash = distance_of_time_in_words_hash(
|
|
72
|
+
START_TIME,
|
|
73
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds
|
|
74
|
+
)
|
|
69
75
|
expect(hash[:years]).to eq(1)
|
|
70
76
|
expect(hash[:months]).to eq(2)
|
|
71
77
|
expect(hash[:weeks]).to eq(3)
|
|
@@ -77,214 +83,307 @@ describe "A better distance_of_time_in_words" do
|
|
|
77
83
|
end
|
|
78
84
|
end
|
|
79
85
|
|
|
80
|
-
describe
|
|
81
|
-
it
|
|
82
|
-
expect(
|
|
83
|
-
expect(distance_of_time_in_words(START_TIME, START_TIME + 5.days, :locale => :es)).to eq("5 días")
|
|
86
|
+
describe '#time_ago_in_words' do
|
|
87
|
+
it 'aliases to distance_of_time_in_words' do
|
|
88
|
+
expect(time_ago_in_words(Time.now - 3.days - 14.minutes)).to eq('3 days and 14 minutes')
|
|
84
89
|
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe '#distance_of_time_in_words' do
|
|
93
|
+
context 'locale' do
|
|
94
|
+
it 'includes known languages' do
|
|
95
|
+
expect(DOTIW.languages).to include :en
|
|
96
|
+
expect(DOTIW.languages).to include :ru
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'includes all the languages in specs' do
|
|
100
|
+
languages = Dir[File.join(File.dirname(__FILE__), 'i18n', '*.yml')].map { |f| File.basename(f, '.yml') }
|
|
101
|
+
expect(DOTIW.languages.map(&:to_s).sort).to eq languages.sort
|
|
102
|
+
end
|
|
85
103
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
104
|
+
DOTIW.languages.each do |lang|
|
|
105
|
+
context lang do
|
|
106
|
+
YAML.safe_load(
|
|
107
|
+
File.read(
|
|
108
|
+
File.join(
|
|
109
|
+
File.dirname(__FILE__), 'i18n', "#{lang}.yml"
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
).each_pair do |category, fixtures|
|
|
113
|
+
context category do
|
|
114
|
+
fixtures.each_pair do |k, v|
|
|
115
|
+
it v do
|
|
116
|
+
expect(
|
|
117
|
+
distance_of_time_in_words(
|
|
118
|
+
START_TIME,
|
|
119
|
+
START_TIME + eval(k),
|
|
120
|
+
true,
|
|
121
|
+
locale: lang
|
|
122
|
+
)
|
|
123
|
+
).to eq(v)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
89
130
|
end
|
|
90
131
|
|
|
91
|
-
|
|
92
|
-
[START_TIME, START_TIME + 5.days + 3.minutes,
|
|
93
|
-
[START_TIME, START_TIME + 1.minute,
|
|
94
|
-
[START_TIME, START_TIME + 3.years,
|
|
95
|
-
[START_TIME, START_TIME + 10.years,
|
|
96
|
-
[START_TIME, START_TIME + 8.months,
|
|
97
|
-
[START_TIME, START_TIME + 3.hour,
|
|
98
|
-
[START_TIME, START_TIME + 13.months,
|
|
132
|
+
[
|
|
133
|
+
[START_TIME, START_TIME + 5.days + 3.minutes, '5 days and 3 minutes'],
|
|
134
|
+
[START_TIME, START_TIME + 1.minute, '1 minute'],
|
|
135
|
+
[START_TIME, START_TIME + 3.years, '3 years'],
|
|
136
|
+
[START_TIME, START_TIME + 10.years, '10 years'],
|
|
137
|
+
[START_TIME, START_TIME + 8.months, '8 months'],
|
|
138
|
+
[START_TIME, START_TIME + 3.hour, '3 hours'],
|
|
139
|
+
[START_TIME, START_TIME + 13.months, '1 year and 1 month'],
|
|
99
140
|
# Any numeric sequence is merely coincidental.
|
|
100
|
-
[START_TIME, START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
101
|
-
[
|
|
102
|
-
[
|
|
103
|
-
[
|
|
104
|
-
[
|
|
105
|
-
[
|
|
106
|
-
|
|
107
|
-
|
|
141
|
+
[START_TIME, START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds, '1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'],
|
|
142
|
+
['2009-3-16'.to_time, '2008-4-14'.to_time, '11 months and 2 days'],
|
|
143
|
+
['2009-3-16'.to_time + 1.minute, '2008-4-14'.to_time, '11 months, 2 days, and 1 minute'],
|
|
144
|
+
['2009-4-14'.to_time, '2008-3-16'.to_time, '1 year, 4 weeks, and 1 day'],
|
|
145
|
+
['2009-2-01'.to_time, '2009-3-01'.to_time, '1 month'],
|
|
146
|
+
['2008-2-01'.to_time, '2008-3-01'.to_time, '1 month'],
|
|
147
|
+
[Date.parse('31.03.2015').to_time, Time.parse('01.03.2016'), '10 months, 4 weeks, and 2 days'],
|
|
148
|
+
[Date.new(2014, 1, 31), Date.new(2014, 3, 1), '4 weeks and 1 day'],
|
|
149
|
+
['2008-2-01'.to_time, '2008-3-01'.to_time, '1 month'],
|
|
150
|
+
['2014-1-31'.to_time, '2014-3-01'.to_time, '4 weeks and 1 day'],
|
|
151
|
+
['2014-1-31'.to_time, '2014-3-02'.to_time, '4 weeks and 2 days'],
|
|
152
|
+
['2016-1-31'.to_time, '2016-3-01'.to_time, '4 weeks and 2 days'],
|
|
153
|
+
['2016-1-31'.to_time, '2016-3-02'.to_time, '1 month']
|
|
154
|
+
].each do |start, finish, output|
|
|
108
155
|
it "should be #{output}" do
|
|
109
156
|
expect(distance_of_time_in_words(start, finish, true)).to eq(output)
|
|
157
|
+
expect(distance_of_time_in_words(finish, start, true)).to eq(output)
|
|
110
158
|
end
|
|
111
159
|
end
|
|
112
160
|
|
|
113
|
-
|
|
114
|
-
|
|
161
|
+
[
|
|
162
|
+
[Time.zone.now, Time.zone.now + 1.day - 1.minute, '23 hours and 59 minutes'],
|
|
163
|
+
[Time.zone.now, Time.zone.now + 15.days - 1.minute, '14 days, 23 hours, and 59 minutes'],
|
|
164
|
+
[Time.zone.now, Time.zone.now + 29.days - 1.minute, '28 days, 23 hours, and 59 minutes'],
|
|
165
|
+
[Time.zone.now, Time.zone.now + 30.days - 1.minute, '29 days, 23 hours, and 59 minutes'],
|
|
166
|
+
[Time.zone.now, Time.zone.now + 31.days - 1.minute, '30 days, 23 hours, and 59 minutes'],
|
|
167
|
+
[Time.zone.now, Time.zone.now + 32.days - 1.minute, '31 days, 23 hours, and 59 minutes'],
|
|
168
|
+
[Time.zone.now, Time.zone.now + 33.days - 1.minute, '32 days, 23 hours, and 59 minutes']
|
|
169
|
+
].each do |start, finish, output|
|
|
170
|
+
it "should be #{output}" do
|
|
171
|
+
expect(distance_of_time_in_words(start, finish, accumulate_on: 'days')).to eq(output)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
[
|
|
176
|
+
[Time.at(1), Time.at(100), '1 minute'],
|
|
177
|
+
[DateTime.now, DateTime.now + 1.minute, '1 minute'],
|
|
178
|
+
[Date.new(2000, 1, 2), Date.new(2000, 1, 3), '1 day'],
|
|
179
|
+
[Time.at(DateTime.now), DateTime.now + 1.minute, '1 minute']
|
|
180
|
+
].each do |start, finish, output|
|
|
181
|
+
it "should be #{output}" do
|
|
182
|
+
expect(distance_of_time_in_words(start, finish)).to eq(output)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
describe 'accumulate_on:' do
|
|
187
|
+
[
|
|
115
188
|
[START_TIME,
|
|
116
189
|
START_TIME + 10.minute,
|
|
117
190
|
:seconds,
|
|
118
|
-
|
|
191
|
+
'600 seconds'],
|
|
119
192
|
[START_TIME,
|
|
120
193
|
START_TIME + 10.hour + 10.minute + 1.second,
|
|
121
194
|
:minutes,
|
|
122
|
-
|
|
195
|
+
'610 minutes and 1 second'],
|
|
123
196
|
[START_TIME,
|
|
124
|
-
START_TIME + 2.day +
|
|
197
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
|
125
198
|
:hours,
|
|
126
|
-
|
|
199
|
+
'10048 hours and 10 seconds'],
|
|
127
200
|
[START_TIME,
|
|
128
|
-
START_TIME + 2.day +
|
|
201
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
|
129
202
|
:days,
|
|
130
|
-
|
|
203
|
+
'418 days, 16 hours, and 10 seconds'],
|
|
131
204
|
[START_TIME,
|
|
132
|
-
START_TIME + 2.day +
|
|
205
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
|
133
206
|
:weeks,
|
|
134
|
-
|
|
207
|
+
'59 weeks, 5 days, 16 hours, and 10 seconds'],
|
|
135
208
|
[START_TIME,
|
|
136
|
-
START_TIME + 2.day +
|
|
209
|
+
START_TIME + 2.day + 10_000.hour + 10.second,
|
|
137
210
|
:months,
|
|
138
|
-
|
|
139
|
-
[
|
|
140
|
-
|
|
141
|
-
]
|
|
142
|
-
fragments.each do |start, finish, accumulator, output|
|
|
211
|
+
'13 months, 3 weeks, 1 day, 16 hours, and 10 seconds'],
|
|
212
|
+
['2015-1-15'.to_time, '2016-3-15'.to_time, :months, '14 months']
|
|
213
|
+
].each do |start, finish, accumulator, output|
|
|
143
214
|
it "should be #{output}" do
|
|
144
|
-
expect(distance_of_time_in_words(start, finish, true, :
|
|
215
|
+
expect(distance_of_time_in_words(start, finish, true, accumulate_on: accumulator)).to eq(output)
|
|
145
216
|
end
|
|
146
217
|
end
|
|
147
218
|
end # :accumulate_on
|
|
148
219
|
|
|
149
|
-
describe
|
|
220
|
+
describe 'without finish time' do
|
|
150
221
|
# A missing finish argument should default to zero, essentially returning
|
|
151
222
|
# the equivalent of distance_of_time in order to be backwards-compatible
|
|
152
223
|
# with the original rails distance_of_time_in_words helper.
|
|
153
|
-
|
|
154
|
-
[5.minutes.to_i,
|
|
155
|
-
[10.minutes.to_i,
|
|
156
|
-
[1.hour.to_i,
|
|
157
|
-
[6.days.to_i,
|
|
158
|
-
[4.weeks.to_i,
|
|
159
|
-
[24.weeks.to_i,
|
|
160
|
-
]
|
|
161
|
-
fragments.each do |start, output|
|
|
224
|
+
[
|
|
225
|
+
[5.minutes.to_i, '5 minutes'],
|
|
226
|
+
[10.minutes.to_i, '10 minutes'],
|
|
227
|
+
[1.hour.to_i, '1 hour'],
|
|
228
|
+
[6.days.to_i, '6 days'],
|
|
229
|
+
[4.weeks.to_i, '4 weeks'],
|
|
230
|
+
[24.weeks.to_i, '5 months, 2 weeks, and 1 day']
|
|
231
|
+
].each do |start, output|
|
|
162
232
|
it "should be #{output}" do
|
|
163
233
|
expect(distance_of_time_in_words(start)).to eq(output)
|
|
164
234
|
end
|
|
165
235
|
end
|
|
166
236
|
end
|
|
167
|
-
|
|
168
237
|
end
|
|
169
238
|
|
|
170
|
-
describe
|
|
171
|
-
|
|
239
|
+
describe 'with output options' do
|
|
240
|
+
[
|
|
172
241
|
# Any numeric sequence is merely coincidental.
|
|
173
242
|
[START_TIME,
|
|
174
243
|
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
175
|
-
{ :
|
|
176
|
-
|
|
244
|
+
{ words_connector: ' - ' },
|
|
245
|
+
'1 year - 2 months - 3 weeks - 4 days - 5 hours - 6 minutes, and 7 seconds'],
|
|
177
246
|
[START_TIME,
|
|
178
247
|
START_TIME + 5.minutes + 6.seconds,
|
|
179
|
-
{ :
|
|
180
|
-
|
|
248
|
+
{ two_words_connector: ' - ' },
|
|
249
|
+
'5 minutes - 6 seconds'],
|
|
181
250
|
[START_TIME,
|
|
182
|
-
START_TIME + 4.hours +
|
|
183
|
-
{ :
|
|
184
|
-
|
|
251
|
+
START_TIME + 4.hours + 5.minutes + 6.seconds,
|
|
252
|
+
{ last_word_connector: ' - ' },
|
|
253
|
+
'4 hours, 5 minutes - 6 seconds'],
|
|
185
254
|
[START_TIME,
|
|
186
255
|
START_TIME + 1.year + 2.months + 3.days + 4.hours + 5.minutes + 6.seconds,
|
|
187
|
-
{ :
|
|
188
|
-
|
|
256
|
+
{ except: 'minutes' },
|
|
257
|
+
'1 year, 2 months, 3 days, 4 hours, and 6 seconds'],
|
|
189
258
|
[START_TIME,
|
|
190
259
|
START_TIME + 1.hour + 1.minute,
|
|
191
|
-
{ :
|
|
260
|
+
{ except: 'minutes' }, '1 hour'],
|
|
192
261
|
[START_TIME,
|
|
193
262
|
START_TIME + 1.hour + 1.day + 1.minute,
|
|
194
|
-
{ :
|
|
195
|
-
|
|
263
|
+
{ except: %w[minutes hours] },
|
|
264
|
+
'1 day'],
|
|
196
265
|
[START_TIME,
|
|
197
266
|
START_TIME + 1.hour + 1.day + 1.minute,
|
|
198
|
-
{ :
|
|
199
|
-
|
|
200
|
-
[START_TIME,
|
|
201
|
-
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
202
|
-
{ :vague => true },
|
|
203
|
-
"about 1 year"],
|
|
204
|
-
[START_TIME,
|
|
205
|
-
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
206
|
-
{ :vague => "Yes please" },
|
|
207
|
-
"about 1 year"],
|
|
208
|
-
[START_TIME,
|
|
209
|
-
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
210
|
-
{ :vague => false },
|
|
211
|
-
"1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds"],
|
|
212
|
-
[START_TIME,
|
|
213
|
-
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
214
|
-
{ :vague => nil },
|
|
215
|
-
"1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds"],
|
|
267
|
+
{ only: %w[minutes hours] },
|
|
268
|
+
'1 hour and 1 minute'],
|
|
216
269
|
[START_TIME,
|
|
217
270
|
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
218
|
-
{ :
|
|
219
|
-
|
|
271
|
+
{ except: 'minutes' },
|
|
272
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, and 7 seconds'],
|
|
220
273
|
[START_TIME,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
274
|
+
START_TIME + 1.hour + 2.minutes + 3.seconds,
|
|
275
|
+
{ highest_measure_only: true },
|
|
276
|
+
'1 hour'],
|
|
224
277
|
[START_TIME,
|
|
225
278
|
START_TIME + 1.hours + 2.minutes + 3.seconds,
|
|
226
|
-
{ :
|
|
227
|
-
|
|
279
|
+
{ highest_measures: 1 },
|
|
280
|
+
'1 hour'],
|
|
228
281
|
[START_TIME,
|
|
229
282
|
START_TIME + 2.year + 3.months + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
230
|
-
{ :
|
|
231
|
-
|
|
283
|
+
{ highest_measures: 3 },
|
|
284
|
+
'2 years, 3 months, and 4 days'],
|
|
232
285
|
[START_TIME,
|
|
233
286
|
START_TIME + 2.year + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
234
|
-
{ :
|
|
235
|
-
|
|
287
|
+
{ highest_measures: 2 },
|
|
288
|
+
'2 years and 3 weeks'],
|
|
236
289
|
[START_TIME,
|
|
237
290
|
START_TIME + 4.days + 6.minutes + 7.seconds,
|
|
238
|
-
{ :
|
|
239
|
-
|
|
291
|
+
{ highest_measures: 3 },
|
|
292
|
+
'4 days, 6 minutes, and 7 seconds'],
|
|
240
293
|
[START_TIME,
|
|
241
294
|
START_TIME + 1.year + 2.weeks,
|
|
242
|
-
{ :
|
|
243
|
-
|
|
295
|
+
{ highest_measures: 3 },
|
|
296
|
+
'1 year and 2 weeks'],
|
|
244
297
|
[START_TIME,
|
|
245
298
|
START_TIME + 1.days,
|
|
246
|
-
{ :
|
|
247
|
-
|
|
299
|
+
{ only: %i[years months] },
|
|
300
|
+
'less than 1 month'],
|
|
248
301
|
[START_TIME,
|
|
249
302
|
START_TIME + 5.minutes,
|
|
250
|
-
{ :
|
|
251
|
-
|
|
303
|
+
{ except: %i[hours minutes seconds] },
|
|
304
|
+
'less than 1 day'],
|
|
252
305
|
[START_TIME,
|
|
253
306
|
START_TIME + 1.days,
|
|
254
|
-
{ :
|
|
255
|
-
|
|
256
|
-
]
|
|
257
|
-
fragments.each do |start, finish, options, output|
|
|
307
|
+
{ highest_measures: 1, only: %i[years months] },
|
|
308
|
+
'less than 1 month']
|
|
309
|
+
].each do |start, finish, options, output|
|
|
258
310
|
it "should be #{output}" do
|
|
259
311
|
expect(distance_of_time_in_words(start, finish, true, options)).to eq(output)
|
|
260
312
|
end
|
|
261
313
|
end
|
|
262
314
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
315
|
+
if defined?(ActionView)
|
|
316
|
+
describe 'ActionView' do
|
|
317
|
+
[
|
|
318
|
+
[START_TIME,
|
|
319
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
320
|
+
{ vague: true },
|
|
321
|
+
'about 1 year'],
|
|
322
|
+
[START_TIME,
|
|
323
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
324
|
+
{ vague: 'Yes please' },
|
|
325
|
+
'about 1 year'],
|
|
326
|
+
[START_TIME,
|
|
327
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
328
|
+
{ vague: false },
|
|
329
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'],
|
|
330
|
+
[START_TIME,
|
|
331
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
332
|
+
{ vague: nil },
|
|
333
|
+
'1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds']
|
|
334
|
+
].each do |start, finish, options, output|
|
|
335
|
+
it "should be #{output}" do
|
|
336
|
+
expect(distance_of_time_in_words(start, finish, true, options)).to eq(output)
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
context 'via ActionController::Base.helpers' do
|
|
341
|
+
it '#distance_of_time_in_words' do
|
|
342
|
+
end_time = START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds
|
|
343
|
+
expected = '1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds'
|
|
344
|
+
actual = ActionController::Base.helpers.distance_of_time_in_words(START_TIME, end_time, true, { vague: false })
|
|
345
|
+
expect(actual).to eq(expected)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it '#time_ago_in_words' do
|
|
349
|
+
expected = '3 days and 14 minutes'
|
|
350
|
+
actual = ActionController::Base.helpers.time_ago_in_words(Time.now - 3.days - 14.minutes)
|
|
351
|
+
expect(actual).to eq(expected)
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
describe 'include_seconds' do
|
|
358
|
+
it 'is ignored if only seconds have passed' do
|
|
359
|
+
expect(distance_of_time_in_words(START_TIME, START_TIME + 1.second, false)).to eq('1 second')
|
|
266
360
|
end
|
|
267
361
|
|
|
268
|
-
it
|
|
269
|
-
expect(
|
|
270
|
-
|
|
271
|
-
|
|
362
|
+
it 'removes seconds in all other cases' do
|
|
363
|
+
expect(
|
|
364
|
+
distance_of_time_in_words(
|
|
365
|
+
START_TIME,
|
|
366
|
+
START_TIME + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds,
|
|
367
|
+
false
|
|
368
|
+
)
|
|
369
|
+
).to eq('1 year, 2 months, 3 weeks, 4 days, 5 hours, and 6 minutes')
|
|
272
370
|
end
|
|
273
371
|
end # include_seconds
|
|
274
372
|
end
|
|
275
373
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
374
|
+
if defined?(ActionView)
|
|
375
|
+
describe 'percentage of time' do
|
|
376
|
+
def time_in_percent(options = {})
|
|
377
|
+
distance_of_time_in_percent('04-12-2009'.to_time, '29-01-2010'.to_time, '04-12-2010'.to_time, options)
|
|
378
|
+
end
|
|
280
379
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
380
|
+
it 'calculates 15%' do
|
|
381
|
+
expect(time_in_percent).to eq('15%')
|
|
382
|
+
end
|
|
284
383
|
|
|
285
|
-
|
|
286
|
-
|
|
384
|
+
it 'calculates 15.3%' do
|
|
385
|
+
expect(time_in_percent(precision: 1)).to eq('15.3%')
|
|
386
|
+
end
|
|
287
387
|
end
|
|
288
388
|
end
|
|
289
|
-
|
|
290
389
|
end
|