Skip to content

Commit c0e1202

Browse files
author
Tony Levi
authored
Merge pull request #23 from sealink/TT-6441-import-timedifference
Tt 6441 import timedifference
2 parents 23b6a8d + 1a5d5a3 commit c0e1202

7 files changed

Lines changed: 293 additions & 2 deletions

File tree

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
language: ruby
22
rvm:
33
- 2.6
4+
- 2.7
45
matrix:
56
fast_finish: true
67
before_install:

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
* [TT-6441] Due to TimeDifference being unmaintained bring it into the timely library
6+
37
## 0.6.0
48

59
* [TT-6402] Require date group weekdays bit field to be not null/nil

gemfiles/rails6.gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ source 'https://rubygems.org'
44
gemspec path: '../'
55

66
group :development, :test do
7-
gem 'activerecord', '~> 6.0.0.rc1'
7+
gem 'activerecord', '~> 6.0'
88
end

lib/timely/rails.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
require 'timely/rails/date'
1313
require 'timely/rails/period'
1414
require 'timely/rails/time'
15+
require 'timely/rails/time_difference'
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# frozen_string_literal: true
2+
3+
require 'rubygems'
4+
require 'active_support/all'
5+
6+
module Timely
7+
class TimeDifference
8+
private_class_method :new
9+
10+
TIME_COMPONENTS = %i[years months weeks days hours minutes seconds].freeze
11+
12+
def self.between(start_time, end_time)
13+
new(start_time, end_time)
14+
end
15+
16+
def in_years
17+
in_component(:years)
18+
end
19+
20+
def in_months
21+
(@time_diff / (1.day * 30.42)).round(2)
22+
end
23+
24+
def in_weeks
25+
in_component(:weeks)
26+
end
27+
28+
def in_days
29+
in_component(:days)
30+
end
31+
32+
def in_hours
33+
in_component(:hours)
34+
end
35+
36+
def in_minutes
37+
in_component(:minutes)
38+
end
39+
40+
def in_seconds
41+
@time_diff
42+
end
43+
44+
def in_each_component
45+
Hash[TIME_COMPONENTS.map do |time_component|
46+
[time_component, public_send("in_#{time_component}")]
47+
end]
48+
end
49+
50+
def in_general
51+
remaining = @time_diff
52+
Hash[TIME_COMPONENTS.map do |time_component|
53+
if remaining > 0
54+
rounded_time_component = (remaining / 1.send(time_component).seconds).round(2).floor
55+
remaining -= rounded_time_component.send(time_component)
56+
[time_component, rounded_time_component]
57+
else
58+
[time_component, 0]
59+
end
60+
end]
61+
end
62+
63+
def humanize
64+
diff_parts = []
65+
in_general.each do |part, quantity|
66+
next if quantity <= 0
67+
68+
part = part.to_s.humanize
69+
70+
part = part.singularize if quantity <= 1
71+
72+
diff_parts << "#{quantity} #{part}"
73+
end
74+
75+
last_part = diff_parts.pop
76+
if diff_parts.empty?
77+
last_part
78+
else
79+
[diff_parts.join(', '), last_part].join(' and ')
80+
end
81+
end
82+
83+
private
84+
85+
def initialize(start_time, end_time)
86+
start_time = time_in_seconds(start_time)
87+
end_time = time_in_seconds(end_time)
88+
89+
@time_diff = (end_time - start_time).abs
90+
end
91+
92+
def time_in_seconds(time)
93+
time.to_time.to_f
94+
end
95+
96+
def in_component(component)
97+
(@time_diff / 1.send(component)).round(2)
98+
end
99+
end
100+
end

spec/rails/time_difference_spec.rb

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper'
4+
5+
describe Timely::TimeDifference do
6+
def self.with_each_class(&block)
7+
classes = [Time, Date, DateTime]
8+
9+
classes.each do |clazz|
10+
context "with a #{clazz.name} class" do
11+
instance_exec clazz, &block
12+
end
13+
end
14+
end
15+
16+
describe '.between' do
17+
with_each_class do |clazz|
18+
it 'returns a new TimeDifference instance in each component' do
19+
start_time = clazz.new(2011, 1)
20+
end_time = clazz.new(2011, 12)
21+
22+
expect(Timely::TimeDifference.between(start_time, end_time)).to be_a(Timely::TimeDifference)
23+
end
24+
end
25+
end
26+
27+
describe '#in_each_component' do
28+
with_each_class do |clazz|
29+
it 'returns time difference in each component' do
30+
start_time = clazz.new(2011, 1)
31+
end_time = clazz.new(2011, 12)
32+
33+
expect(Timely::TimeDifference.between(start_time, end_time).in_each_component).to eql(years: 0.91, months: 10.98, weeks: 47.71, days: 334.0, hours: 8016.0, minutes: 480_960.0, seconds: 28_857_600.0)
34+
end
35+
end
36+
end
37+
38+
describe '#in_general' do
39+
with_each_class do |clazz|
40+
it 'returns time difference in general that matches the total seconds' do
41+
start_time = clazz.new(2009, 11)
42+
end_time = clazz.new(2011, 1)
43+
44+
expect(Timely::TimeDifference.between(start_time, end_time).in_general).to eql(years: 1, months: 2, weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0)
45+
end
46+
end
47+
end
48+
49+
describe '#humanize' do
50+
with_each_class do |clazz|
51+
it 'returns a string representing the time difference from in_general' do
52+
start_time = clazz.new(2009, 11)
53+
end_time = clazz.new(2011, 1)
54+
55+
expect(Timely::TimeDifference.between(start_time, end_time).humanize).to eql('1 Year and 2 Months')
56+
end
57+
end
58+
end
59+
60+
describe '#in_years' do
61+
with_each_class do |clazz|
62+
it 'returns time difference in years based on Wolfram Alpha' do
63+
start_time = clazz.new(2011, 1)
64+
end_time = clazz.new(2011, 12)
65+
66+
expect(Timely::TimeDifference.between(start_time, end_time).in_years).to eql(0.91)
67+
end
68+
69+
it 'returns an absolute difference' do
70+
start_time = clazz.new(2011, 12)
71+
end_time = clazz.new(2011, 1)
72+
73+
expect(Timely::TimeDifference.between(start_time, end_time).in_years).to eql(0.91)
74+
end
75+
end
76+
end
77+
78+
describe '#in_months' do
79+
with_each_class do |clazz|
80+
it 'returns time difference in months based on Wolfram Alpha' do
81+
start_time = clazz.new(2011, 1)
82+
end_time = clazz.new(2011, 12)
83+
84+
expect(Timely::TimeDifference.between(start_time, end_time).in_months).to eql(10.98)
85+
end
86+
87+
it 'returns an absolute difference' do
88+
start_time = clazz.new(2011, 12)
89+
end_time = clazz.new(2011, 1)
90+
91+
expect(Timely::TimeDifference.between(start_time, end_time).in_months).to eql(10.98)
92+
end
93+
end
94+
end
95+
96+
describe '#in_weeks' do
97+
with_each_class do |clazz|
98+
it 'returns time difference in weeks based on Wolfram Alpha' do
99+
start_time = clazz.new(2011, 1)
100+
end_time = clazz.new(2011, 12)
101+
102+
expect(Timely::TimeDifference.between(start_time, end_time).in_weeks).to eql(47.71)
103+
end
104+
105+
it 'returns an absolute difference' do
106+
start_time = clazz.new(2011, 12)
107+
end_time = clazz.new(2011, 1)
108+
109+
expect(Timely::TimeDifference.between(start_time, end_time).in_weeks).to eql(47.71)
110+
end
111+
end
112+
end
113+
114+
describe '#in_days' do
115+
with_each_class do |clazz|
116+
it 'returns time difference in weeks based on Wolfram Alpha' do
117+
start_time = clazz.new(2011, 1)
118+
end_time = clazz.new(2011, 12)
119+
120+
expect(Timely::TimeDifference.between(start_time, end_time).in_days).to eql(334.0)
121+
end
122+
123+
it 'returns an absolute difference' do
124+
start_time = clazz.new(2011, 12)
125+
end_time = clazz.new(2011, 1)
126+
127+
expect(Timely::TimeDifference.between(start_time, end_time).in_days).to eql(334.0)
128+
end
129+
end
130+
end
131+
132+
describe '#in_hours' do
133+
with_each_class do |clazz|
134+
it 'returns time difference in hours based on Wolfram Alpha' do
135+
start_time = clazz.new(2011, 1)
136+
end_time = clazz.new(2011, 12)
137+
138+
expect(Timely::TimeDifference.between(start_time, end_time).in_hours).to eql(8016.0)
139+
end
140+
141+
it 'returns an absolute difference' do
142+
start_time = clazz.new(2011, 12)
143+
end_time = clazz.new(2011, 1)
144+
145+
expect(Timely::TimeDifference.between(start_time, end_time).in_hours).to eql(8016.0)
146+
end
147+
end
148+
end
149+
150+
describe '#in_minutes' do
151+
with_each_class do |clazz|
152+
it 'returns time difference in minutes based on Wolfram Alpha' do
153+
start_time = clazz.new(2011, 1)
154+
end_time = clazz.new(2011, 12)
155+
156+
expect(Timely::TimeDifference.between(start_time, end_time).in_minutes).to eql(480_960.0)
157+
end
158+
159+
it 'returns an absolute difference' do
160+
start_time = clazz.new(2011, 12)
161+
end_time = clazz.new(2011, 1)
162+
163+
expect(Timely::TimeDifference.between(start_time, end_time).in_minutes).to eql(480_960.0)
164+
end
165+
end
166+
end
167+
168+
describe '#in_seconds' do
169+
with_each_class do |clazz|
170+
it 'returns time difference in seconds based on Wolfram Alpha' do
171+
start_time = clazz.new(2011, 1)
172+
end_time = clazz.new(2011, 12)
173+
174+
expect(Timely::TimeDifference.between(start_time, end_time).in_seconds).to eql(28_857_600.0)
175+
end
176+
177+
it 'returns an absolute difference' do
178+
start_time = clazz.new(2011, 12)
179+
end_time = clazz.new(2011, 1)
180+
181+
expect(Timely::TimeDifference.between(start_time, end_time).in_seconds).to eql(28_857_600.0)
182+
end
183+
end
184+
end
185+
end

spec/support/coverage_loader.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
require 'simplecov-rcov'
44
require 'coveralls'
55
require 'coverage/kit'
6-
Coverage::Kit.setup(minimum_coverage: 70.15)
6+
Coverage::Kit.setup(minimum_coverage: 72.0)

0 commit comments

Comments
 (0)