delta_t 0.0.1

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.
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ .idea/
20
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in delta_t.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tim 'S.D.Eagle' Zeitz
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,90 @@
1
+ # DeltaT
2
+
3
+ DeltaT provides an interface to represent time differences and make duration calculations nice and easy.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'delta_t'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install delta_t
18
+
19
+ ## Usage
20
+
21
+ DeltaT hooks into the Time class and overrides the - operator.
22
+
23
+ diff = (Time.now - 2.days.ago)
24
+ diff.class # => TimeDiff
25
+
26
+ The TimeDiff class provides accessors for Years, Months, Days, Hours, Minutes and Seconds
27
+
28
+ diff.days # => 2
29
+
30
+ The differences will always be normalized - you will never get something like 48 hours.
31
+ For the total amount of something
32
+
33
+ diff.total_hours # => 48
34
+
35
+ Furthermore either all time amounts will be positive or negative
36
+
37
+ diff = Time.new(2012, 2) - Time.new(2011, 11)
38
+ diff.years # => 0
39
+ diff.months # => 3
40
+
41
+ diff = Time.new(2011, 11) - Time.new(2012, 2)
42
+ diff.years # => 0
43
+ diff.months # => -3
44
+
45
+ You can create TimeDiffs with the differences of two times or with a hash
46
+
47
+ diff = TimeDiff.new(hours: 1, seconds: 5)
48
+ diff.seconds # => 5
49
+ diff.total_seconds # => 3605
50
+
51
+ and you can a hash back out of the TimeDiff
52
+
53
+ diff.to_hash # => {years: 0, months: 0, days: 0, hours: 1, minutes: 0, seconds: 5}
54
+
55
+ You can do calculations with TimeDiffs
56
+
57
+ diff = TimeDiff.new(days: 2) + TimeDiff.new(months: 3)
58
+ diff.days # => 2
59
+ diff.months # => 3
60
+
61
+ diff - TimeDiff.new(days: 2).days # => 0
62
+
63
+ diff * -1 == -diff # => true
64
+
65
+ When calculating a TimeDiff from two Time the day - month foobar will be handled correctly
66
+
67
+ (Time.new(2012,4,2) - Time.new(2012,3,31)).days # => 2
68
+
69
+ but if you do any further calculations since the concrete month is unknown a month will always have 30 days.
70
+
71
+ You can apply TimeDiffs to Time objects
72
+
73
+ Time.new(2012, 4, 5) + TimeDiff.new(days: 30) == Time.new(2012, 4, 5) + 30.days # => true
74
+
75
+ Concluding: the following equation should always be true
76
+
77
+ (sometime - othertime) + othertime == sometime # => true
78
+
79
+
80
+ The TimeDiff class is in the DeltaT Module so normally you would have to use DeltaT::TimeDiff
81
+ For further examples have a look into the tests
82
+
83
+
84
+ ## Contributing
85
+
86
+ 1. Fork it
87
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
88
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
89
+ 4. Push to the branch (`git push origin my-new-feature`)
90
+ 5. Create new Pull Request
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.pattern = 'test/**/*_test.rb'
9
+ end
10
+
11
+ desc "Run tests"
12
+ task :default => :test
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/delta_t/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Tim 'S.D.Eagle' Zeitz"]
6
+ gem.email = ["dev.tim.zeitz@gmail.com"]
7
+ gem.description = %q{Making time difference calculations fun}
8
+ gem.summary = %q{Provides a class to represent time differences and make duration calculations nice and easy}
9
+ gem.homepage = "https://github.com/SDEagle/delta_t"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "delta_t"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = DeltaT::VERSION
17
+
18
+ gem.add_development_dependency 'rake'
19
+
20
+ gem.add_runtime_dependency 'activesupport'
21
+ end
@@ -0,0 +1,7 @@
1
+ require 'active_support/all'
2
+ require 'delta_t/version'
3
+ require 'delta_t/time_diff'
4
+ require 'delta_t/time'
5
+
6
+ module DeltaT
7
+ end
@@ -0,0 +1,22 @@
1
+ class Time
2
+ old_plus = instance_method :+
3
+ old_minus = instance_method :-
4
+
5
+ define_method :+ do |other|
6
+ if other.class == DeltaT::TimeDiff
7
+ other + self
8
+ else
9
+ old_plus.bind(self).(other)
10
+ end
11
+ end
12
+
13
+ define_method :- do |other|
14
+ if other.class == DeltaT::TimeDiff
15
+ (other*-1) + self
16
+ elsif other.respond_to? :to_time
17
+ DeltaT::TimeDiff.new self, other
18
+ else
19
+ old_minus.bind(self).(other)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,163 @@
1
+ module DeltaT
2
+ class TimeDiff
3
+ UNITS = [:n_secs, :seconds, :minutes, :hours, :days, :months, :years]
4
+
5
+ ##
6
+ # Create a new TimeDiff either by two Time like objects or an hash with values for the time units (keys: seconds, minutes, hours, days, months, years)
7
+ def initialize *args
8
+ if args.size == 1 && args[0].class == Hash
9
+ @diff = [0,0,0,0,0,0,0]
10
+ add_array [0, args[0][:seconds], args[0][:minutes], args[0][:hours], args[0][:days], args[0][:months], args[0][:years]]
11
+ elsif args.size == 2 && args[0].respond_to?(:to_time) && args[1].respond_to?(:to_time)
12
+ apply_time_diff args[0].to_time, args[1].to_time
13
+ else
14
+ raise ArgumentError, "Arguments neither two times nor a hash", caller
15
+ end
16
+ end
17
+
18
+ UNITS.each_index do |index|
19
+ define_method UNITS[index] do
20
+ @diff[index]
21
+ end
22
+ end
23
+
24
+ UNITS.each_index do |index|
25
+ unless index == 0
26
+ define_method ("total_" + UNITS[index].to_s).to_sym do
27
+ sum = 0
28
+ i = index
29
+ while i < UNITS.length
30
+ sum += @diff[i].send UNITS[i]
31
+ i += 1
32
+ end
33
+ sum / 1.send(UNITS[index])
34
+ end
35
+ end
36
+ end
37
+
38
+ ##
39
+ # checks if two TimeDiffs are equal
40
+ def == other
41
+ eql = true
42
+ UNITS.each do |unit|
43
+ eql &= send(unit) == other.send(unit)
44
+ end
45
+ eql
46
+ end
47
+
48
+ ##
49
+ # Either adds two TimeDiffs together or advances a time by this TimeDiff
50
+ def + other
51
+ if other.class == TimeDiff
52
+ TimeDiff.new(other.to_hash).add_array @diff
53
+ elsif other.respond_to? :to_time
54
+ other.to_time.advance self.to_hash
55
+ else
56
+ raise ArgumentError, "Addition only defined for TimeDiff and time like classes", caller
57
+ end
58
+ end
59
+
60
+ ##
61
+ # Subtracts the other TimeDiff from this one
62
+ def - other
63
+ if other.class == TimeDiff
64
+ self + (-other)
65
+ else
66
+ raise ArgumentError, "Only subtraction of TimeDiffs possible", caller
67
+ end
68
+ end
69
+
70
+ ##
71
+ # multiplies the duration of this TimeDiff with the given scalar. Must be an integer
72
+ def * scalar
73
+ unless scalar.integer?
74
+ raise ArgumentError, "Only integer calculations possible", caller
75
+ end
76
+ h = to_hash
77
+ h.each { |k, v| h[k] = v * scalar }
78
+ result = TimeDiff.new h
79
+ result.normalize!
80
+ end
81
+
82
+ ##
83
+ # Equivalent to *-1
84
+ def -@
85
+ self * -1
86
+ end
87
+
88
+ ##
89
+ # Returns an integer representing this TimeDiff - the total number of seconds
90
+ def to_i
91
+ total_seconds
92
+ end
93
+
94
+ ##
95
+ # Returns an float representing this TimeDiff - the total number of seconds with smaller units as decimals
96
+ def to_f
97
+ to_i.to_f + @diff[0] * 0.000000001
98
+ end
99
+
100
+ def coerce other
101
+ return other, self.to_f
102
+ end
103
+
104
+ ##
105
+ # Returns an hash with all different time durations with each ones value
106
+ def to_hash
107
+ h = {}
108
+ UNITS.each do |unit|
109
+ h[unit] = send(unit)
110
+ end
111
+ h
112
+ end
113
+
114
+ protected
115
+
116
+ def apply_time_diff ending, start
117
+ @diff = [ending.nsec - start.nsec, ending.sec - start.sec, ending.min - start.min, ending.hour - start.hour, ending.day - start.day, ending.month - start.month, ending.year - start.year]
118
+ normalize! start
119
+ end
120
+
121
+ def add_array array
122
+ array.each_index do |i|
123
+ @diff[i] += array[i] unless array[i].nil?
124
+ end
125
+ normalize!
126
+ end
127
+
128
+ def normalize! base_date=nil, recalculate=false
129
+ if base_date && recalculate
130
+ ending = base_date + self
131
+ apply_time_diff ending, base_date
132
+ else
133
+ switched = false
134
+ if total_seconds < 0
135
+ @diff.collect! { |t| t * -1 }
136
+ switched = true
137
+ end
138
+
139
+ @diff.each_index do |index|
140
+ (index+1...UNITS.length).to_a.each do |unit|
141
+ base = TimeDiff.get_ratio UNITS[unit], UNITS[index], base_date
142
+ @diff[unit] += @diff[index] / base
143
+ @diff[index] %= base
144
+ end
145
+ end
146
+
147
+ @diff.collect! { |t| t * -1 } if switched
148
+ self
149
+ end
150
+ end
151
+
152
+ def self.get_ratio numerator_unit, denominator_unit, base_date=nil
153
+ if base_date && numerator_unit == :months && denominator_unit == :days
154
+ Time.days_in_month base_date.month, base_date.year
155
+ elsif denominator_unit == :n_secs
156
+ (1.send(numerator_unit) * 1000000000).round
157
+ else
158
+ (1.send(numerator_unit) / 1.send(denominator_unit)).round
159
+ end
160
+ end
161
+
162
+ end
163
+ end
@@ -0,0 +1,3 @@
1
+ module DeltaT
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,86 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class DeltaT::TimeDiff
4
+ # exposing internals for better testing
5
+ # nano secs are ignored cause they are just implemented for compatibility with old play time diff
6
+ # current implementation: [y,m,d,h,m,s]
7
+ def diff
8
+ @diff.reverse[0..-2]
9
+ end
10
+ end
11
+
12
+ class DeltaTTest < Test::Unit::TestCase
13
+
14
+ # caution - depends on current time so if buggy non deterministic
15
+ def test_simple_difference
16
+ now = Time.now
17
+ dif = DeltaT::TimeDiff.new(now, now - (1.days + 3.hours))
18
+ assert_equal 0, dif.years
19
+ assert_equal 0, dif.months
20
+ assert_equal 1, dif.days
21
+ assert_equal 3, dif.hours
22
+ assert_equal 0, dif.minutes
23
+ assert_equal 0, dif.seconds
24
+ end
25
+
26
+ def test_overlapping_difference
27
+ assert_equal [0,0,0,0,0,2], DeltaT::TimeDiff.new(Time.new(2000, 1, 1, 0, 1 , 1), Time.new(2000, 1, 1, 0, 0, 59)).diff
28
+ assert_equal [0,0,2,0,0,0], DeltaT::TimeDiff.new(Time.new(2000, 2, 1), Time.new(2000, 1, 30)).diff
29
+ end
30
+
31
+ def test_negative_difference
32
+ assert_equal [1, 2, 10, 0, 3, 2], DeltaT::TimeDiff.new(Time.new(2001, 6, 15, 10, 4, 1), Time.new(2000, 4, 5, 10, 0, 59)).diff
33
+ assert_equal [-1, -2, -10, 0, -3, -2], DeltaT::TimeDiff.new(Time.new(2000, 4, 5, 10, 0, 59), Time.new(2001, 6, 15, 10, 4, 1)).diff
34
+ end
35
+
36
+ def test_init
37
+ assert_equal [1,2,3,4,5,6], DeltaT::TimeDiff.new(years: 1, months: 2, days: 3, hours: 4, minutes: 5, seconds: 6).diff
38
+ assert_equal [1,0,3,0,0,0], DeltaT::TimeDiff.new(years: 1, days: 3).diff
39
+ assert_equal [1,0,0,0,0,0], DeltaT::TimeDiff.new(years: 1).diff
40
+ end
41
+
42
+ def test_equals
43
+ t = DeltaT::TimeDiff.new(years: 1, months: 2, days: 3, hours: 4, minutes: 5, seconds: 6)
44
+ assert t == t
45
+ assert t != -t
46
+ end
47
+
48
+ def test_total
49
+ assert_equal 48, DeltaT::TimeDiff.new(days: 2).total_hours
50
+ assert_equal 62, DeltaT::TimeDiff.new(months: 2, days: 2).total_days
51
+ dif = DeltaT::TimeDiff.new(months: 2, days: 2, hours: 5, minutes: 7, seconds: 1)
52
+ assert_equal 62, dif.total_days
53
+ assert_equal 5375221, dif.total_seconds
54
+ end
55
+
56
+ def test_normalization
57
+ assert_equal [0,1,21,0,0,0], DeltaT::TimeDiff.new(days: 51).diff
58
+ assert_equal [0,1,10,18,5,0], DeltaT::TimeDiff.new(minutes: 60*24*40 + 60*18 + 5).diff
59
+ assert_equal [0,-1,-10,-18,-5,0], DeltaT::TimeDiff.new(minutes: -(60*24*40 + 60*18 + 5)).diff
60
+ end
61
+
62
+ def test_to_hash
63
+ h = {years: 1, months: 2, days: 3, hours: 4, minutes: 5, seconds: 6, n_secs: 0}
64
+ assert_equal h, DeltaT::TimeDiff.new(h).to_hash
65
+ end
66
+
67
+ def test_operators
68
+ assert_equal [1,3,0,0,0,0], (DeltaT::TimeDiff.new(months: 11) + DeltaT::TimeDiff.new(months: 4)).diff
69
+ assert_equal [0,7,0,0,0,0], (DeltaT::TimeDiff.new(months: 11) - DeltaT::TimeDiff.new(months: 4)).diff
70
+ assert_equal [2,9,0,0,0,0], (DeltaT::TimeDiff.new(months: 11) * 3).diff
71
+ end
72
+
73
+ def test_time_operators
74
+ before = Time.new 2001, 4, 3, 12, 23, 55
75
+ after = Time.new 2012, 12, 21, 0, 0, 0
76
+ assert_equal after, before + DeltaT::TimeDiff.new(after, before)
77
+ assert_equal after, DeltaT::TimeDiff.new(after, before) + before
78
+ assert_equal before, after - DeltaT::TimeDiff.new(after, before)
79
+ assert_equal before, -DeltaT::TimeDiff.new(after, before) + after
80
+
81
+ assert_equal after, before + (after - before)
82
+ assert_equal after, after - before + before
83
+ assert_equal before, after - (after - before)
84
+ assert_equal before, -(after - before) + after
85
+ end
86
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ require 'delta_t'
15
+
16
+ class Test::Unit::TestCase
17
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: delta_t
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tim 'S.D.Eagle' Zeitz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: activesupport
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Making time difference calculations fun
47
+ email:
48
+ - dev.tim.zeitz@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - delta_t.gemspec
59
+ - lib/delta_t.rb
60
+ - lib/delta_t/time.rb
61
+ - lib/delta_t/time_diff.rb
62
+ - lib/delta_t/version.rb
63
+ - test/delta_t_test.rb
64
+ - test/helper.rb
65
+ homepage: https://github.com/SDEagle/delta_t
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.24
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Provides a class to represent time differences and make duration calculations
89
+ nice and easy
90
+ test_files:
91
+ - test/delta_t_test.rb
92
+ - test/helper.rb