month 1.3.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
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