units-time 0.0.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3894ab823f4d595259a95b23637fa877737a7632
4
- data.tar.gz: d9a684989b45c322a6ad86af619ca107a9d588eb
3
+ metadata.gz: cd753e92ae05a7b8124067b1530096616392cb33
4
+ data.tar.gz: 16ded8e6519cdc289e8ea6f452a7e985571ac602
5
5
  SHA512:
6
- metadata.gz: a08e3e095f76c77428ffdeb0ae5816b092a43a531266156750cbb2eccc7fb5ed969c35b83656d2c3b78ec1f5b44cc52255f7b167222097583465398a97313c7c
7
- data.tar.gz: 86c076784ddd8dead6797d797fce9adccb75bcce43cf04e22df5b676a9d3dd67ab1c355605ff79196c0c8758935f67f0f5923b96f9ffe5ea3045013cea27c49e
6
+ metadata.gz: d2e4132b9194102097f6ebcfbf1c78145f6467965c19df49d30b61808b5732a168c38e00af35a371af8357d34bc730568be7bf628c87f075d276851098d4ea65
7
+ data.tar.gz: 0c3f079769f959f77f58913f79396a87bbbed7032b5fe435933f7ac6e3c3fc715fd91352412d3afca32362d56025f745d72052f7b0cdb75ffd8120650bce5113
data/README.md CHANGED
@@ -11,7 +11,93 @@ units-time library / gem - units of time (in epoch time) incl. seconds, minutes,
11
11
 
12
12
  ## Usage
13
13
 
14
- to be done
14
+ [Timestamp](#timestamp) [Timedelta](#timedelta)
15
+
16
+
17
+ The following methods are added on `Integer` (`Fixnum` and `Bignum`)
18
+ and always return a `Timedelta` object (in seconds):
19
+
20
+ ``` ruby
21
+ # plural versions
22
+ 2.seconds #=> <Timedelta seconds=2>
23
+ 2.secs #=> <Timedelta seconds=2>
24
+ 3.minutes #=> <Timedelta seconds=180>
25
+ 3.mins #=> <Timedelta seconds=180>
26
+ 4.hours #=> <Timedelta seconds=14_400>
27
+ 5.days #=> <Timedelta seconds=432_000>
28
+ 6.weeks #=> <Timedelta seconds=3_628_800>
29
+ 7.fortnights #=> <Timedelta seconds=8_467_200>
30
+ 8.years #=> <Timedelta seconds=252_288_000>
31
+
32
+ # singular versions
33
+ 1.second #=> <Timedelta seconds=1>
34
+ 1.sec #=> <Timedelta seconds=1>
35
+ 1.minute #=> <Timedelta seconds=60>
36
+ 1.min #=> <Timedelta seconds=60>
37
+ 1.hour #=> <Timedelta seconds=3600>
38
+ 1.day #=> <Timedelta seconds=86_400>
39
+ 1.week #=> <Timedelta seconds=604_800>
40
+ 1.fortnight #=> <Timedelta seconds=1_209_600>
41
+ 1.year #=> <Timedelta seconds=31_536_000>
42
+ ```
43
+
44
+
45
+ ### Time arithmetics
46
+
47
+ You can add and subtract durations from `Timestamp` or `Timedelta` objects.
48
+
49
+ ``` ruby
50
+ Timestamp.now + 2.hours #=> <Timestamp seconds= >
51
+ 1.week + 1.day #=> <Timedelta seconds= >
52
+ 2.minutes - 1.second #=> <TimeDelta seconds= >
53
+ ```
54
+
55
+ Note: You CANNOT add or subtract integers to `Timestamp` or `Timedelta` objects
56
+ and vice versa.
57
+
58
+ ``` ruby
59
+ # Bad
60
+ 10 + 1.minute #=> Boom! <TypeError>
61
+ 1.minute + 10 #=> Boom! <TypeError>
62
+
63
+ # Good
64
+ 10.seconds + 1.minute #=> <Timedelta seconds=70>
65
+ 1.minute.to_i + 10 #=> Integer
66
+ ```
67
+
68
+ Note: Multiply an integer with `1.hour` or `1.minute` or `1.second` and so on
69
+ to convert to a time unit.
70
+
71
+ ``` ruby
72
+ 100*1.hour #=> <Timedelta seconds=360_000>
73
+ ```
74
+
75
+
76
+ ### Timestamp
77
+
78
+ The `Timestamp` class holds the time in seconds since unix epoch time (that is, January 1st, 1970).
79
+
80
+ ``` ruby
81
+ Timestamp.new(0) # or Timestamp(0)
82
+ ```
83
+
84
+ To get the time now use:
85
+
86
+ ``` ruby
87
+ Timestamp.now # or Timestamp.new
88
+ ```
89
+
90
+
91
+
92
+ ### Timedelta
93
+
94
+ The `Timedelta` class holds a time duration in seconds.
95
+
96
+ ``` ruby
97
+ Timedelta.new # or Timedelta(0)
98
+ ```
99
+
100
+
15
101
 
16
102
 
17
103
  ## License
data/lib/units-time.rb CHANGED
@@ -1,12 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- ##
4
- # todo/fix: use module
5
- ## use Timestamp and Timedelta classes etc.
6
-
7
-
8
3
  ## stdlibs
9
4
  require 'pp'
5
+ require 'time'
10
6
 
11
7
 
12
8
  ## our own code
@@ -14,52 +10,226 @@ require 'units-time/version' # note: let version always go first
14
10
 
15
11
 
16
12
 
13
+ #########################
14
+ # type constraints:
15
+ #
16
+ # note: for now
17
+ # - you CANNOT add a timestamp to another timestamp
18
+ # - you CAN only compare (<=>) timestamp to timestamp but NOT timedelta !!
19
+ # - you CAN only compare (<=>) timedelta to timedelta but NOT timestamp !!
20
+
21
+ class Timestamp
22
+
23
+ def self.now() new( Time.now.to_i ); end
24
+
25
+ attr_reader :seconds
26
+
27
+ def initialize( seconds=Time.now.to_i )
28
+ @seconds = seconds ## seconds since Jan 1st, 1970 (unix epoch time)
29
+ end
30
+
31
+ def ==( other )
32
+ if other.is_a?( self.class )
33
+ @seconds == other.seconds
34
+ else
35
+ ## note: allow for now integer comparision too - why? why not?
36
+ if other.is_a?( Integer )
37
+ @seconds == other
38
+ else
39
+ false
40
+ end
41
+ end
42
+ end
43
+ alias_method :eql?, :==
44
+
45
+ def +( other )
46
+ if other.is_a?( Timedelta )
47
+ self.class.new( @seconds + other.seconds )
48
+ else
49
+ ## fix/todo: use TypeError!!!!
50
+ raise ArgumentError.new( "[Timestamp] add(ition) - wrong type #{other.inspect} - Timedelta expected" )
51
+ end
52
+ end
53
+
54
+ def -( other )
55
+ if other.is_a?( Timedelta )
56
+ self.class.new( @seconds - other.seconds )
57
+ else
58
+ ## fix/todo: use TypeError!!!!
59
+ raise ArgumentError.new( "[Timestamp] sub(straction) - wrong type #{other.inspect} - Timedelta expected" )
60
+ end
61
+ end
62
+
63
+
64
+ include Comparable
65
+
66
+ def <=>( other )
67
+ if other.is_a?( self.class )
68
+ @seconds <=> other.seconds
69
+ else
70
+ ## fix/todo: use TypeError!!!!
71
+ raise ArgumentError.new( "[Timestamp] <=> - wrong type #{other.inspect} - Timestamp expected" )
72
+ end
73
+ end
74
+
75
+
76
+ ## todo/fix: always freeze by default (timestamp is immutable) - why? why not?
77
+ def self.zero() @@zero ||= new(0).freeze; end
78
+
79
+ alias_method :to_i, :seconds ## add to integer conversion - why? why not?
80
+ alias_method :to_int, :seconds
81
+ end ## class Timestamp
82
+
83
+
84
+
85
+ class Timedelta
86
+
87
+ attr_reader :seconds
88
+
89
+ def initialize( seconds=0 )
90
+ @seconds = seconds
91
+ end
92
+
93
+
94
+ def ==( other )
95
+ if other.is_a?( self.class )
96
+ @seconds == other.seconds
97
+ else
98
+ ## note: allow for now integer comparision too - why? why not?
99
+ if other.is_a?( Integer )
100
+ @seconds == other
101
+ else
102
+ false
103
+ end
104
+ end
105
+ end
106
+ alias_method :eql?, :==
107
+
108
+ def *( other )
109
+ if other.is_a?( Integer )
110
+ self.class.new( @seconds * other )
111
+ else
112
+ ## fix/todo: use TypeError!!!!
113
+ raise ArgumentError.new( "[Timedelta] mul(tiplication) - wrong type #{other.inspect} - integer number expected" )
114
+ end
115
+ end
116
+
117
+ def +( other )
118
+ if other.is_a?( self.class )
119
+ self.class.new( @seconds + other.seconds )
120
+ else
121
+ ## fix/todo: use TypeError!!!!
122
+ raise ArgumentError.new( "[Timedelta] add(ition) - wrong type #{other.inspect} - Timedelta expected" )
123
+ end
124
+ end
125
+
126
+ def -( other )
127
+ if other.is_a?( self.class )
128
+ self.class.new( @seconds - other.seconds )
129
+ else
130
+ ## fix/todo: use TypeError!!!!
131
+ raise ArgumentError.new( "[Timedelta] sub(straction) - wrong type #{other.inspect} - Timedelta expected" )
132
+ end
133
+ end
134
+
135
+
136
+ ### for details on coerce
137
+ ## see https://blog.dnsimple.com/2017/01/ruby-coercion-protocols-part-2/
138
+ def coerce( other )
139
+ if other.is_a?( Integer )
140
+ [self, other] ## allow communitative - switch left and right e.g. 365*24.hours to 24.hours*365
141
+ else
142
+ ## fix/todo: use TypeError!!!!
143
+ raise ArgumentError.new( "[Timedelta] coerce - wrong type #{other.inspect} - Integer number expected" )
144
+ end
145
+ end
146
+
147
+
148
+ include Comparable
149
+
150
+ def <=>( other )
151
+ if other.is_a?( self.class )
152
+ @seconds <=> other.seconds
153
+ else
154
+ ## fix/todo: use TypeError!!!!
155
+ raise ArgumentError.new( "[Timedelta] <=> - wrong type #{other.inspect} - Timedelta expected" )
156
+ end
157
+ end
158
+
159
+
160
+ ## todo/fix: always freeze by default (timedelta is immutable) - why? why not?
161
+ def self.zero() @@zero ||= new(0).freeze; end
17
162
 
18
- class Integer
19
-
163
+ alias_method :to_i, :seconds ## add to integer conversion - why? why not?
164
+ alias_method :to_int, :seconds
165
+ ## note: same as:
166
+ ## def to_i() @seconds; end ## add to integer conversion - why? why not?
167
+ ## def to_int() @seconds; end
168
+ end # class Timedelta
169
+
170
+
171
+ ### "global" converter functions use like
172
+ ## Timestamp(0) or Timedelta(0)
173
+ def Timestamp(arg) Timestamp.new( arg ); end
174
+ def Timedelta(arg) Timedelta.new( arg ); end
175
+
176
+
177
+
178
+ module TimeUnits
20
179
  ######################################
21
180
  ## note: there's NO month (for now)!!!
22
181
  ## why? month might be 28,29,30,31 days
23
182
  ## use days e.g. 30.days or 31.days etc.
24
183
 
184
+
25
185
  HOUR_IN_SECONDS = 60 * 60 # 60 minutes * 60 seconds
26
186
  DAY_IN_SECONDS = 24 * HOUR_IN_SECONDS # 24 hours * 60 * 60
27
187
  WEEK_IN_SECONDS = 7 * DAY_IN_SECONDS # 7 days * 24 * 60 * 60
28
188
  FORTNIGHT_IN_SECONDS = 14 * DAY_IN_SECONDS # 14 days * 24 * 60 * 60
189
+
190
+ #####
191
+ # note: for year use 365 days for now and NOT 365.25 (1/4)
192
+ # - why? why not? discuss
29
193
  YEAR_IN_SECONDS = 365 * DAY_IN_SECONDS # 365 days * 24 * 60 * 60
30
194
 
31
- def second() self; end
32
- def minute() self * 60; end
33
- def hour() self * HOUR_IN_SECONDS; end
34
- def day() self * DAY_IN_SECONDS; end
35
- def week() self * WEEK_IN_SECONDS; end
36
- def fortnight() self * FORTNIGHT_IN_SECONDS; end
37
- def year() self * YEAR_IN_SECONDS; end
195
+ def second() Timedelta.new( self ); end
196
+ def minute() Timedelta.new( self * 60 ); end
197
+ def hour() Timedelta.new( self * HOUR_IN_SECONDS ); end
198
+ def day() Timedelta.new( self * DAY_IN_SECONDS ); end
199
+ def week() Timedelta.new( self * WEEK_IN_SECONDS ); end
200
+ def fortnight() Timedelta.new( self * FORTNIGHT_IN_SECONDS ); end
201
+ def year() Timedelta.new( self * YEAR_IN_SECONDS ); end
202
+
38
203
 
39
204
  ########################################################
40
- ## alias - use alias or alias_method - why? why not?
41
- def seconds() second; end
42
- def secs() second; end
43
- def sec() second; end
44
- def s() second; end
205
+ ## alias
206
+ alias_method :seconds, :second
207
+ alias_method :secs, :second
208
+ alias_method :sec, :second
209
+ ## def s() second; end ### todo/fix: remove/add - why? why not?
210
+
211
+ alias_method :minutes, :minute
212
+ alias_method :mins, :minute
213
+ alias_method :min, :minute
214
+ ## def m() minute; end ### todo/fix: remove/add - why? why not?
45
215
 
46
- def minutes() minute; end
47
- def mins() minute; end
48
- def min() minute; end
49
- def m() minute; end
216
+ alias_method :hours, :hour
217
+ ## def h() hour; end ### todo/fix: remove/add - why? why not?
50
218
 
51
- def hours() hour; end
52
- def h() hour; end
219
+ alias_method :days, :day
220
+ ## def d() day; end ### todo/fix: remove/add - why? why not?
53
221
 
54
- def days() day; end
55
- def d() day; end
222
+ alias_method :weeks, :week
223
+ ## def w() week; end ### todo/fix: remove/add - why? why not?
56
224
 
57
- def weeks() week; end
58
- def w() week; end
225
+ alias_method :fortnights, :fortnight
59
226
 
60
- def fortnights() fortnight; end
227
+ alias_method :years, :year
228
+ ## def y() year; end ### todo/fix: remove/add - why? why not?
229
+ end # module TimeUnits
61
230
 
62
- def years() year; end
63
- def y() year; end
64
231
 
232
+
233
+ class Integer
234
+ include TimeUnits
65
235
  end # class Integer
@@ -2,9 +2,9 @@
2
2
 
3
3
  module UnitsTime
4
4
 
5
- MAJOR = 0
5
+ MAJOR = 1
6
6
  MINOR = 0
7
- PATCH = 1
7
+ PATCH = 0
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
10
10
  def self.version
@@ -10,66 +10,103 @@ require 'helper'
10
10
 
11
11
  class TestUnitsTime < MiniTest::Test
12
12
 
13
- def test_time
14
- now = Time.now.to_i
15
-
16
- assert_equal 31_536_000, 1.year
17
- assert_equal 31_536_000, 1.y
18
- assert_equal 31_536_000*2, 2.years
19
- assert_equal 31_536_000*2, 1.y*2
20
- assert_equal now+31_536_000, now+1.year
21
- assert_equal 31_536_000, 365.days
22
- assert_equal 31_536_000, 365*24.hours
23
-
24
- assert_equal 1_209_600, 1.fortnight
25
- assert_equal 1_209_600*2, 2.fortnights
26
- assert_equal 1_209_600*2, 1.fortnight*2
27
- assert_equal now+1_209_600, now+1.fortnight
28
- assert_equal 1_209_600, 2.weeks
29
- assert_equal 1_209_600, 14.days
30
- assert_equal 1_209_600, 14*24.hours
31
-
32
- assert_equal 604_800, 1.week
33
- assert_equal 604_800, 1.w
34
- assert_equal 604_800*2, 2.weeks
35
- assert_equal 604_800*2, 1.week*2
36
- assert_equal now+604_800, now+1.week
37
- assert_equal 604_800, 7.days
38
- assert_equal 604_800, 7*24.hours
39
-
40
- assert_equal 86_400, 1.day
41
- assert_equal 86_400, 1.d
42
- assert_equal 86_400*2, 2.days
43
- assert_equal 86_400*2, 1.day*2
44
- assert_equal now+86_400, now+1.day
45
- assert_equal 86_400, 24.hours
46
- assert_equal 86_400, 24*1.hour
47
-
48
- assert_equal 3600, 1.hour
49
- assert_equal 3600, 1.h
50
- assert_equal 3600*2, 2.hours
51
- assert_equal 3600*2, 1.hour*2
52
- assert_equal now+3600, now+1.hour
53
- assert_equal 3600, 60.minutes
54
- assert_equal 3600, 60*1.minute
55
-
56
- assert_equal 60, 1.minute
57
- assert_equal 60, 1.min
58
- assert_equal 60, 1.m
59
- assert_equal 60*2, 2.minutes
60
- assert_equal 60*2, 2.mins
61
- assert_equal 60*2, 1.minute*2
62
- assert_equal now+60, now+1.minute
63
- assert_equal 60, 60.seconds
64
- assert_equal 60, 60*1.second
65
-
66
- assert_equal 1, 1.second
67
- assert_equal 1, 1.sec
68
- assert_equal 1, 1.s
69
- assert_equal 1*2, 2.seconds
70
- assert_equal 1*2, 2.secs
71
- assert_equal 1*2, 1.second*2
72
- assert_equal now+1, now+1.second
13
+ def test_timstamp
14
+ now = Timestamp.now
15
+
16
+ assert_equal now.to_i, now
17
+
18
+ assert_equal now+31_536_000.secs, now+1.year
19
+ assert_equal now+1_209_600.secs, now+1.fortnight
20
+ assert_equal now+604_800.secs, now+1.week
21
+ assert_equal now+86_400.secs, now+1.day
22
+ assert_equal now+3600.secs, now+1.hour
23
+ assert_equal now+60.secs, now+1.minute
24
+ assert_equal now+1.sec, now+1.second
25
+
26
+ assert_equal true, now+1.second > now
27
+ assert_equal true, now+1.second >= now
28
+ assert_equal false, now+1.second < now
29
+ assert_equal false, now+1.second <= now
30
+ end
31
+
32
+
33
+ def test_timedelta
34
+ assert_equal 31_536_000.secs, 1.year
35
+ ## assert_equal 31_536_000, 1.y
36
+ assert_equal 31_536_000.secs*2, 2.years
37
+ assert_equal 31_536_000.secs*2, 1.year*2
38
+ ## assert_equal 31_536_000*2, 1.y*2
39
+ assert_equal 31_536_000.secs, 365.days
40
+ assert_equal 31_536_000.secs, 24.hours*365 ## note: uses coerce for type coercion
41
+ assert_equal 31_536_000.secs, 365*24.hours
42
+
43
+ assert_equal 1_209_600.secs, 1.fortnight
44
+ assert_equal 1_209_600.secs*2, 2.fortnights
45
+ assert_equal 1_209_600.secs*2, 1.fortnight*2
46
+ assert_equal 1_209_600.secs, 2.weeks
47
+ assert_equal 1_209_600.secs, 14.days
48
+ assert_equal 1_209_600.secs, 14*24.hours ## note: uses coerce for type coercion
49
+ assert_equal 1_209_600.secs, 24.hours*14
50
+
51
+ assert_equal 604_800.secs, 1.week
52
+ ## assert_equal 604_800, 1.w
53
+ assert_equal 604_800.secs*2, 2.weeks
54
+ assert_equal 604_800.secs*2, 1.week*2
55
+ assert_equal 604_800.secs, 7.days
56
+ assert_equal 604_800.secs, 7*24.hours ## note: uses coerce for type coercion
57
+ assert_equal 604_800.secs, 24.hours*7
58
+
59
+ assert_equal 86_400.secs, 1.day
60
+ ## assert_equal 86_400, 1.d
61
+ assert_equal 86_400.secs*2, 2.days
62
+ assert_equal 86_400.secs*2, 1.day*2
63
+ assert_equal 86_400.secs, 24.hours
64
+ assert_equal 86_400.secs, 24*1.hour ## note: uses coerce for type coercion
65
+ assert_equal 86_400.secs, 1.hour*24
66
+
67
+ assert_equal 3600.secs, 1.hour
68
+ ## assert_equal 3600, 1.h
69
+ assert_equal 3600.secs*2, 2.hours
70
+ assert_equal 3600.secs*2, 1.hour*2
71
+ assert_equal 3600.secs, 60.minutes
72
+ assert_equal 3600.secs, 60*1.minute ## note: uses coerce for type coercion
73
+ assert_equal 3600.secs, 1.minute*60
74
+
75
+ assert_equal 60.secs, 1.minute
76
+ assert_equal 60.secs, 1.min
77
+ ## assert_equal 60, 1.m
78
+ assert_equal 60.secs*2, 2.minutes
79
+ assert_equal 60.secs*2, 2.mins
80
+ assert_equal 60.secs*2, 1.minute*2
81
+ assert_equal 60.secs, 60.seconds
82
+ assert_equal 60.secs, 60*1.second ## note: uses coerce for type coercion
83
+ assert_equal 60.secs, 1.second*60
84
+
85
+ assert_equal 1.sec, 1.second
86
+ assert_equal 1.sec, 1.sec
87
+ ## assert_equal 1, 1.s
88
+ assert_equal 1.sec*2, 2.seconds
89
+ assert_equal 1.sec*2, 2.secs
90
+ assert_equal 1.sec*2, 1.second*2
91
+ end
92
+
93
+ def test_timedelta_ops
94
+ assert_equal (31_536_000+1_209_600+604_800).secs, 1.year+1.fortnight+1.week
95
+
96
+ now = Timestamp.now
97
+ assert_equal Timedelta, (100 * 1.hour).class
98
+ assert_equal now+100*3600.secs, now + (100 * 1.hour)
99
+ assert_equal Timestamp, (now + (100 * 1.hour)).class
100
+ end
101
+
102
+ def test_conv
103
+ assert_equal Timestamp.new(0), Timestamp(0)
104
+ assert_equal Timedelta.new, Timedelta(0)
105
+
106
+ assert_equal Timestamp.zero, Timestamp(0)
107
+ assert_equal Timedelta.zero, Timedelta(0)
108
+
109
+ assert_equal 0.secs, Timedelta(0)
73
110
  end
74
111
 
75
112
  end # class TestUnitsTime
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: units-time
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-09 00:00:00.000000000 Z
11
+ date: 2019-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc