quarter 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 +7 -0
- data/LICENSE.txt +4 -0
- data/README.md +32 -0
- data/lib/quarter.rb +174 -0
- data/quarter.gemspec +18 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ee89de1f0184f1a1c816f6da0f81544b04c1700325dbdfe018cedb709a73eb68
|
4
|
+
data.tar.gz: f5728f54665347af3b15b6396121f8667ba01488af85bccbedc62c707f67fa41
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 30c126a64d3ae114d3d244722f1f32453a96782f4d6ebf4ee264087818c7b5bca5b4619bf8b7775a9fc9b12158a0d5ec4b8a1382bdf192a0f15a80b67027a23c
|
7
|
+
data.tar.gz: 1bc3ff80ba433d9a21982d1a5b1da2183505363bb4dc98a48c3940ef5a9edb0510e9aa4ede503e94a4989688de3a742055280ab5d4056a832d84bc0b28eab2e6
|
data/LICENSE.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# percentage
|
2
|
+
|
3
|
+
Ruby gem for working with standard calendar quarters.
|
4
|
+
|
5
|
+
|
6
|
+
## Install
|
7
|
+
|
8
|
+
Using Bundler:
|
9
|
+
|
10
|
+
$ bundle add quarter
|
11
|
+
|
12
|
+
Using RubyGems:
|
13
|
+
|
14
|
+
$ gem install quarter
|
15
|
+
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'quarter'
|
21
|
+
|
22
|
+
date = Date.today
|
23
|
+
|
24
|
+
quarter = Quarter(date)
|
25
|
+
|
26
|
+
p quarter.start_date
|
27
|
+
p quarter.include?(date)
|
28
|
+
p quarter.next
|
29
|
+
p quarter.name
|
30
|
+
p quarter.to_s
|
31
|
+
p quarter.iso8601
|
32
|
+
```
|
data/lib/quarter.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
class Quarter
|
5
|
+
def initialize(year, number)
|
6
|
+
unless number.between?(1, 4)
|
7
|
+
raise ArgumentError, 'invalid quarter number'
|
8
|
+
end
|
9
|
+
|
10
|
+
@year = year
|
11
|
+
|
12
|
+
@number = number
|
13
|
+
|
14
|
+
freeze
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :year
|
18
|
+
|
19
|
+
attr_reader :number
|
20
|
+
|
21
|
+
def name
|
22
|
+
"Q#{@number}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
"Q#{@number} #{@year}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def iso8601
|
30
|
+
"#{@year}-Q#{@number}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def hash
|
34
|
+
iso8601.hash
|
35
|
+
end
|
36
|
+
|
37
|
+
def eql?(other)
|
38
|
+
other.class == self.class && other.hash == self.hash
|
39
|
+
end
|
40
|
+
|
41
|
+
def <=>(other)
|
42
|
+
return unless other.class == self.class
|
43
|
+
|
44
|
+
if @year == other.year
|
45
|
+
@number <=> other.number
|
46
|
+
else
|
47
|
+
@year <=> other.year
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
include Comparable
|
52
|
+
|
53
|
+
def next
|
54
|
+
self + 1
|
55
|
+
end
|
56
|
+
|
57
|
+
alias_method :succ, :next
|
58
|
+
|
59
|
+
alias_method :next_quarter, :next
|
60
|
+
|
61
|
+
def prev
|
62
|
+
self - 1
|
63
|
+
end
|
64
|
+
|
65
|
+
alias_method :prev_quarter, :prev
|
66
|
+
|
67
|
+
def step(limit, step = 1)
|
68
|
+
raise ArgumentError if step.zero?
|
69
|
+
|
70
|
+
return enum_for(:step, limit, step) unless block_given?
|
71
|
+
|
72
|
+
quarter = self
|
73
|
+
|
74
|
+
operator = step > 0 ? :> : :<
|
75
|
+
|
76
|
+
until quarter.public_send(operator, limit)
|
77
|
+
yield quarter
|
78
|
+
|
79
|
+
quarter += step
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def upto(max, &block)
|
84
|
+
step(max, 1, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
def downto(min, &block)
|
88
|
+
step(min, -1, &block)
|
89
|
+
end
|
90
|
+
|
91
|
+
def +(other)
|
92
|
+
years, remainder = (@number - 1 + other.to_i).divmod(4)
|
93
|
+
|
94
|
+
self.class.new(@year + years, 1 + remainder)
|
95
|
+
end
|
96
|
+
|
97
|
+
def -(other)
|
98
|
+
if other.class == self.class
|
99
|
+
(@year * 4 + @number) - (other.year * 4 + other.number)
|
100
|
+
else
|
101
|
+
self + (-other)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def include?(date)
|
106
|
+
@year == date.year && @number == Quarter(date.month)
|
107
|
+
end
|
108
|
+
|
109
|
+
alias_method :===, :include?
|
110
|
+
|
111
|
+
def start_date
|
112
|
+
Date.new(@year, @number * 3 - 2, 1)
|
113
|
+
end
|
114
|
+
|
115
|
+
def end_date
|
116
|
+
Date.new(@year, @number * 3, -1)
|
117
|
+
end
|
118
|
+
|
119
|
+
def dates
|
120
|
+
start_date .. end_date
|
121
|
+
end
|
122
|
+
|
123
|
+
def length
|
124
|
+
case @number
|
125
|
+
when 1 then Date.gregorian_leap?(@year) ? 91 : 90
|
126
|
+
when 2 then 91
|
127
|
+
when 3, 4 then 92
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def months
|
132
|
+
Month.new(@year, @number) .. Month.new(@year, @number + 2)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def Quarter(object)
|
137
|
+
case object
|
138
|
+
when Quarter
|
139
|
+
object
|
140
|
+
when Integer
|
141
|
+
(object / 3.0).ceil
|
142
|
+
else
|
143
|
+
Quarter.new(object.year, Quarter(object.month))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class Quarter
|
148
|
+
REGEXP = /\AQ(1|2|3|4) (\d{4})\z/i
|
149
|
+
|
150
|
+
private_constant :REGEXP
|
151
|
+
|
152
|
+
ISO8601_REGEXP = /\A(\d{4})\-Q(1|2|3|4)\z/i
|
153
|
+
|
154
|
+
private_constant :ISO8601_REGEXP
|
155
|
+
|
156
|
+
def self.parse(string)
|
157
|
+
case string
|
158
|
+
when REGEXP
|
159
|
+
Quarter.new($2.to_i, $1.to_i)
|
160
|
+
when ISO8601_REGEXP
|
161
|
+
Quarter.new($1.to_i, $2.to_i)
|
162
|
+
else
|
163
|
+
raise ArgumentError, 'invalid quarter string'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def Quarter.today
|
169
|
+
Quarter(Date.today)
|
170
|
+
end
|
171
|
+
|
172
|
+
def Quarter.now
|
173
|
+
Quarter(Time.now)
|
174
|
+
end
|
data/quarter.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'quarter'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.license = 'LGPL-3.0'
|
5
|
+
s.platform = Gem::Platform::RUBY
|
6
|
+
s.authors = ['Tim Craft']
|
7
|
+
s.email = ['mail@timcraft.com']
|
8
|
+
s.homepage = 'https://github.com/readysteady/quarter'
|
9
|
+
s.description = 'Ruby gem for working with standard calendar quarters'
|
10
|
+
s.summary = 'See description'
|
11
|
+
s.files = Dir.glob('lib/**/*.rb') + %w[LICENSE.txt README.md quarter.gemspec]
|
12
|
+
s.require_path = 'lib'
|
13
|
+
s.metadata = {
|
14
|
+
'homepage' => 'https://github.com/readysteady/quarter',
|
15
|
+
'source_code_uri' => 'https://github.com/readysteady/quarter',
|
16
|
+
'bug_tracker_uri' => 'https://github.com/readysteady/quarter/issues'
|
17
|
+
}
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: quarter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Craft
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-04-27 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Ruby gem for working with standard calendar quarters
|
14
|
+
email:
|
15
|
+
- mail@timcraft.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- LICENSE.txt
|
21
|
+
- README.md
|
22
|
+
- lib/quarter.rb
|
23
|
+
- quarter.gemspec
|
24
|
+
homepage: https://github.com/readysteady/quarter
|
25
|
+
licenses:
|
26
|
+
- LGPL-3.0
|
27
|
+
metadata:
|
28
|
+
homepage: https://github.com/readysteady/quarter
|
29
|
+
source_code_uri: https://github.com/readysteady/quarter
|
30
|
+
bug_tracker_uri: https://github.com/readysteady/quarter/issues
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubygems_version: 3.1.2
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: See description
|
50
|
+
test_files: []
|