lib/japanese_calendar/era/calculations.rb
# frozen_string_literal: true
module JapaneseCalendar
module Era #:nodoc:
Period = Struct.new(:beginning_of_period, :kanji_name, :romaji_name)
PERIODS = [
Period.new(Date.new(2019, 5, 1), '令和', 'Reiwa').freeze,
Period.new(Date.new(1989, 1, 8), '平成', 'Heisei').freeze,
Period.new(Date.new(1926, 12, 25), '昭和', 'Showa').freeze,
Period.new(Date.new(1912, 7, 30), '大正', 'Taisho').freeze,
Period.new(Date.new(1868, 1, 25), '明治', 'Meiji').freeze
].freeze
private_constant :Period, :PERIODS
# Calculations module.
module Calculations
MEIJI_6 = Date.new(1873, 1, 1)
private_constant :MEIJI_6
# Returns the Japanese era name (nengo) since 1 January 1873 (Meiji 6).
#
# reiwa = Time.new(2019, 5, 1) # => 2019-05-01 00:00:00 +0900
# reiwa.era_name # => "令和"
# reiwa.era_name(:romaji) # => "Reiwa"
#
# heisei = Time.new(1989, 1, 8) # => 1989-01-08 00:00:00 +0900
# heisei.era_name # => "平成"
# heisei.era_name(:romaji) # => "Heisei"
#
# showa = Time.new(1926, 12, 25) # => 1926-12-25 00:00:00 +0900
# showa.era_name # => "昭和"
# showa.era_name(:romaji) # => "Showa"
#
# taisho = Time.new(1912, 7, 30) # => 1912-07-30 00:00:00 +0900
# taisho.era_name # => "大正"
# taisho.era_name(:romaji) # => "Taisho"
#
# meiji = Time.new(1873, 1, 1) # => 1873-01-01 00:00:00 +0900
# meiji.era_name # => "明治"
# meiji.era_name(:romaji) # => "Meiji"
#
# Raises an error when the Japanese era name cannot be found.
#
# Time.new(1872, 12, 31).era_name # => RuntimeError
def era_name(character = :kanji)
unless %i[kanji romaji].include?(character)
raise ArgumentError, 'invalid character'
end
current_era.send("#{character}_name")
end
# Returns the year of the Japanese era since 1 January 1873 (Meiji 6).
#
# Time.new(2019, 5, 1).era_year # => 1
# Time.new(2019, 4, 30).era_year # => 31
# Time.new(1989, 1, 7).era_year # => 64
# Time.new(1926, 12, 24).era_year # => 15
# Time.new(1912, 7, 29).era_year # => 45
#
# Raises an error when the year of the Japanese era cannot be found.
#
# Time.new(1872, 12, 31).era_year # => RuntimeError
def era_year
year - current_era.beginning_of_period.year + 1
end
private
def current_era
error_proc = proc { raise "#{self.class.name.downcase} out of range" }
error_proc.call if to_date < MEIJI_6
PERIODS.find(error_proc) do |period|
period.beginning_of_period <= to_date
end
end
# Returns a string representing the full name of the Japanese era in
# Kanji ("令和").
def japanese_era_kanji_name
era_name(:kanji)
end
# Returns a string representing the abbreviated name of the Japanese era
# in Kanji ("令").
def japanese_era_kanji_abbreviated_name
japanese_era_kanji_name[0]
end
# Returns a string representing the full name of the Japanese era in
# Romaji ("Reiwa").
def japanese_era_romaji_name
era_name(:romaji)
end
# Returns a string representing the uppercased full name of the Japanese
# era in Romaji ("REIWA").
def japanese_era_romaji_uppercased_name
japanese_era_romaji_name.upcase
end
# Returns a string representing the abbreviated name of the Japanese era
# in Romaji ("R").
def japanese_era_romaji_abbreviated_name
japanese_era_romaji_name[0]
end
# Returns a string representing the year of the Japanese era ("1")
def japanese_era_year_string
format('%-d', era_year)
end
# Returns a string representing the zero-padded year of the Japanese era
# ("01").
def japanese_era_year_zero_padded_string
format('%02d', era_year)
end
# Returns a string representing the blank-padded year of the Japanese era
# (" 1").
def japanese_era_year_blank_padded_string
format('%2d', era_year)
end
end
end
end