easy_time 0.1.2
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 +7 -0
- data/.circleci/config.yml +132 -0
- data/.gitignore +11 -0
- data/.rspec +4 -0
- data/.rubocop.yml +38 -0
- data/.travis.yml +6 -0
- data/.yardopts +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +137 -0
- data/Guardfile +35 -0
- data/LICENSE.txt +21 -0
- data/README.md +300 -0
- data/Rakefile +19 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/easy_time.gemspec +63 -0
- data/lib/easy_time.rb +381 -0
- data/lib/easy_time/convert.rb +148 -0
- data/lib/easy_time/version.rb +3 -0
- metadata +304 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4495654dbc3739198ac730b17b43fd61d66edf258f3a1506e7608414b6e16328
|
4
|
+
data.tar.gz: f3cb77f9f6a71a2d0c48811f3f69153f93678eda2e7510db58fc26657cfe4764
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1bff901b47f340553598a7e1f618faaf011ead4e86c3a32abf84a9edd64afecd043a932811d83a63d6820e319a89fb4c0df2f451733f1c22a5b1465585f83415
|
7
|
+
data.tar.gz: c87ede1b52cd24227c3734c41230af038ee3710ee46dffd9c11776dab8dfe73f8553999e5d04da9ba15f45a4f52a0ebc9133c2a8da228e9c5c2af48240b0bdcc
|
@@ -0,0 +1,132 @@
|
|
1
|
+
version: 2.1
|
2
|
+
orbs:
|
3
|
+
ruby: circleci/ruby@0.1.2
|
4
|
+
|
5
|
+
defaults: &DEFAULTS
|
6
|
+
resource_class: small
|
7
|
+
docker:
|
8
|
+
- image: circleci/ruby:2.5
|
9
|
+
|
10
|
+
environment:
|
11
|
+
BUNDLE_JOBS: 3
|
12
|
+
BUNDLE_RETRY: 3
|
13
|
+
BUNDLE_PATH: vendor/bundle
|
14
|
+
|
15
|
+
working_directory: ~/repo
|
16
|
+
|
17
|
+
jobs:
|
18
|
+
build:
|
19
|
+
docker:
|
20
|
+
- image: circleci/ruby:2.6.3-stretch-node
|
21
|
+
executor: ruby/default
|
22
|
+
steps:
|
23
|
+
- checkout
|
24
|
+
- attach_workspace:
|
25
|
+
at: ~/repo
|
26
|
+
|
27
|
+
- restore_cache:
|
28
|
+
keys:
|
29
|
+
- gem-cache-{{ checksum "easy_time.gemspec" }}
|
30
|
+
- gem-cache-
|
31
|
+
|
32
|
+
- run:
|
33
|
+
name: Install bundler
|
34
|
+
command: gem install bundler
|
35
|
+
|
36
|
+
- run:
|
37
|
+
name: Check bundle version
|
38
|
+
command: bundle --version
|
39
|
+
|
40
|
+
- run:
|
41
|
+
name: set the bundle path
|
42
|
+
command: bundle config set path 'vendor/bundle'
|
43
|
+
|
44
|
+
- run:
|
45
|
+
name: install dependencies
|
46
|
+
command: bundle install --jobs=4 --retry=3
|
47
|
+
|
48
|
+
- save_cache:
|
49
|
+
paths:
|
50
|
+
- ./vendor/bundle
|
51
|
+
key: gem-cache-{{ checksum "easy_time.gemspec" }}
|
52
|
+
|
53
|
+
- run:
|
54
|
+
name: run tests
|
55
|
+
command: |
|
56
|
+
mkdir /tmp/test-results
|
57
|
+
TEST_FILES="$(circleci tests glob 'spec/**/*_spec.rb' | circleci tests split --split-by=timings)"
|
58
|
+
|
59
|
+
bundle exec rspec --format RspecJunitFormatter \
|
60
|
+
--out /tmp/test-results/rspec.xml \
|
61
|
+
--format progress \
|
62
|
+
$TEST_FILES
|
63
|
+
|
64
|
+
- store_test_results:
|
65
|
+
path: /tmp/test-results
|
66
|
+
|
67
|
+
- store_artifacts:
|
68
|
+
path: /tmp/test-results
|
69
|
+
destination: test-results
|
70
|
+
|
71
|
+
- run:
|
72
|
+
name: build package
|
73
|
+
command: |
|
74
|
+
bundle exec rake clean
|
75
|
+
bundle exec rake build
|
76
|
+
|
77
|
+
release:
|
78
|
+
<<: *DEFAULTS
|
79
|
+
steps:
|
80
|
+
- checkout
|
81
|
+
|
82
|
+
- attach_workspace:
|
83
|
+
at: ~/repo
|
84
|
+
|
85
|
+
- restore_cache:
|
86
|
+
keys:
|
87
|
+
- gem-cache-{{ checksum "easy_time.gemspec" }}
|
88
|
+
- gem-cache-
|
89
|
+
|
90
|
+
- run:
|
91
|
+
name: Check bundle version
|
92
|
+
command: bundle --version
|
93
|
+
|
94
|
+
- run:
|
95
|
+
name: Install bundler
|
96
|
+
command: gem install bundler
|
97
|
+
|
98
|
+
- run:
|
99
|
+
name: set the bundle path
|
100
|
+
command: bundle config set path 'vendor/bundle'
|
101
|
+
|
102
|
+
- run:
|
103
|
+
name: install dependencies
|
104
|
+
command: bundle install --jobs=4 --retry=3
|
105
|
+
|
106
|
+
- save_cache:
|
107
|
+
paths:
|
108
|
+
- ./vendor/bundle
|
109
|
+
key: gem-cache-{{ checksum "easy_time.gemspec" }}
|
110
|
+
|
111
|
+
- run:
|
112
|
+
name: build package
|
113
|
+
command: |
|
114
|
+
bundle exec rake clean
|
115
|
+
bundle exec rake build
|
116
|
+
|
117
|
+
#- deploy:
|
118
|
+
# name: Release and push
|
119
|
+
# command: bundle exec gem push
|
120
|
+
|
121
|
+
workflows:
|
122
|
+
version: 2
|
123
|
+
bundle_build_test_release:
|
124
|
+
jobs:
|
125
|
+
- build
|
126
|
+
- release:
|
127
|
+
requires:
|
128
|
+
- build
|
129
|
+
filters:
|
130
|
+
branches:
|
131
|
+
only: master
|
132
|
+
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Metrics
|
2
|
+
Metrics/AbcSize:
|
3
|
+
Enabled: false
|
4
|
+
|
5
|
+
Metrics/CyclomaticComplexity:
|
6
|
+
Enabled: false
|
7
|
+
|
8
|
+
Metrics/MethodLength:
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
Metrics/PerceivedComplexity:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
Metrics/ClassLength:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
# Layouts
|
18
|
+
Layout/ExtraSpacing:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Layout/LineLength:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Layout/SpacingAroundOperators:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
# Styles
|
28
|
+
Style/AsciiComments:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/Documentation:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/StringLiterals:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Style/RescueModifier:
|
38
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
easy_time (0.1.2)
|
5
|
+
activesupport
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activesupport (6.0.2.2)
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
+
i18n (>= 0.7, < 2)
|
13
|
+
minitest (~> 5.1)
|
14
|
+
tzinfo (~> 1.1)
|
15
|
+
zeitwerk (~> 2.2)
|
16
|
+
ast (2.4.0)
|
17
|
+
builder (3.2.4)
|
18
|
+
byebug (11.1.3)
|
19
|
+
coderay (1.1.2)
|
20
|
+
concurrent-ruby (1.1.6)
|
21
|
+
diff-lcs (1.3)
|
22
|
+
docile (1.3.2)
|
23
|
+
ffi (1.12.2)
|
24
|
+
formatador (0.2.5)
|
25
|
+
fuubar (2.5.0)
|
26
|
+
rspec-core (~> 3.0)
|
27
|
+
ruby-progressbar (~> 1.4)
|
28
|
+
guard (2.16.2)
|
29
|
+
formatador (>= 0.2.4)
|
30
|
+
listen (>= 2.7, < 4.0)
|
31
|
+
lumberjack (>= 1.0.12, < 2.0)
|
32
|
+
nenv (~> 0.1)
|
33
|
+
notiffany (~> 0.0)
|
34
|
+
pry (>= 0.9.12)
|
35
|
+
shellany (~> 0.0)
|
36
|
+
thor (>= 0.18.1)
|
37
|
+
guard-compat (1.2.1)
|
38
|
+
guard-rspec (4.7.3)
|
39
|
+
guard (~> 2.1)
|
40
|
+
guard-compat (~> 1.1)
|
41
|
+
rspec (>= 2.99.0, < 4.0)
|
42
|
+
guard-yard (2.2.1)
|
43
|
+
guard (>= 1.1.0)
|
44
|
+
yard (>= 0.7.0)
|
45
|
+
i18n (1.8.2)
|
46
|
+
concurrent-ruby (~> 1.0)
|
47
|
+
jaro_winkler (1.5.4)
|
48
|
+
listen (3.2.1)
|
49
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
50
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
51
|
+
lumberjack (1.2.4)
|
52
|
+
method_source (1.0.0)
|
53
|
+
minitest (5.14.0)
|
54
|
+
nenv (0.3.0)
|
55
|
+
notiffany (0.1.3)
|
56
|
+
nenv (~> 0.1)
|
57
|
+
shellany (~> 0.0)
|
58
|
+
parallel (1.19.1)
|
59
|
+
parser (2.7.1.1)
|
60
|
+
ast (~> 2.4.0)
|
61
|
+
pry (0.13.1)
|
62
|
+
coderay (~> 1.1)
|
63
|
+
method_source (~> 1.0)
|
64
|
+
pry-byebug (3.9.0)
|
65
|
+
byebug (~> 11.0)
|
66
|
+
pry (~> 0.13.0)
|
67
|
+
rainbow (3.0.0)
|
68
|
+
rake (13.0.1)
|
69
|
+
rb-fsevent (0.10.3)
|
70
|
+
rb-inotify (0.10.1)
|
71
|
+
ffi (~> 1.0)
|
72
|
+
redcarpet (3.5.0)
|
73
|
+
rexml (3.2.4)
|
74
|
+
rspec (3.9.0)
|
75
|
+
rspec-core (~> 3.9.0)
|
76
|
+
rspec-expectations (~> 3.9.0)
|
77
|
+
rspec-mocks (~> 3.9.0)
|
78
|
+
rspec-core (3.9.1)
|
79
|
+
rspec-support (~> 3.9.1)
|
80
|
+
rspec-expectations (3.9.1)
|
81
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
82
|
+
rspec-support (~> 3.9.0)
|
83
|
+
rspec-mocks (3.9.1)
|
84
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
85
|
+
rspec-support (~> 3.9.0)
|
86
|
+
rspec-support (3.9.2)
|
87
|
+
rspec_junit (4.0.4)
|
88
|
+
builder (>= 3.2.2)
|
89
|
+
rspec (>= 3.3.0)
|
90
|
+
rspec_junit_formatter (0.4.1)
|
91
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
92
|
+
rubocop (0.82.0)
|
93
|
+
jaro_winkler (~> 1.5.1)
|
94
|
+
parallel (~> 1.10)
|
95
|
+
parser (>= 2.7.0.1)
|
96
|
+
rainbow (>= 2.2.2, < 4.0)
|
97
|
+
rexml
|
98
|
+
ruby-progressbar (~> 1.7)
|
99
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
100
|
+
ruby-progressbar (1.10.1)
|
101
|
+
shellany (0.0.1)
|
102
|
+
simplecov (0.18.5)
|
103
|
+
docile (~> 1.1)
|
104
|
+
simplecov-html (~> 0.11)
|
105
|
+
simplecov-html (0.12.2)
|
106
|
+
terminal-notifier-guard (1.7.0)
|
107
|
+
thor (1.0.1)
|
108
|
+
thread_safe (0.3.6)
|
109
|
+
tzinfo (1.2.7)
|
110
|
+
thread_safe (~> 0.1)
|
111
|
+
unicode-display_width (1.7.0)
|
112
|
+
yard (0.9.24)
|
113
|
+
zeitwerk (2.3.0)
|
114
|
+
|
115
|
+
PLATFORMS
|
116
|
+
ruby
|
117
|
+
|
118
|
+
DEPENDENCIES
|
119
|
+
bundler (~> 2.1.4)
|
120
|
+
easy_time!
|
121
|
+
fuubar (>= 2.5.0)
|
122
|
+
guard
|
123
|
+
guard-rspec
|
124
|
+
guard-yard
|
125
|
+
pry-byebug
|
126
|
+
rake
|
127
|
+
redcarpet
|
128
|
+
rspec
|
129
|
+
rspec_junit
|
130
|
+
rspec_junit_formatter
|
131
|
+
rubocop (>= 0.82.0)
|
132
|
+
simplecov
|
133
|
+
terminal-notifier-guard
|
134
|
+
yard (>= 0.9.24)
|
135
|
+
|
136
|
+
BUNDLED WITH
|
137
|
+
2.1.4
|
data/Guardfile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Guardfile for easy_time gem
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'terminal-notifier-guard'
|
5
|
+
notification :terminal_notifier, app_name: 'easy_time'
|
6
|
+
rescue LoadError
|
7
|
+
warn "Failed to load notifier"
|
8
|
+
end
|
9
|
+
|
10
|
+
guard :rspec,
|
11
|
+
all_on_start: false,
|
12
|
+
all_after_pass: false,
|
13
|
+
failed_mode: :focus,
|
14
|
+
cmd: "CODE_COVERAGE=1 bundle exec rspec" do
|
15
|
+
directories(%w[lib spec])
|
16
|
+
.select { |d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist") }
|
17
|
+
|
18
|
+
require "guard/rspec/dsl"
|
19
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
20
|
+
|
21
|
+
# RSpec files
|
22
|
+
rspec = dsl.rspec
|
23
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
24
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
25
|
+
watch(rspec.spec_files)
|
26
|
+
|
27
|
+
# Ruby files
|
28
|
+
ruby = dsl.ruby
|
29
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
30
|
+
end
|
31
|
+
|
32
|
+
guard 'yard' do
|
33
|
+
watch(%r{lib\/.+\.rb})
|
34
|
+
watch('README.md')
|
35
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 Alan Stebbens
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,300 @@
|
|
1
|
+
# EasyTime
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/easy_time)
|
4
|
+
|
5
|
+
[](https://app.circleci.com/pipelines/github/aks/easy_time)
|
6
|
+
|
7
|
+
Are you tired of having to deal with many kinds of date and time objects?
|
8
|
+
|
9
|
+
Are you frustrated that comparing timestamps from different systems yields
|
10
|
+
incorrect results? _(Were you surprised to learn that, despite really good
|
11
|
+
time sync sources, many systems aren't actually synced all that closely in
|
12
|
+
time?)_
|
13
|
+
|
14
|
+
Well, then, give EasyTime a try!
|
15
|
+
|
16
|
+
`EasyTime` accepts most of the well-known date and time objects, including
|
17
|
+
`RFC2822`, `HTTPDate`, `XMLSchema`, `ISO8601`, as well as
|
18
|
+
ActiveSupport::TimeWithZone strings and provides comparisons that have an
|
19
|
+
adjustable tolerance. With `EasyTime` methods, you can reliably compare two
|
20
|
+
timestamps and determine which one is "newer", "older" or the "same" withing
|
21
|
+
a configurable tolerance. The default comparison tolerance is 1.minute.
|
22
|
+
|
23
|
+
In other words, if you have a time-stamp from an `ActiveRecord` object that is
|
24
|
+
a few seconds different from a related object obtained from a 3rd-party system,
|
25
|
+
(eg: AWS S3), then logically, from an application perspective, these two
|
26
|
+
objects could be considered having the "same" time-stamp.
|
27
|
+
|
28
|
+
This is quite useful when one is trying to keep state synchronized between
|
29
|
+
different systems. How does one know if an object is "newer" or "older" than
|
30
|
+
that from another system? If the system time from the connected systems varies
|
31
|
+
by a few or more seconds, then comparisons needs to have some tolerance.
|
32
|
+
|
33
|
+
Having a tolerant comparison makes "newness" and "oldness" checks easier to
|
34
|
+
manage across systems with possibly varying time sources.
|
35
|
+
|
36
|
+
`EasyTime` objects are just like Time objects, except:
|
37
|
+
|
38
|
+
- they auto-convert most date and time objects to Time objects
|
39
|
+
- they provide configurable tolerant comparisons between two time objects
|
40
|
+
|
41
|
+
Even if you decide to set the configurable comparison tolerance to zero
|
42
|
+
_(disabling it)_, the auto-type conversion of most date and time objects is
|
43
|
+
very useful all by itself.
|
44
|
+
|
45
|
+
Finally, this module adds a new instance method to the familiar date and time
|
46
|
+
classes, to easily convert from the object to the corresponding `EasyTime`
|
47
|
+
object:
|
48
|
+
|
49
|
+
obj.easy_time
|
50
|
+
|
51
|
+
For example, this is pretty cool:
|
52
|
+
|
53
|
+
'2010-09-08 07:06:05 +04:00'.easy_time # => EasyTime instance
|
54
|
+
|
55
|
+
So it is just as easy to convert an ISO8601 time string as it is to convert
|
56
|
+
a `created_at` value from an ActiveRecord object:
|
57
|
+
|
58
|
+
rec.created_at.easy_time # => EasyTime instance
|
59
|
+
|
60
|
+
resp = RestClient.get service_uri + '/get_time'
|
61
|
+
time = JSON.parse(resp.body)["date_time"].easy_time
|
62
|
+
|
63
|
+
|
64
|
+
These are the currently known date and time classes the values of which will be
|
65
|
+
automatically converted, enabling tolerant ("easy") comparisons:
|
66
|
+
|
67
|
+
Date
|
68
|
+
Time
|
69
|
+
DateTime
|
70
|
+
ActiveSupport::Duration
|
71
|
+
ActiveSupport::TimeWithZone
|
72
|
+
|
73
|
+
## Installation
|
74
|
+
|
75
|
+
Add this line to your application's `Gemfile`:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
gem 'easy_time'
|
79
|
+
```
|
80
|
+
|
81
|
+
or, add this to your application's `*-gemspec.rb` file:
|
82
|
+
|
83
|
+
add.dependency 'easy_time'
|
84
|
+
|
85
|
+
And then execute:
|
86
|
+
|
87
|
+
$ bundle install
|
88
|
+
|
89
|
+
Or install it yourself as:
|
90
|
+
|
91
|
+
$ gem install easy_time
|
92
|
+
|
93
|
+
## Usage
|
94
|
+
|
95
|
+
require 'easy_time'
|
96
|
+
|
97
|
+
### Class Methods
|
98
|
+
|
99
|
+
There are class methods and instance methods.
|
100
|
+
|
101
|
+
### Creating a `EasyTime` Value
|
102
|
+
|
103
|
+
EasyTime.new(time)
|
104
|
+
|
105
|
+
This creates a new `EasyTime` value, which is essentially a wrapped `Time` value.
|
106
|
+
|
107
|
+
The `new` method uses the `convert` method to convert several known date and
|
108
|
+
time value types into a `Time` value.
|
109
|
+
|
110
|
+
EasyTime.convert(timestr)
|
111
|
+
|
112
|
+
### Auto-Conversion Date and Time Classes
|
113
|
+
|
114
|
+
These are the currently known class values that can be converted:
|
115
|
+
|
116
|
+
String # => Time.parse(string)
|
117
|
+
EasyTime # => EasyTime.time
|
118
|
+
Time # => Time
|
119
|
+
Date # => Time.iso8601(Date.iso8601)
|
120
|
+
DateTime # => Time.iso8601(DateTime.iso8601)
|
121
|
+
[yyyy,mm,dd,...] # => Time.new(yyyy,mm,dd,...)
|
122
|
+
ActiveSupport::TimeWithZone # => value.to_time (eg: 3.weeks.ago)
|
123
|
+
ActiveSupport::Duration # => Time.now + duration (eg: 2.months)
|
124
|
+
|
125
|
+
Most of the date and time classes have built-in ISO8601 formatters, which
|
126
|
+
allows easy conversion using the `Time.iso8601` parser.
|
127
|
+
|
128
|
+
The `EasyTime` and `Time` values are passed through unchanged.
|
129
|
+
|
130
|
+
The `ActiveSupport::TimeWithZone` value is converted to a `Time`.
|
131
|
+
|
132
|
+
The `ActiveSupport::Duration` value is converted to a `Time` by adding it to `Time.now`.
|
133
|
+
|
134
|
+
A `String` value is parsed with the `convert` method.
|
135
|
+
|
136
|
+
#### Time Strings
|
137
|
+
|
138
|
+
Most modern time format strings are recognized: ISO8601, RFD2822, HTTPDate,
|
139
|
+
XMLSchema, and even some natural date and time formats. Many systems use an
|
140
|
+
[ISO8601](https://en.wikipedia.org/wiki/ISO_8601) string, which has date, time,
|
141
|
+
and timezone components, with each variant having some variations.
|
142
|
+
|
143
|
+
With `EasyTime`, you don't have to know which time string format to use,
|
144
|
+
you can just ask `EasyTime` to convert it. If it can't, you'll get an
|
145
|
+
`ArgumentError` exception.
|
146
|
+
|
147
|
+
### `EasyTime` Comparison Class Methods
|
148
|
+
|
149
|
+
One advantage of `EasyTime` values over the other time objects is that `EasyTime`
|
150
|
+
can perform tolerant-comparisons, where the tolerance can be specified by
|
151
|
+
you _(the developer)_.
|
152
|
+
|
153
|
+
These are the `EasyTime` class methods for comparison:
|
154
|
+
|
155
|
+
EasyTime.newer?(t1, t2) # => true if t1 > t2
|
156
|
+
EasyTime.older?(t1, t2) # => true if t1 < t2
|
157
|
+
EasyTime.same?(t1, t2) # => true if t1 == t2 with tolerance
|
158
|
+
EasyTime.compare(t1, t2) # => t1 <=> t2 => -1, 0, 1, or nil with tolerance
|
159
|
+
|
160
|
+
Each comparison method auto-converts both time arguments into a `Time` value,
|
161
|
+
and then compares them with tolerance. This means that if the absolute
|
162
|
+
difference between `t1` and `t2` is less than the configured tolerance value,
|
163
|
+
then the two values will be considered equal _(the same)_.
|
164
|
+
|
165
|
+
If the two values are not tolerantly-equal, then the two values are compared
|
166
|
+
with `<=>`, which normally returns one of three values: [-1, 0, 1]. However,
|
167
|
+
since a tolerant-equality _(or sameness)_ was already tested and ruled out, the
|
168
|
+
comparison using `<=>` will only ever return -1 or 1.
|
169
|
+
|
170
|
+
Finally, if either time value is nil, or cannot be converted to a Time value,
|
171
|
+
the result of any comparison method is also nil.
|
172
|
+
|
173
|
+
There are other methods that make use of the tolerant comparison:
|
174
|
+
|
175
|
+
EasyTime.between?(t1, t_min, t_max) # => true if t1 >= t_min and t1 <= t_max
|
176
|
+
|
177
|
+
or
|
178
|
+
|
179
|
+
EasyTime.between?(t1, time_range) # => true if t1 is within the time_range
|
180
|
+
|
181
|
+
|
182
|
+
### Configuring the Comparison Tolerance
|
183
|
+
|
184
|
+
As described above, the comparison tolerance value can be configured to
|
185
|
+
something other than the default of `DEFAULT_TIME_COMPARISON_TOLERANCE`, which
|
186
|
+
is currently set to `1.minute`.
|
187
|
+
|
188
|
+
EasyTime.tolerance = 15.seconds # set an appropriate tolerance for our app
|
189
|
+
|
190
|
+
The above will set the tolerance value to 15 seconds. This configuration is
|
191
|
+
applied across all instances of the class.
|
192
|
+
|
193
|
+
### EasyTime Instance Methods
|
194
|
+
|
195
|
+
Once a `EasyTime` value has been created, it is basically a wrapped `Time` value
|
196
|
+
where the comparison methods are overridden in order to apply the comparison
|
197
|
+
tolerance value.
|
198
|
+
|
199
|
+
These are the instance methods:
|
200
|
+
|
201
|
+
t1 < t2 # => true if t1 is older than t2
|
202
|
+
t1 > t2 # => true if t1 is newer than t2
|
203
|
+
t1 <= t2 # => true if t1 is the same or older as t2
|
204
|
+
t1 >= t2 # => true if t1 is the same or newer as t2
|
205
|
+
t1 != t2 # => true if t1 is not the same as t2 (with tolerance)
|
206
|
+
t1 == t2 # => true if t1 is the same as t2 (with tolerance)
|
207
|
+
|
208
|
+
On each of the above, the `t2` value will be automatically converted to
|
209
|
+
a `Time` value, and tolerantly compared against `t1`.
|
210
|
+
|
211
|
+
In addition to the infix operators, there are the comparison instance methods:
|
212
|
+
|
213
|
+
t1.newer?(t2) # => true if t1 is newer (>) than t2
|
214
|
+
t1.older?(t2) # => true if t1 is older (<) then t2
|
215
|
+
t1.same?(t2) # => true if t1 is equal (==) to t2
|
216
|
+
t1.compare(t2) # => [-1, 0, 1] from t1 <=> t2
|
217
|
+
|
218
|
+
and
|
219
|
+
|
220
|
+
t1.between?(t_min, t_max) #=> true if t_min >= t1 <= t_max
|
221
|
+
t1.between?([t_min..t_max]) # => true if t1 is in the range
|
222
|
+
|
223
|
+
In all the above instance methods, `t2`, `t_min`, or `t_max` may be any known
|
224
|
+
date or time value, which is automatically converted into a Time value for the
|
225
|
+
tolerant comparison.
|
226
|
+
|
227
|
+
Arithmetic operators with auto-conversion are also supported:
|
228
|
+
|
229
|
+
t1 + duration
|
230
|
+
t1 - t2
|
231
|
+
t1 - duration
|
232
|
+
|
233
|
+
The `t2` can be a date, time or even a time string. In which case, the are
|
234
|
+
converted to a `Time` value, and the subtraction is performed between two
|
235
|
+
dates, with a duration result.
|
236
|
+
|
237
|
+
When arithmetic is performed with a `duration` value, then the result is a new
|
238
|
+
updated `EasyTime` value
|
239
|
+
|
240
|
+
### Auto-Conversion Of Comparison Values
|
241
|
+
|
242
|
+
`EasyTime` values can be compared with tolerance against any other time value,
|
243
|
+
including time strings, using instance methods. The receiver object must be an
|
244
|
+
`EasyTime` object in order to enable the auto-conversion of the other time
|
245
|
+
object.
|
246
|
+
|
247
|
+
The values provided on any comparison operator or method are converted to
|
248
|
+
a `Time` value using the same `convert` routine. See the description of the
|
249
|
+
acceptable date and time types above.
|
250
|
+
|
251
|
+
### Comparison Tolerance Instance Methods
|
252
|
+
|
253
|
+
As given above, the comparison tolerance value used on the instance methods is
|
254
|
+
that previously configured either on the instance, or at the class level.
|
255
|
+
|
256
|
+
It is possible, however, to dynamically provide comparison tolerance when
|
257
|
+
creating a new `EasyTime` value, or with the `with_tolerance` method.
|
258
|
+
|
259
|
+
In addition to the class methods for comparison tolerance, it is possible to
|
260
|
+
configure the comparison tolerance for each instance.
|
261
|
+
|
262
|
+
The `new` method accepts an optional `tolerance:` keyword value:
|
263
|
+
|
264
|
+
t1 = EasyTime.new(record.created_at, tolerance: 20.seconds)
|
265
|
+
t1.newer?(another_time) # => compared with a tolerance of 20 seconds
|
266
|
+
|
267
|
+
The comparison tolerance can also be set dynamically using `.with_tolerance`:
|
268
|
+
|
269
|
+
t1 = EasyTime.new(record.updated_at)
|
270
|
+
t1.with_tolerance(1.second) > another_time
|
271
|
+
t1.with_tolerance(2.seconds).newer?(another_time)
|
272
|
+
|
273
|
+
The `.with_tolerance` method creates a _new_ `EasyTime` value with the
|
274
|
+
specified tolerance, leaving the original value and configured tolerance
|
275
|
+
intact.
|
276
|
+
|
277
|
+
## Development
|
278
|
+
|
279
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
280
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
281
|
+
prompt that will allow you to experiment.
|
282
|
+
|
283
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
284
|
+
release a new version, update the version number in `version.rb`, and then run
|
285
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
286
|
+
git commits and tags, and push the `.gem` file to
|
287
|
+
[rubygems.org](https://rubygems.org).
|
288
|
+
|
289
|
+
## Contributing
|
290
|
+
|
291
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/aks/easy_time.
|
292
|
+
|
293
|
+
|
294
|
+
## License
|
295
|
+
|
296
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
297
|
+
|
298
|
+
## Author
|
299
|
+
|
300
|
+
Alan K. Stebbens `<aks@stebbens.org>`
|