month 1.3.0 → 1.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 074b88d35639de246321396e3deb7986c75d0e6e
4
- data.tar.gz: 4a359d04e6abb0cde293420bc6193234d47b9c8e
2
+ SHA256:
3
+ metadata.gz: c6f2cb49e56df71efa50a5d0b1d0defa911997bb7b1f064ce4820cbb171d64b7
4
+ data.tar.gz: 3d16daecccc4d6b4a8287e870f6114d51e148478aa7f26bf295a805020f9b670
5
5
  SHA512:
6
- metadata.gz: 2f41916e6b14eab832a57b778ac39b988346e2554a313228e2c8affe4a944605ad503954fcb9aae43d77ef6b04fe0a046489e65db967e7f7f7fa7836785035bf
7
- data.tar.gz: d8ce70bc5f52728efce01d298fdec98a5312549236ad9458e9950cb16cd71bb1cd5b61878b324d5db2a9a7c7284f6fd302540118b6901cdbce86c305cdf25dd5
6
+ metadata.gz: 9dcaed88e8f32858f302b14369a7f095bbe5e237d89599ed74bd430956946e3297c52eba4f639b94b17b7f8b9060e7b208d4360d3f8812f2ab2fc41a7970dc62
7
+ data.tar.gz: 6d0627f52ef61f665be335c66734cf9e0fcce5d0751bf9bf08c07aaf195b6209fb970cf0696625d3667dce68350fcc7c55e34fbb7b2c7ba45bdf13acc14a5de0
@@ -0,0 +1,53 @@
1
+ # 1.7.1
2
+
3
+ * Added CHANGES.md to gem files
4
+
5
+ * Fixed outdated changelog_uri
6
+
7
+ # 1.7.0
8
+
9
+ * Added optional YAML integration
10
+
11
+ This makes it possible to dump/load month objects to/from YAML as scalar values. For example:
12
+
13
+ require 'month/yaml'
14
+
15
+ puts YAML.dump([Month.today])
16
+
17
+ This functionality is not enabled by default, due to the use of Module#prepend.
18
+
19
+ # 1.6.0
20
+
21
+ * Added Month#month alias for Month#number
22
+
23
+ * Added Month#iso8601 alias for Month#to_s
24
+
25
+ # 1.5.0
26
+
27
+ * Added Month#<< and Month#>> methods (@pboling)
28
+
29
+ * Added Month.today method
30
+
31
+ * Added Month.now method
32
+
33
+ # 1.4.0
34
+
35
+ * Fixed comparison with nil objects / ActiveRecord serialization
36
+
37
+ # 1.3.0
38
+
39
+ * Month objects are now frozen on initialization (@replaid, #4)
40
+
41
+ # 1.2.0
42
+
43
+ * Added step argument to Month#step and upto/downto methods (@jkr2255, #3)
44
+
45
+ # 1.1.0
46
+
47
+ * Fixed fence-post error with addition (@fhwang, #2)
48
+
49
+ * Added subtraction functionality for calculating number of months between two month objects (@aprikip, #1)
50
+
51
+ # 1.0.0
52
+
53
+ * New version!
@@ -1,4 +1,4 @@
1
- Copyright the authors and contributors. All rights reserved.
1
+ Copyright (c) 2014-2020 TIMCRAFT
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person
4
4
  obtaining a copy of this software and associated documentation
data/README.md CHANGED
@@ -1,12 +1,19 @@
1
1
  # month
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/month.svg)](https://badge.fury.io/rb/month) [![Build Status](https://api.travis-ci.org/timcraft/month.svg?branch=master)](https://travis-ci.org/timcraft/month)
3
+ ![Gem Version](https://badge.fury.io/rb/month.svg)
4
+ ![Build Status](https://github.com/readysteady/month/workflows/Test/badge.svg)
4
5
 
5
6
 
6
- A little Ruby library for working with months.
7
+ Ruby gem for working with months.
7
8
 
8
9
 
9
- ## Installation
10
+ ## Install
11
+
12
+ Using Bundler:
13
+
14
+ $ bundle add month
15
+
16
+ Using RubyGems:
10
17
 
11
18
  $ gem install month
12
19
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'date'
2
3
 
3
4
  class Month
@@ -17,7 +18,7 @@ class Month
17
18
  }
18
19
 
19
20
  def initialize(year, number)
20
- unless NAMES.has_key?(number)
21
+ unless NAMES.key?(number)
21
22
  raise ArgumentError, 'invalid month number'
22
23
  end
23
24
 
@@ -28,10 +29,14 @@ class Month
28
29
 
29
30
  attr_reader :year, :number
30
31
 
32
+ alias_method :month, :number
33
+
31
34
  def to_s
32
35
  "#@year-#{@number.to_s.rjust(2, '0')}"
33
36
  end
34
37
 
38
+ alias_method :iso8601, :to_s
39
+
35
40
  def name
36
41
  NAMES.fetch(@number)
37
42
  end
@@ -51,6 +56,8 @@ class Month
51
56
  end
52
57
 
53
58
  def <=>(month)
59
+ return unless month.class == self.class
60
+
54
61
  if @year == month.year
55
62
  @number <=> month.number
56
63
  else
@@ -70,6 +77,18 @@ class Month
70
77
 
71
78
  alias_method :succ, :next
72
79
 
80
+ def >>(n)
81
+ self + n
82
+ end
83
+
84
+ alias_method :next_month, :>>
85
+
86
+ def <<(n)
87
+ self - n
88
+ end
89
+
90
+ alias_method :prev_month, :<<
91
+
73
92
  def step(limit, step = 1)
74
93
  raise ArgumentError if step.zero?
75
94
 
@@ -112,7 +131,7 @@ class Month
112
131
  if object.is_a?(Integer)
113
132
  self + (-object)
114
133
  else
115
- (year * 12 + @number) - (object.year * 12 + object.number)
134
+ 12 * (year - object.year) + (@number - object.number)
116
135
  end
117
136
  end
118
137
 
@@ -139,11 +158,17 @@ class Month
139
158
  end
140
159
  end
141
160
 
142
- def Month.parse(string)
143
- if string =~ /\A(\d{4})-(\d{2})\z/
144
- Month.new($1.to_i, $2.to_i)
145
- else
146
- raise ArgumentError, 'invalid month'
161
+ class Month
162
+ REGEXP = /\A(\d{4})-(\d{2})\z/
163
+
164
+ private_constant :REGEXP
165
+
166
+ def self.parse(string)
167
+ if string =~ REGEXP
168
+ Month.new($1.to_i, $2.to_i)
169
+ else
170
+ raise ArgumentError, 'invalid month'
171
+ end
147
172
  end
148
173
  end
149
174
 
@@ -158,6 +183,14 @@ def Month(object)
158
183
  end
159
184
  end
160
185
 
186
+ def Month.today
187
+ Month(Date.today)
188
+ end
189
+
190
+ def Month.now
191
+ Month(Time.now)
192
+ end
193
+
161
194
  class Month
162
195
  module Methods
163
196
  NAMES.each do |number, name|
@@ -0,0 +1,23 @@
1
+ require 'yaml'
2
+
3
+ class Month
4
+ def encode_with(coder)
5
+ coder.represent_scalar(nil, to_s)
6
+ end
7
+
8
+ module ScalarScannerPatch
9
+ REGEXP = /\A(\d{4})-(\d{2})\z/
10
+
11
+ def tokenize(string)
12
+ if !string.empty? && string.match(REGEXP)
13
+ return Month.new($1.to_i, $2.to_i)
14
+ end
15
+
16
+ super string
17
+ end
18
+
19
+ YAML::ScalarScanner.prepend(self)
20
+ end
21
+
22
+ private_constant :ScalarScannerPatch
23
+ end
@@ -1,16 +1,20 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'month'
3
- s.version = '1.3.0'
3
+ s.version = '1.7.1'
4
4
  s.license = 'MIT'
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = ['Tim Craft']
7
7
  s.email = ['mail@timcraft.com']
8
- s.homepage = 'http://github.com/timcraft/month'
9
- s.description = 'A little Ruby library for working with months'
8
+ s.homepage = 'https://github.com/readysteady/month'
9
+ s.description = 'Ruby gem for working with months'
10
10
  s.summary = 'See description'
11
- s.files = Dir.glob('{lib,spec}/**/*') + %w(LICENSE.txt README.md month.gemspec)
11
+ s.files = Dir.glob('lib/**/*.rb') + %w[CHANGES.md LICENSE.txt README.md month.gemspec]
12
12
  s.required_ruby_version = '>= 1.9.3'
13
- s.add_development_dependency('rake', '~> 10.0')
14
- s.add_development_dependency('minitest', '~> 5.0')
15
13
  s.require_path = 'lib'
14
+ s.metadata = {
15
+ 'homepage' => 'https://github.com/readysteady/month',
16
+ 'source_code_uri' => 'https://github.com/readysteady/month',
17
+ 'bug_tracker_uri' => 'https://github.com/readysteady/month/issues',
18
+ 'changelog_uri' => 'https://github.com/readysteady/month/blob/main/CHANGES.md'
19
+ }
16
20
  end
metadata CHANGED
@@ -1,60 +1,37 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: month
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Craft
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-09 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rake
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '10.0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '10.0'
27
- - !ruby/object:Gem::Dependency
28
- name: minitest
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '5.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '5.0'
41
- description: A little Ruby library for working with months
11
+ date: 2020-11-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby gem for working with months
42
14
  email:
43
15
  - mail@timcraft.com
44
16
  executables: []
45
17
  extensions: []
46
18
  extra_rdoc_files: []
47
19
  files:
20
+ - CHANGES.md
48
21
  - LICENSE.txt
49
22
  - README.md
50
23
  - lib/month.rb
24
+ - lib/month/yaml.rb
51
25
  - month.gemspec
52
- - spec/month_spec.rb
53
- homepage: http://github.com/timcraft/month
26
+ homepage: https://github.com/readysteady/month
54
27
  licenses:
55
28
  - MIT
56
- metadata: {}
57
- post_install_message:
29
+ metadata:
30
+ homepage: https://github.com/readysteady/month
31
+ source_code_uri: https://github.com/readysteady/month
32
+ bug_tracker_uri: https://github.com/readysteady/month/issues
33
+ changelog_uri: https://github.com/readysteady/month/blob/main/CHANGES.md
34
+ post_install_message:
58
35
  rdoc_options: []
59
36
  require_paths:
60
37
  - lib
@@ -69,9 +46,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
46
  - !ruby/object:Gem::Version
70
47
  version: '0'
71
48
  requirements: []
72
- rubyforge_project:
73
- rubygems_version: 2.6.11
74
- signing_key:
49
+ rubygems_version: 3.1.4
50
+ signing_key:
75
51
  specification_version: 4
76
52
  summary: See description
77
53
  test_files: []
@@ -1,315 +0,0 @@
1
- require 'minitest/autorun'
2
-
3
- require_relative '../lib/month'
4
-
5
- describe 'Month' do
6
- describe 'constructor' do
7
- it 'raises an exception when initialized with an invalid number' do
8
- proc { Month.new(2014, 0) }.must_raise(ArgumentError)
9
- proc { Month.new(2014, 100) }.must_raise(ArgumentError)
10
- end
11
-
12
- it 'returns frozen instances' do
13
- month = Month.new(2017, 1)
14
- month.frozen?.must_equal(true)
15
- end
16
- end
17
-
18
- describe 'year method' do
19
- it 'returns the integer year of the month' do
20
- Month.new(2014, 1).year.must_equal(2014)
21
- end
22
- end
23
-
24
- describe 'number method' do
25
- it 'returns the integer number of the month' do
26
- Month.new(2014, 1).number.must_equal(1)
27
- end
28
- end
29
-
30
- describe 'to_s method' do
31
- it 'returns a string containing the year and zero padded number of the month' do
32
- Month.new(2014, 1).to_s.must_equal('2014-01')
33
- end
34
- end
35
-
36
- describe 'name method' do
37
- it 'returns the name of the month' do
38
- Month.new(2014, 1).name.must_equal(:January)
39
- end
40
- end
41
-
42
- describe 'january predicate method' do
43
- it 'returns true if the month is january' do
44
- Month.new(2014, 1).january?.must_equal(true)
45
- end
46
-
47
- it 'returns false otherwise' do
48
- Month.new(2014, 2).january?.must_equal(false)
49
- end
50
- end
51
-
52
- describe 'february predicate method' do
53
- it 'returns true if the month is february' do
54
- Month.new(2014, 2).february?.must_equal(true)
55
- end
56
-
57
- it 'returns false otherwise' do
58
- Month.new(2014, 1).february?.must_equal(false)
59
- end
60
- end
61
-
62
- it 'supports being used as a hash key' do
63
- hash, n = Hash.new(0), 10
64
-
65
- n.times { hash[Month.new(2014, 1)] += 1 }
66
-
67
- hash.count.must_equal(1)
68
- hash[Month.new(2014, 1)].must_equal(n)
69
- end
70
-
71
- it 'supports comparison between month objects' do
72
- Month.new(2014, 1).must_be_kind_of(Comparable)
73
-
74
- (Month.new(2014, 1) == Month.new(2014, 1)).must_equal(true)
75
- (Month.new(2014, 1) == Month.new(2014, 2)).must_equal(false)
76
-
77
- (Month.new(2014, 1) < Month.new(2014, 2)).must_equal(true)
78
- (Month.new(2014, 2) > Month.new(2014, 1)).must_equal(true)
79
- end
80
-
81
- it 'supports being used in a range' do
82
- range = Month.new(2014, 1) .. Month.new(2014, 4)
83
-
84
- range.map(&:number).must_equal([1, 2, 3, 4])
85
- end
86
-
87
- describe 'next method' do
88
- it 'returns a month object denoting the next month' do
89
- Month.new(2014, 1).next.must_equal(Month.new(2014, 2))
90
- Month.new(2014, 12).next.must_equal(Month.new(2015, 1))
91
- end
92
- end
93
-
94
- describe 'succ method' do
95
- it 'returns a month object denoting the next month' do
96
- Month.new(2014, 1).succ.must_equal(Month.new(2014, 2))
97
- Month.new(2014, 12).succ.must_equal(Month.new(2015, 1))
98
- end
99
- end
100
-
101
- describe 'step method' do
102
- it 'calls the block for every month until the given limit' do
103
- months = []
104
-
105
- Month.new(2014, 1).step(Month.new(2014, 3)) { |month| months << month }
106
-
107
- months.must_equal([Month.new(2014, 1), Month.new(2014, 2), Month.new(2014, 3)])
108
- end
109
-
110
- it 'returns an enumerator if no block was given' do
111
- months = Month.new(2014, 1).step(Month.new(2014, 3))
112
-
113
- months.must_be_instance_of(Enumerator)
114
-
115
- months.next.must_equal(Month.new(2014, 1))
116
- months.next.must_equal(Month.new(2014, 2))
117
- months.next.must_equal(Month.new(2014, 3))
118
- end
119
-
120
- it 'raises an exception when the given step argument is zero' do
121
- proc { Month.new(2014, 1).step(Month.new(2014, 3), 0) }.must_raise(ArgumentError)
122
- end
123
-
124
- it 'increases by the given number of months if the step argument is positive' do
125
- months = []
126
-
127
- Month.new(2014, 1).step(Month.new(2014, 3), 2) { |month| months << month }
128
-
129
- months.must_equal([Month.new(2014, 1), Month.new(2014, 3)])
130
- end
131
-
132
- it 'decreases by the given number of months if the step argument is negative' do
133
- months = []
134
-
135
- Month.new(2014, 3).step(Month.new(2014, 1), -1) { |month| months << month }
136
-
137
- months.must_equal([Month.new(2014, 3), Month.new(2014, 2), Month.new(2014, 1)])
138
- end
139
- end
140
-
141
- describe 'upto method' do
142
- it 'calls the block for every month until the given limit' do
143
- months = []
144
-
145
- Month.new(2014, 1).upto(Month.new(2014, 3)) { |month| months << month }
146
-
147
- months.must_equal([Month.new(2014, 1), Month.new(2014, 2), Month.new(2014, 3)])
148
- end
149
-
150
- it 'returns an enumerator if no block was given' do
151
- months = Month.new(2014, 1).upto(Month.new(2014, 3))
152
-
153
- months.must_be_instance_of(Enumerator)
154
-
155
- months.next.must_equal(Month.new(2014, 1))
156
- months.next.must_equal(Month.new(2014, 2))
157
- months.next.must_equal(Month.new(2014, 3))
158
- end
159
- end
160
-
161
- describe 'downto method' do
162
- it 'calls the block for every month until the given limit' do
163
- months = []
164
-
165
- Month.new(2014, 3).downto(Month.new(2014, 1)) { |month| months << month }
166
-
167
- months.must_equal([Month.new(2014, 3), Month.new(2014, 2), Month.new(2014, 1)])
168
- end
169
-
170
- it 'returns an enumerator if no block was given' do
171
- months = Month.new(2014, 3).downto(Month.new(2014, 1))
172
-
173
- months.must_be_instance_of(Enumerator)
174
-
175
- months.next.must_equal(Month.new(2014, 3))
176
- months.next.must_equal(Month.new(2014, 2))
177
- months.next.must_equal(Month.new(2014, 1))
178
- end
179
- end
180
-
181
- describe 'addition' do
182
- it 'returns a month object denoting the given number of months after self' do
183
- (Month.new(2014, 1) + 1).must_equal(Month.new(2014, 2))
184
- (Month.new(2014, 1) + 12).must_equal(Month.new(2015, 1))
185
- (Month.new(2014, 1) + 18).must_equal(Month.new(2015, 7))
186
- (Month.new(2013, 11) + 1).must_equal(Month.new(2013, 12))
187
- (Month.new(2013, 11) + 2).must_equal(Month.new(2014, 1))
188
- end
189
- end
190
-
191
- describe 'subtraction' do
192
- it 'returns a month object denoting the given number of months before self' do
193
- (Month.new(2014, 2) - 1).must_equal(Month.new(2014, 1))
194
- (Month.new(2014, 1) - 1).must_equal(Month.new(2013, 12))
195
- (Month.new(2014, 1) - 12).must_equal(Month.new(2013, 1))
196
- (Month.new(2014, 1) - 18).must_equal(Month.new(2012, 7))
197
- (Month.new(2013, 12) - 1).must_equal(Month.new(2013, 11))
198
- (Month.new(2014, 1) - 2).must_equal(Month.new(2013, 11))
199
- end
200
-
201
- it 'returns the number of months between the given month and self' do
202
- (Month.new(2014, 3) - Month.new(2014, 1)).must_equal(2)
203
- (Month.new(2015, 1) - Month.new(2014, 1)).must_equal(12)
204
- (Month.new(2077, 4) - Month.new(2070, 4)).must_equal(84)
205
- end
206
- end
207
-
208
- describe 'include predicate method' do
209
- it 'returns true if the month includes the given date' do
210
- Month.new(2014, 1).include?(Date.new(2014, 1, 1)).must_equal(true)
211
- end
212
-
213
- it 'returns false otherwise' do
214
- Month.new(2014, 1).include?(Date.new(2014, 2, 1)).must_equal(false)
215
- end
216
- end
217
-
218
- describe 'case equals method' do
219
- it 'returns true if the month includes the given date' do
220
- (Month.new(2014, 1) === Date.new(2014, 1, 1)).must_equal(true)
221
- end
222
-
223
- it 'returns false otherwise' do
224
- (Month.new(2014, 1) === Date.new(2014, 2, 1)).must_equal(false)
225
- end
226
- end
227
-
228
- describe 'start_date method' do
229
- it 'returns a date object denoting the first day of the month' do
230
- Month.new(2014, 1).start_date.must_equal(Date.new(2014, 1, 1))
231
- end
232
- end
233
-
234
- describe 'end_date method' do
235
- it 'returns a date object denoting the last day of the month' do
236
- Month.new(2014, 1).end_date.must_equal(Date.new(2014, 1, 31))
237
- end
238
- end
239
-
240
- describe 'dates method' do
241
- it 'returns the range of dates in the month' do
242
- dates = Month.new(2014, 1).dates
243
- dates.must_be_instance_of(Range)
244
- dates.count.must_equal(31)
245
- dates.all? { |date| Date === date }.must_equal(true)
246
- dates.first.must_equal(Date.new(2014, 1, 1))
247
- dates.last.must_equal(Date.new(2014, 1, 31))
248
- end
249
- end
250
-
251
- describe 'length method' do
252
- it 'returns the integer number of days in the month' do
253
- Month.new(2014, 1).length.must_equal(31)
254
- Month.new(2014, 2).length.must_equal(28)
255
- end
256
- end
257
- end
258
-
259
- describe 'Month parse method' do
260
- it 'returns the month corresponding to the given string representation' do
261
- Month.parse('2014-01').must_equal(Month.new(2014, 1))
262
- end
263
-
264
- it 'raises an exception if the format of the string is not as expected' do
265
- proc { Month.parse('January 2014') }.must_raise(ArgumentError)
266
- end
267
- end
268
-
269
- describe 'Month method' do
270
- it 'returns the month of the given date object' do
271
- Month(Date.new(2014, 1, 1)).must_equal(Month.new(2014, 1))
272
- end
273
-
274
- it 'returns the month of the given time object' do
275
- Month(Time.at(1234567890)).must_equal(Month.new(2009, 2))
276
- end
277
-
278
- it 'returns the month of the given datetime object' do
279
- Month(DateTime.parse('2001-02-03T04:05:06+07:00')).must_equal(Month.new(2001, 2))
280
- end
281
-
282
- it 'returns the month of the given integer unix timestamp' do
283
- Month(1234567890).must_equal(Month.new(2009, 2))
284
- end
285
-
286
- it 'idempotently returns the given month' do
287
- month = Month.new(2014, 1)
288
-
289
- Month(month).object_id.must_equal(month.object_id)
290
- end
291
- end
292
-
293
- describe 'A method defined in Month::Methods' do
294
- include Month::Methods
295
-
296
- it 'returns a month object denoting that month in the given year' do
297
- month = January 2014
298
- month.must_equal(Month.new(2014, 1))
299
-
300
- month = February 2014
301
- month.must_equal(Month.new(2014, 2))
302
- end
303
-
304
- it 'returns a date object when given two arguments' do
305
- date = January 31, 2014
306
- date.must_equal(Date.new(2014, 1, 31))
307
-
308
- date = February 28, 2014
309
- date.must_equal(Date.new(2014, 2, 28))
310
- end
311
-
312
- it 'raises an exception if given too many arguments' do
313
- proc { January 1, 2, 3 }.must_raise(ArgumentError)
314
- end
315
- end