diff --git a/README.md b/README.md index 4692d80..c3d86b6 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,12 @@ Or install it yourself as: #### 2-4. String class - `'2020/10/30 00:00:00 +09:00'.prekin? #=> true` +#### 2-5. Next Prekin +- `Prekin.next #=> "2020-10-30"` +- `Prekin.next('2023-12-28') #=> "2023-12-29"` +- `Prekin.next('2023-12-29') #=> "2023-12-29"` +- `Prekin.next('2023-12-30') #=> "2024-01-26"` + ## Note - This gem overwrites `Time`, `Date`, `DateTime` and `String` class. - So if you use `Time`, `Date`, `DateTime` and `String` class in your code, you should be careful. diff --git a/lib/prekin.rb b/lib/prekin.rb index 02d691d..cae3a9b 100644 --- a/lib/prekin.rb +++ b/lib/prekin.rb @@ -6,4 +6,80 @@ module Prekin class Error < StandardError; end + + class << self + # TODO: 月および年をまたぐ場合の処理が都度都度になっており、複雑すぎる + def next(year_month_str = nil) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity + base_month = if year_month_str.nil? + Date.today.month + else + Date.parse(year_month_str).month + end + end_day_of_this_month = if year_month_str.nil? + Date.new(Date.today.year, base_month, -1) + else + Date.new( + Date.parse(year_month_str).year, + base_month, + -1 + ) + end + days_in_month = end_day_of_this_month.day + + # 現在の月を1日ずつ増やしながら、その日が金曜日かどうかをチェックする + dates = [] + for i in 1..days_in_month # rubocop:disable Style/For + date = if year_month_str.nil? + Date.new(Date.today.year, base_month, i) + else + Date.new(Date.parse(year_month_str).year, base_month, i) + end + + dates << date if date.wday == 5 + end + + # 金曜日である日付を配列で得て、最終金曜日を返す (String) + if dates.last < Date.parse(year_month_str || Date.today.to_s) + end_day_of_next_month = if year_month_str.nil? + if base_month == 12 + Date.new(Date.today.year + 1, 1, -1) + else + Date.new(Date.today.year, base_month + 1, -1) + end + elsif base_month == 12 + Date.new( + Date.parse(year_month_str).year + 1, + 1, + -1 + ) + else + Date.new( + Date.parse(year_month_str).year, + base_month + 1, + -1 + ) + end + days_in_month = end_day_of_next_month.day + + dates = [] + for i in 1..days_in_month # rubocop:disable Style/For + date = if year_month_str.nil? + if base_month == 12 # rubocop:disable Metrics/BlockNesting + Date.new(Date.today.year + 1, 1, i) + else + Date.new(Date.today.year, base_month + 1, i) + end + elsif base_month == 12 + Date.new(Date.parse(year_month_str).year + 1, 1, i) + else + Date.new(Date.parse(year_month_str).year, base_month + 1, i) + end + + dates << date if date.wday == 5 + end + end + + dates.last.to_s + end + end end diff --git a/spec/prekin_spec.rb b/spec/prekin_spec.rb new file mode 100644 index 0000000..faaa58a --- /dev/null +++ b/spec/prekin_spec.rb @@ -0,0 +1,93 @@ +# 10月 2020 +# 日 月 火 水 木 金 土 +# 1 2 3 +# 4 5 6 7 8 9 10 +# 11 12 13 14 15 16 17 +# 18 19 20 21 22 23 24 +# 25 26 27 28 29 30 31 +# +# 1月 2020 +# 日 月 火 水 木 金 土 +# 1 2 3 4 +# 5 6 7 8 9 10 11 +# 12 13 14 15 16 17 18 +# 19 20 21 22 23 24 25 +# 26 27 28 29 30 31 + +# 10月 2019 +# 日 月 火 水 木 金 土 +# 1 2 3 4 5 +# 6 7 8 9 10 11 12 +# 13 14 15 16 17 18 19 +# 20 21 22 23 24 25 26 +# 27 28 29 30 31 + +RSpec.describe Prekin do + describe 'クラスメソッド' do + describe '#next' do + xit '2023/09/05 における next は 2023/09/29 であること(日時指定なし)' do + # TODO: travel_to や Timecop が必要 + next_day = Prekin.next + + expect(next_day).to eq '2023-09-29' + end + + it '2023/09/05 における next は 2023/09/29 であること(日時指定あり)' do + next_day = Prekin.next('2023-09-05') + + expect(next_day).to eq '2023-09-29' + end + + it '2023/09/30 における next は 2023/10/27 であること(日時指定あり)' do + next_day = Prekin.next('2023-09-30') + + expect(next_day).to eq '2023-10-27' + end + + it '2023/12/28 における next は 2023/12/29 であること(日時指定あり)' do + next_day = Prekin.next('2023-12-28') + + expect(next_day).to eq '2023-12-29' + end + + it '2023/12/30 における next は 2024/01/26 であること(日時指定あり)' do + next_day = Prekin.next('2023-12-30') + + expect(next_day).to eq '2024-01-26' + end + + it '2022/12/24 における next は 2022/12/30 であること(日時指定あり)' do + next_day = Prekin.next('2022-12-24') + + expect(next_day).to eq '2022-12-30' + end + + it '2022/12/30 における next は 2022/12/30 であること(日時指定あり)' do + next_day = Prekin.next('2022-12-30') + + expect(next_day).to eq '2022-12-30' + end + + it '2022/12/31 における next は 2023/01/27 であること(日時指定あり)' do + next_day = Prekin.next('2022-12-31') + + expect(next_day).to eq '2023-01-27' + end + end + + describe '#previous' do + xit '2023/09/05 における previous は 2023/08/25 であること(日時指定なし)' do + # TODO: travel_to や Timecop が必要 + previous_day = Prekin.previous + + expect(previous_day).to eq '2023-08-25' + end + + xit '2023/09/05 における previous は 2023/08/25 であること(日時指定あり)' do + previous_day = Prekin.previous('2023-09-05') + + expect(previous_day).to eq '2023-08-25' + end + end + end +end