wareki 0.1.0
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 +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/LICENSE +24 -0
- data/README.rdoc +103 -0
- data/Rakefile +6 -0
- data/lib/wareki/calendar_def.rb +1433 -0
- data/lib/wareki/common.rb +41 -0
- data/lib/wareki/core_ext.rb +33 -0
- data/lib/wareki/date.rb +206 -0
- data/lib/wareki/era_def.rb +502 -0
- data/lib/wareki/utils.rb +173 -0
- data/lib/wareki/version.rb +3 -0
- data/lib/wareki.rb +2 -0
- data/wareki.gemspec +25 -0
- metadata +101 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'wareki/calendar_def'
|
3
|
+
require 'wareki/era_def'
|
4
|
+
require 'date'
|
5
|
+
module Wareki
|
6
|
+
GREGORIAN_START = 2405160 # Date.new(1873, 1, 1, Date::GREGORIAN).jd
|
7
|
+
GREGORIAN_START_YEAR = 1873
|
8
|
+
IMPERIAL_START = 1480041 # Date.new(-660, 2, 11, Date::GREGORIAN).jd
|
9
|
+
IMPERIAL_START_YEAR = -660
|
10
|
+
DATE_INFINITY = ::Date.new(2**(0.size * 8 -2) -1, 12, 31) # Use max Fixnum as year.
|
11
|
+
YEAR_BY_NUM = Hash[*YEAR_DEFS.map{|y| [y.year, y]}.flatten].freeze
|
12
|
+
ERA_BY_NAME = Hash[*(ERA_NORTH_DEFS + ERA_DEFS).map {|g| [g.name, g]}.flatten]
|
13
|
+
ERA_BY_NAME['皇紀'] = ERA_BY_NAME['神武天皇即位紀元'] = Era.new('皇紀', -660, 1480041, DATE_INFINITY.jd)
|
14
|
+
ERA_BY_NAME.keys.each do |era_name|
|
15
|
+
alt_era_name = era_name.tr("宝霊神応暦祥寿斎観寛徳禄万福禎国亀", "寳靈神應曆祥壽斉觀寬德祿萬福禎國龜")
|
16
|
+
alt_era_name == era_name and next
|
17
|
+
ERA_BY_NAME[alt_era_name] = ERA_BY_NAME[era_name]
|
18
|
+
end
|
19
|
+
ERA_BY_NAME.freeze
|
20
|
+
NUM_CHARS = "零〇一二三四五六七八九十卄廿卅丗卌肆百皕千万億兆01234567890123456789"
|
21
|
+
ALT_MONTH_NAME = %w(睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走).freeze
|
22
|
+
REGEX = %r{^
|
23
|
+
(?<era_name>西暦|#{ERA_BY_NAME.keys.join('|')})?
|
24
|
+
(?:(?<year>[元#{NUM_CHARS}]+)年)?
|
25
|
+
(?:(?<is_leap>閏|潤|うるう)?
|
26
|
+
(?:(?<month>[正#{NUM_CHARS}]+)月 |
|
27
|
+
(?<alt_month>#{ALT_MONTH_NAME.join('|')})))?
|
28
|
+
(?:(?<day>[元朔晦#{NUM_CHARS}]+)日)?
|
29
|
+
$}x
|
30
|
+
|
31
|
+
class UnsupportedDateRange < StandardError; end
|
32
|
+
|
33
|
+
module_function
|
34
|
+
def parse_to_date(str, start = ::Date::ITALY)
|
35
|
+
begin
|
36
|
+
Date.parse(str).to_date(start)
|
37
|
+
rescue ArgumentError => e
|
38
|
+
::Date.parse(str, true, start)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'wareki/date'
|
3
|
+
module Wareki
|
4
|
+
module CoreExt
|
5
|
+
end
|
6
|
+
end
|
7
|
+
class Date
|
8
|
+
JAPAN = Wareki::GREGORIAN_START
|
9
|
+
|
10
|
+
def to_wareki_date
|
11
|
+
Wareki::Date.jd(self.jd)
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :_wareki_strftime_orig, :strftime
|
15
|
+
def strftime(format = "%F")
|
16
|
+
if format.index("%J")
|
17
|
+
to_wareki_date.strftime(format)
|
18
|
+
else
|
19
|
+
_wareki_strftime_orig(format)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
alias_method :_wareki_parse_orig, :parse
|
25
|
+
def parse(str, comp = true, start = ::Date::ITALY)
|
26
|
+
begin
|
27
|
+
Wareki::Date.parse(str).to_date(start)
|
28
|
+
rescue => e
|
29
|
+
::Date._wareki_parse_orig(str, comp, start)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/wareki/date.rb
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'date'
|
3
|
+
require 'wareki/common'
|
4
|
+
require 'wareki/utils'
|
5
|
+
module Wareki
|
6
|
+
|
7
|
+
class Date
|
8
|
+
attr_reader :jd
|
9
|
+
attr_accessor :year, :month, :day, :era_year, :era_name
|
10
|
+
|
11
|
+
def self._parse(str)
|
12
|
+
match = REGEX.match(str.to_s.gsub(/[[:space:]]/, ''))
|
13
|
+
if !match || !match[:year]
|
14
|
+
raise ArgumentError, "Invaild Date: #{str}"
|
15
|
+
end
|
16
|
+
era = match[:era_name]
|
17
|
+
year = Utils.kan_to_i(match[:year])
|
18
|
+
month = 1
|
19
|
+
day = 1
|
20
|
+
|
21
|
+
if era.to_s != "" && !ERA_BY_NAME[era]
|
22
|
+
raise ArgumentError, "Date parse failed: Invalid era name '#{match[:era_name]}'"
|
23
|
+
end
|
24
|
+
|
25
|
+
if match[:month]
|
26
|
+
month = Utils.kan_to_i(match[:month])
|
27
|
+
elsif match[:alt_month]
|
28
|
+
month = Utils.alt_month_name_to_i(match[:alt_month])
|
29
|
+
end
|
30
|
+
|
31
|
+
month > 12 || month < 0 and
|
32
|
+
raise ArgumentError, "Invalid month: #{str}"
|
33
|
+
|
34
|
+
if match[:day]
|
35
|
+
if match[:day] == "晦"
|
36
|
+
day = Utils.last_day_of_month(ERA_BY_NAME[era].year + year -1, month, match[:is_leap])
|
37
|
+
else
|
38
|
+
day = Utils.kan_to_i(match[:day])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if (era == "明治" && year == 5 ||
|
43
|
+
era.to_s == "" && year == GREGORIAN_START_YEAR - 1 ||
|
44
|
+
(era == "皇紀" || era == "神武天皇即位紀元") &&
|
45
|
+
year == GREGORIAN_START_YEAR - IMPERIAL_START_YEAR - 1) &&
|
46
|
+
month == 12 && day > 2
|
47
|
+
raise ArgumentError, "Invaild Date: #{str}"
|
48
|
+
end
|
49
|
+
|
50
|
+
{era: era, year: year, month: month, day: day, is_leap: !!match[:is_leap]}
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.parse(str)
|
54
|
+
di = _parse(str)
|
55
|
+
new(di[:era], di[:year], di[:month], di[:day], di[:is_leap])
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.jd(d)
|
59
|
+
era = Utils.find_era(d)
|
60
|
+
era or raise UnsupportedDateRange, "Cannot find era for date #{d.inspect}"
|
61
|
+
year, month, day, is_leap = Utils.find_date_ary(d)
|
62
|
+
obj = new(era.name, year - era.year + 1, month, day, is_leap)
|
63
|
+
obj.__set_jd(d)
|
64
|
+
obj
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.date(date)
|
68
|
+
jd(date.jd)
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.imperial(year, month = 1, day = 1, is_leap_month = false)
|
72
|
+
new("皇紀", year, month, day, is_leap_month)
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(era_name, era_year, month = 1, day = 1, is_leap_month = false)
|
76
|
+
if era_name.to_s != "" && era_name != "西暦" && !ERA_BY_NAME[era_name]
|
77
|
+
raise ArgumentError, "Undefined era '#{era_name}'"
|
78
|
+
end
|
79
|
+
@month = month
|
80
|
+
@day = day
|
81
|
+
@is_leap_month = is_leap_month
|
82
|
+
@era_name = era_name
|
83
|
+
@era_year = era_year
|
84
|
+
if era_name.to_s == ""
|
85
|
+
@year = @era_year
|
86
|
+
elsif era_name == "皇紀" || era_name == "神武天皇即位紀元"
|
87
|
+
@year = era_year + IMPERIAL_START_YEAR
|
88
|
+
else
|
89
|
+
@year = ERA_BY_NAME[era_name].year + era_year - 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def imperial_year
|
94
|
+
@year - IMPERIAL_START_YEAR
|
95
|
+
end
|
96
|
+
|
97
|
+
def imperial_year=(v)
|
98
|
+
@year = v - IMPERIAL_START_YEAR
|
99
|
+
end
|
100
|
+
|
101
|
+
def leap_month?
|
102
|
+
!!@is_leap_month
|
103
|
+
end
|
104
|
+
|
105
|
+
def leap_month=(v)
|
106
|
+
@is_leap_month = v
|
107
|
+
end
|
108
|
+
|
109
|
+
def __set_jd(v)
|
110
|
+
@jd = v
|
111
|
+
end
|
112
|
+
|
113
|
+
def month_index
|
114
|
+
if @era_name == "西暦" || @year >= GREGORIAN_START_YEAR
|
115
|
+
return month -1
|
116
|
+
end
|
117
|
+
|
118
|
+
yobj = YEAR_BY_NUM[@year] or
|
119
|
+
raise UnsupportedDateRange, "Cannot get year info of #{self.inspect}"
|
120
|
+
idx = month - 1
|
121
|
+
if leap_month? || yobj.leap_month && month > yobj.leap_month
|
122
|
+
idx += 1
|
123
|
+
end
|
124
|
+
idx
|
125
|
+
end
|
126
|
+
|
127
|
+
def jd
|
128
|
+
@jd and return @jd
|
129
|
+
|
130
|
+
if @era_name == "西暦"
|
131
|
+
return @jd = ::Date.new(@year, month, day, ::Date::ITALY).jd
|
132
|
+
elsif @year >= GREGORIAN_START_YEAR
|
133
|
+
return @jd = ::Date.new(@year, month, day, ::Date::GREGORIAN).jd
|
134
|
+
end
|
135
|
+
|
136
|
+
yobj = YEAR_BY_NUM[@year] or
|
137
|
+
raise UnsupportedDateRange, "Cannot convert to jd #{self.inspect}"
|
138
|
+
@jd = yobj.month_starts[month_index] + day - 1
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_date(start = ::Date::ITALY)
|
142
|
+
::Date.jd(jd, start)
|
143
|
+
end
|
144
|
+
|
145
|
+
def strftime(format_str = "%JF")
|
146
|
+
ret = format_str.to_str.gsub(/%J([fFyYegGoOiImMsSlLdD][kK]?)/) { format($1) || $& }
|
147
|
+
ret.index("%") or return ret
|
148
|
+
d = to_date
|
149
|
+
d.respond_to?(:_wareki_strftime_orig) ? d._wareki_strftime_orig(ret) : d.strftime(ret)
|
150
|
+
end
|
151
|
+
|
152
|
+
def format(key)
|
153
|
+
case key.to_sym
|
154
|
+
when :e; era_name
|
155
|
+
when :g; era_name.to_s == "" ? '' : era_year
|
156
|
+
when :G; era_name.to_s == "" ? '' : Utils.i_to_zen(era_year)
|
157
|
+
when :Gk; era_name.to_s == "" ? '' : Utils.i_to_kan(era_year)
|
158
|
+
when :GK
|
159
|
+
if era_name.to_s == ""
|
160
|
+
''
|
161
|
+
elsif era_year == 1
|
162
|
+
"元"
|
163
|
+
else
|
164
|
+
Utils.i_to_kan(era_year)
|
165
|
+
end
|
166
|
+
when :o; year
|
167
|
+
when :O; Utils.i_to_zen(year)
|
168
|
+
when :Ok; Utils.i_to_kan(year)
|
169
|
+
when :i; imperial_year
|
170
|
+
when :I; Utils.i_to_zen(imperial_year)
|
171
|
+
when :Ik; Utils.i_to_kan(imperial_year)
|
172
|
+
when :s; month
|
173
|
+
when :S; Utils.i_to_zen(month)
|
174
|
+
when :Sk; Utils.i_to_kan(month)
|
175
|
+
when :SK; ALT_MONTH_NAME[month-1]
|
176
|
+
when :l; leap_month? ? "'" : ""
|
177
|
+
when :L; leap_month? ? "’" : ""
|
178
|
+
when :Lk; leap_month? ? "閏" : ""
|
179
|
+
when :d; day
|
180
|
+
when :D; Utils.i_to_zen(day)
|
181
|
+
when :Dk; Utils.i_to_kan(day)
|
182
|
+
when :DK
|
183
|
+
if month == 1 && !leap_month? && day == 1
|
184
|
+
"元"
|
185
|
+
elsif day == 1
|
186
|
+
"朔"
|
187
|
+
elsif day == Utils.last_day_of_month(year, month, leap_month?)
|
188
|
+
"晦"
|
189
|
+
else
|
190
|
+
Utils.i_to_kan(day)
|
191
|
+
end
|
192
|
+
when :m; "#{format(:s)}#{format(:l)}"
|
193
|
+
when :M; "#{format(:Lk)}#{format(:S)}"
|
194
|
+
when :Mk; "#{format(:Lk)}#{format(:Sk)}"
|
195
|
+
when :y; "#{format(:e)}#{format(:g)}"
|
196
|
+
when :Y; "#{format(:e)}#{format(:G)}"
|
197
|
+
when :Yk; "#{format(:e)}#{format(:Gk)}"
|
198
|
+
when :YK; "#{format(:e)}#{format(:GK)}"
|
199
|
+
when :f; "#{format(:e)}#{format(:g)}年#{format(:s)}#{format(:l)}月#{format(:d)}日"
|
200
|
+
when :F; "#{format(:e)}#{format(:GK)}年#{format(:Lk)}#{format(:Sk)}月#{format(:Dk)}日"
|
201
|
+
else
|
202
|
+
nil
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|