time-utils 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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +21 -0
- data/Rakefile +1 -0
- data/lib/date/utils.rb +14 -0
- data/lib/time/utils.rb +190 -0
- data/lib/time/utils/version.rb +5 -0
- data/time-utils.gemspec +23 -0
- metadata +93 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Alex MacCaw
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Time::Utils
|
2
|
+
|
3
|
+
`Time::Utils` extracts some of ActiveSupports's time utilities.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'time-utils'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install time-utils
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/date/utils.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class Date
|
4
|
+
module Utils extend self
|
5
|
+
def advance(date, options)
|
6
|
+
options = options.dup
|
7
|
+
date = date >> options.delete(:years) * 12 if options[:years]
|
8
|
+
date = date >> options.delete(:months) if options[:months]
|
9
|
+
date = date + options.delete(:weeks) * 7 if options[:weeks]
|
10
|
+
date = date + options.delete(:days) if options[:days]
|
11
|
+
date
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/time/utils.rb
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'time/utils/version'
|
3
|
+
require 'date/utils'
|
4
|
+
|
5
|
+
class Time
|
6
|
+
module Utils extend self
|
7
|
+
COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
8
|
+
|
9
|
+
def days_in_month(month, year = now.year)
|
10
|
+
return 29 if month == 2 && ::Date.gregorian_leap?(year)
|
11
|
+
COMMON_YEAR_DAYS_IN_MONTH[month]
|
12
|
+
end
|
13
|
+
|
14
|
+
def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
|
15
|
+
time = ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
|
16
|
+
# This check is needed because Time.utc(y) returns a time object in the 2000s for 0 <= y <= 138.
|
17
|
+
time.year == year ? time : ::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
|
18
|
+
time
|
19
|
+
end
|
20
|
+
|
21
|
+
# Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:utc</tt>.
|
22
|
+
def utc_time(*args)
|
23
|
+
time_with_datetime_fallback(:utc, *args)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:local</tt>.
|
27
|
+
def local_time(*args)
|
28
|
+
time_with_datetime_fallback(:local, *args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def change(time, options)
|
32
|
+
send(
|
33
|
+
time.utc? ? :utc_time : :local_time,
|
34
|
+
options[:year] || time.year,
|
35
|
+
options[:month] || time.month,
|
36
|
+
options[:day] || time.day,
|
37
|
+
options[:hour] || time.hour,
|
38
|
+
options[:min] || (options[:hour] ? 0 : time.min),
|
39
|
+
options[:sec] || ((options[:hour] || options[:min]) ? 0 : time.sec),
|
40
|
+
options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : time.usec)
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def advance(time, options)
|
45
|
+
unless options[:weeks].nil?
|
46
|
+
options[:weeks], partial_weeks = options[:weeks].divmod(1)
|
47
|
+
options[:days] = (options[:days] || 0) + 7 * partial_weeks
|
48
|
+
end
|
49
|
+
|
50
|
+
unless options[:days].nil?
|
51
|
+
options[:days], partial_days = options[:days].divmod(1)
|
52
|
+
options[:hours] = (options[:hours] || 0) + 24 * partial_days
|
53
|
+
end
|
54
|
+
|
55
|
+
d = Date::Utils.advance(to_date(time), options)
|
56
|
+
time_advanced_by_date = change(time, :year => d.year, :month => d.month, :day => d.day)
|
57
|
+
seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
|
58
|
+
seconds_to_advance == 0 ? time_advanced_by_date : since(time_advanced_by_date, seconds_to_advance)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
|
62
|
+
def ago(time, seconds)
|
63
|
+
since(time, -seconds)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns a new Time representing the time a number of seconds since the instance time
|
67
|
+
def since(time, seconds)
|
68
|
+
time + seconds
|
69
|
+
end
|
70
|
+
alias :in :since
|
71
|
+
|
72
|
+
# Returns a new Time representing the time a number of specified weeks ago.
|
73
|
+
def weeks_ago(time, weeks)
|
74
|
+
advance(time, :weeks => -weeks)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns a new Time representing the time a number of specified months ago
|
78
|
+
def months_ago(time, months)
|
79
|
+
advance(time, :months => -months)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns a new Time representing the time a number of specified months in the future
|
83
|
+
def months_since(time, months)
|
84
|
+
advance(time, :months => months)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns a new Time representing the time a number of specified years ago
|
88
|
+
def years_ago(time, years)
|
89
|
+
advance(time, :years => -years)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns a new Time representing the time a number of specified years in the future
|
93
|
+
def years_since(time, years)
|
94
|
+
advance(time, :years => years)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Short-hand for years_ago(1)
|
98
|
+
def prev_year(time)
|
99
|
+
years_ago(time, 1)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Short-hand for years_since(1)
|
103
|
+
def next_year(time)
|
104
|
+
years_since(time, 1)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Short-hand for months_ago(1)
|
108
|
+
def prev_month(time)
|
109
|
+
months_ago(time, 1)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Short-hand for months_since(1)
|
113
|
+
def next_month(time)
|
114
|
+
months_since(time, 1)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns a new Time representing the start of the day (0:00)
|
118
|
+
def beginning_of_day(time)
|
119
|
+
#(self - seconds_since_midnight).change(:usec => 0)
|
120
|
+
change(time, :hour => 0)
|
121
|
+
end
|
122
|
+
alias :midnight :beginning_of_day
|
123
|
+
alias :at_midnight :beginning_of_day
|
124
|
+
alias :at_beginning_of_day :beginning_of_day
|
125
|
+
|
126
|
+
# Returns a new Time representing the end of the day, 23:59:59.999999 (.999999999 in ruby1.9)
|
127
|
+
def end_of_day(time)
|
128
|
+
change(time, :hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns a new Time representing the start of the hour (x:00)
|
132
|
+
def beginning_of_hour(time)
|
133
|
+
change(time, :min => 0)
|
134
|
+
end
|
135
|
+
alias :at_beginning_of_hour :beginning_of_hour
|
136
|
+
|
137
|
+
# Returns a new Time representing the end of the hour, x:59:59.999999 (.999999999 in ruby1.9)
|
138
|
+
def end_of_hour(time)
|
139
|
+
change(
|
140
|
+
time,
|
141
|
+
:min => 59,
|
142
|
+
:sec => 59,
|
143
|
+
:usec => 999999.999
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Returns a new Time representing the start of the month (1st of the month, 0:00)
|
148
|
+
def beginning_of_month(time)
|
149
|
+
#self - ((self.mday-1).days + self.seconds_since_midnight)
|
150
|
+
change(time, :day => 1, :hour => 0)
|
151
|
+
end
|
152
|
+
alias :at_beginning_of_month :beginning_of_month
|
153
|
+
|
154
|
+
# Returns a new Time representing the end of the month (end of the last day of the month)
|
155
|
+
def end_of_month(time)
|
156
|
+
#self - ((self.mday-1).days + self.seconds_since_midnight)
|
157
|
+
last_day = days_in_month(time.month, time.year)
|
158
|
+
change(time, :day => last_day, :hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
|
159
|
+
end
|
160
|
+
alias :at_end_of_month :end_of_month
|
161
|
+
|
162
|
+
# Returns a new Time representing the start of the year (1st of january, 0:00)
|
163
|
+
def beginning_of_year(time)
|
164
|
+
change(time, :month => 1, :day => 1, :hour => 0)
|
165
|
+
end
|
166
|
+
alias :at_beginning_of_year :beginning_of_year
|
167
|
+
|
168
|
+
# Returns a new Time representing the end of the year (end of the 31st of december)
|
169
|
+
def end_of_year(time)
|
170
|
+
change(time, :month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59, :usec => 999999.999)
|
171
|
+
end
|
172
|
+
alias :at_end_of_year :end_of_year
|
173
|
+
|
174
|
+
# Convenience method which returns a new Time representing the time 1 day ago
|
175
|
+
def yesterday(time)
|
176
|
+
advance(time, :days => -1)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Convenience method which returns a new Time representing the time 1 day since the instance time
|
180
|
+
def tomorrow(time)
|
181
|
+
advance(time, :days => 1)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Conversions
|
185
|
+
|
186
|
+
def to_date(time)
|
187
|
+
Date.new(time.year, time.month, time.day)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
data/time-utils.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'time/utils/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "time-utils"
|
8
|
+
spec.version = Time::Utils::VERSION
|
9
|
+
spec.authors = ["Alex MacCaw"]
|
10
|
+
spec.email = ["alex@stripe.com"]
|
11
|
+
spec.description = %q{Some useful time utilities}
|
12
|
+
spec.summary = %q{Some useful time utilities}
|
13
|
+
spec.homepage = "http://github.com/stripe/time-utils"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: time-utils
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alex MacCaw
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
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: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
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: Some useful time utilities
|
47
|
+
email:
|
48
|
+
- alex@stripe.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- LICENSE.txt
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- lib/date/utils.rb
|
59
|
+
- lib/time/utils.rb
|
60
|
+
- lib/time/utils/version.rb
|
61
|
+
- time-utils.gemspec
|
62
|
+
homepage: http://github.com/stripe/time-utils
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
hash: 2881585529544989181
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
hash: 2881585529544989181
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.8.24
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: Some useful time utilities
|
93
|
+
test_files: []
|