西暦 to 和暦
Posted feedbacks - Ruby
お題のサンプル出力では元年は前年号の最終年と併記していますが, 1年を元年としたことが同義だと考えてその記述は省略しました.
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 | require 'date'
require 'kconv'
WAREKI = [['明治', '1868/9/8'], ['大正', '1912/7/30'],
['昭和', '1926/12/25'], ['平成', '1989/1/8']]
DATES = %w('1868/12/2' '1926/12/24' '2007/12/01' '1926/12/25'
'1868/1/2' '1868/100/2')
wareki = WAREKI.sort{|a, b|
-1*(Date.parse(a[1]).year <=> Date.parse(b[1]).year)
} # => 新しい年代からマッチさせるためにソート
DATES.each{|date_str|
begin
date = Date.parse(date_str)
y0, m0, d0 = date.year, date.month, date.day
era = wareki.each{|nengo, date_str|
date = Date.parse(date_str)
y1, m1, d1 = date.year, date.month, date.day
evaluation = y0 >= y1 && (m0 > m1 or m0 == m1 && d0 >= d1)
break [nengo, y0 - y1] if evaluation
}
puts "#{era[0]}#{era[1] == 0 ? '元' : era[1] + 1}年#{m0}月#{d0}日".tosjis
rescue
puts '範囲外'.tosjis
next
end
}
|
文字列の比較と,Rangeを使って書きました. RubyのRangeは終点を無限大にできないので,自前でそれっぽいクラスを定義しました.
「明治」はFri Dec 13 20:45:52 UTC 1901以前を含むので,32ビットのtime_tでは表現できず,そのためTimeクラスが使えないってのが痛いなぁ.
実行結果:
./jdate.rb 1868/12/2 範囲外 ./jdate.rb 1926/12/24 大正15年12月24日 ./jdate.rb 2007/12/01 平成19年12月1日 ./jdate.rb 1926/12/25 大正15年12月25日 昭和1年12月25日 ./jdate.rb 1868/1/2 範囲外 ./jdate.rb 1868/100/2 範囲外 ./jdate.rb 1873/01/01 明治6年1月1日
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #!/usr/local/bin/ruby -Ke
require 'time'
class DateRange < Range
attr_reader :infinit
def initialize(first, last, exclude_end = false)
super
@infinit = true if first > last
end
def ===(other)
return super unless @infinit
return true if self.first <= other
return false
end
end
def acceptable?(date, y, m, d)
unless (0 < m and m < 13) and (0 < d and d < 32) and
(date >= '1873/01/01')
return false
end
return true
end
def usage
puts "usage: #{File.basename($0)} <date>"
end
class DateOutOfRange < Exception; end
era = [['明治', ['1868/01/25', '1912/07/30']],
['大正', ['1912/07/30', '1926/12/25']],
['昭和', ['1926/12/25', '1989/01/07']],
['平成', ['1989/01/08', '1970/01/01']]].
map {|name, r| [name, DateRange.new(*r)] }
begin
date = ARGV[0]
y, m, d = %r!(\d+)[/-](\d+)[/-](\d+)!.match(date).to_a[1..-1].map {|x| x.to_i}
date = "%04d/%02d/%02d" % [y, m, d]
raise DateOutOfRange unless acceptable?(date, y, m, d)
result = era.select {|_, r| r === date}.
map {|name, r| [name, y - r.first.split('/')[0].to_i + 1] }.
map {|name, y| "%s%d年%d月%d日" % [name, y, m, d] }
raise DateOutOfRange if result.empty?
puts result.join(' ')
rescue DateOutOfRange
puts '範囲外'
rescue
usage
exit(1)
end
|
caseを使って素直に実装してみました。太陰暦は考慮に入れていません。
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 32 33 34 35 36 | #!/usr/bin/env ruby -Ku
require 'date'
def seireki2wareki(date = Date.today)
case
when date > Date.new(1989, 1, 7)
"平成#{date.year - 1988}年#{date.month}月#{date.day}日"
when date == Date.new(1989, 1, 7)
'昭和64年1月7日 平成1年1月7日'
when date > Date.new(1926, 12, 25)
"昭和#{date.year - 1925}年#{date.month}月#{date.day}日"
when date == Date.new(1926, 12, 25)
'大正15年12月25日 昭和1年12月25日'
when date > Date.new(1912, 7, 30)
"大正#{date.year - 1911}年#{date.month}月#{date.day}日"
when date == Date.new(1912, 7, 30)
'明治45年7月30日 大正1年7月30日'
when date > Date.new(1868, 9, 8)
"明治#{date.year - 1867}年#{date.month}月#{date.day}日"
else
'範囲外'
end
end
if __FILE__ == $0
begin
if ARGV.empty?
puts seireki2wareki
else
puts seireki2wareki(Date.parse(ARGV.shift))
end
rescue
puts '範囲外'
end
end
|
だいぶ遅くなりましたが、投稿させていただきます。調べる日付を閾値の配列に放り込んでsort することで元号を調べています。
#明治6年未満は「範囲外」としました。
#明治6年未満は「範囲外」としました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | require 'date'
DAYS = [Date.parse('1873/1/1'), Date.parse('1912/7/30'), Date.parse('1926/12/25'), Date.parse('1989/1/8')]
GENGO = ['明治', '大正', '昭和', '平成']
def format_date(d, i)
raise if d < DAYS[0]
d = d + 365 * 6 + 1 if i <= 1 #明治用のオフセット
return "#{GENGO[i != 0 ? i - 1 : i]}#{d.year - DAYS[i - 1].year + 1}年#{d.month}月#{d.day}日"
end
begin
d = Date.parse(ARGV[0])
days = DAYS.push(d).sort
i = days.index(d)
puts (days.uniq.size == 4 && i != 0 ? format_date(d, i) << ' ' << format_date(d, i + 1) : format_date(d, i))
rescue
puts '範囲外'
end
|


ocean
#5067()
Rating0/8=0.00
>a.py 1868/12/2
明治1年12月2日
>a.py 1926/12/24
大正15年12月24日
>a.py 2007/12/01
平成19年12月1日
>a.py 1926/12/25
大正15年12月25日 昭和1年12月25日
>a.py 1868/1/2
範囲外
>a.py 1868/100/2
範囲外
see: 和暦西暦対応表
[ reply ]