when_exe 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (194) hide show
  1. data/bin/irb.rc +1 -0
  2. data/bin/locales.rb +8 -6
  3. data/bin/when.rb +1 -1
  4. data/lib/when_exe.rb +231 -146
  5. data/lib/when_exe/basictypes.rb +108 -18
  6. data/lib/when_exe/calendarnote.rb +263 -116
  7. data/lib/when_exe/calendartypes.rb +413 -22
  8. data/lib/when_exe/coordinates.rb +58 -36
  9. data/lib/when_exe/core/compatibility.rb +8 -6
  10. data/lib/when_exe/core/extension.rb +40 -15
  11. data/lib/when_exe/ephemeris.rb +20 -19
  12. data/lib/when_exe/{region → ephemeris}/moon.rb +4 -4
  13. data/lib/when_exe/{region/ephemeric_notes.rb → ephemeris/notes.rb} +25 -6
  14. data/lib/when_exe/{region → ephemeris}/planets.rb +0 -0
  15. data/lib/when_exe/{region → ephemeris}/sun.rb +7 -3
  16. data/lib/when_exe/{region → ephemeris}/v50.rb +0 -0
  17. data/lib/when_exe/googlecalendar.rb +2 -2
  18. data/lib/when_exe/icalendar.rb +3 -3
  19. data/lib/when_exe/inspect.rb +130 -70
  20. data/lib/when_exe/locales/af.rb +2 -2
  21. data/lib/when_exe/locales/akt.rb +176 -0
  22. data/lib/when_exe/locales/ar.rb +2 -2
  23. data/lib/when_exe/locales/{locales.rb → autoload.rb} +6 -2
  24. data/lib/when_exe/locales/az.rb +2 -2
  25. data/lib/when_exe/locales/bg.rb +2 -2
  26. data/lib/when_exe/locales/bn.rb +2 -2
  27. data/lib/when_exe/locales/bs.rb +2 -2
  28. data/lib/when_exe/locales/ca.rb +2 -2
  29. data/lib/when_exe/locales/cs.rb +2 -2
  30. data/lib/when_exe/locales/cy.rb +2 -2
  31. data/lib/when_exe/locales/da.rb +2 -2
  32. data/lib/when_exe/locales/de.rb +2 -2
  33. data/lib/when_exe/locales/de_AT.rb +2 -2
  34. data/lib/when_exe/locales/de_CH.rb +2 -2
  35. data/lib/when_exe/locales/el.rb +2 -2
  36. data/lib/when_exe/locales/en.rb +2 -2
  37. data/lib/when_exe/locales/en_AU.rb +2 -2
  38. data/lib/when_exe/locales/en_CA.rb +2 -2
  39. data/lib/when_exe/locales/en_GB.rb +2 -2
  40. data/lib/when_exe/locales/en_IE.rb +2 -2
  41. data/lib/when_exe/locales/en_IN.rb +3 -3
  42. data/lib/when_exe/locales/en_NZ.rb +2 -2
  43. data/lib/when_exe/locales/en_US.rb +2 -2
  44. data/lib/when_exe/locales/en_ZA.rb +88 -0
  45. data/lib/when_exe/locales/encoding_conversion.rb +126 -0
  46. data/lib/when_exe/locales/eo.rb +2 -2
  47. data/lib/when_exe/locales/es.rb +2 -2
  48. data/lib/when_exe/locales/es_419.rb +2 -2
  49. data/lib/when_exe/locales/es_AR.rb +2 -2
  50. data/lib/when_exe/locales/es_CL.rb +2 -2
  51. data/lib/when_exe/locales/es_CO.rb +2 -2
  52. data/lib/when_exe/locales/es_CR.rb +2 -2
  53. data/lib/when_exe/locales/es_EC.rb +2 -2
  54. data/lib/when_exe/locales/es_MX.rb +2 -2
  55. data/lib/when_exe/locales/es_PA.rb +2 -2
  56. data/lib/when_exe/locales/es_PE.rb +2 -2
  57. data/lib/when_exe/locales/es_US.rb +84 -0
  58. data/lib/when_exe/locales/es_VE.rb +2 -2
  59. data/lib/when_exe/locales/et.rb +2 -2
  60. data/lib/when_exe/locales/eu.rb +2 -2
  61. data/lib/when_exe/locales/fa.rb +2 -2
  62. data/lib/when_exe/locales/fi.rb +3 -3
  63. data/lib/when_exe/locales/fr.rb +2 -2
  64. data/lib/when_exe/locales/fr_CA.rb +2 -2
  65. data/lib/when_exe/locales/fr_CH.rb +2 -2
  66. data/lib/when_exe/locales/gl.rb +2 -2
  67. data/lib/when_exe/locales/he.rb +3 -3
  68. data/lib/when_exe/locales/hi.rb +2 -2
  69. data/lib/when_exe/locales/hi_IN.rb +2 -2
  70. data/lib/when_exe/locales/hr.rb +2 -2
  71. data/lib/when_exe/locales/hu.rb +6 -5
  72. data/lib/when_exe/locales/iast.rb +90 -0
  73. data/lib/when_exe/locales/id.rb +2 -2
  74. data/lib/when_exe/locales/is.rb +2 -2
  75. data/lib/when_exe/locales/it.rb +2 -2
  76. data/lib/when_exe/locales/it_CH.rb +2 -2
  77. data/lib/when_exe/locales/ja.rb +2 -2
  78. data/lib/when_exe/locales/kn.rb +2 -2
  79. data/lib/when_exe/locales/ko.rb +2 -2
  80. data/lib/when_exe/locales/links.rb +3 -3
  81. data/lib/when_exe/locales/lo.rb +2 -2
  82. data/lib/when_exe/{parts → locales}/locale.rb +77 -49
  83. data/lib/when_exe/locales/lt.rb +6 -2
  84. data/lib/when_exe/locales/lv.rb +2 -2
  85. data/lib/when_exe/locales/mk.rb +2 -2
  86. data/lib/when_exe/locales/mn.rb +2 -2
  87. data/lib/when_exe/locales/ms.rb +2 -2
  88. data/lib/when_exe/locales/nb.rb +2 -2
  89. data/lib/when_exe/locales/ne.rb +2 -2
  90. data/lib/when_exe/locales/nl.rb +2 -2
  91. data/lib/when_exe/locales/nn.rb +2 -2
  92. data/lib/when_exe/locales/or.rb +2 -2
  93. data/lib/when_exe/locales/pl.rb +2 -2
  94. data/lib/when_exe/locales/pt.rb +2 -2
  95. data/lib/when_exe/locales/pt_BR.rb +2 -2
  96. data/lib/when_exe/locales/rm.rb +2 -2
  97. data/lib/when_exe/locales/ro.rb +2 -2
  98. data/lib/when_exe/locales/ru.rb +2 -2
  99. data/lib/when_exe/locales/sk.rb +2 -2
  100. data/lib/when_exe/locales/sl.rb +2 -2
  101. data/lib/when_exe/locales/sr.rb +2 -2
  102. data/lib/when_exe/locales/sv.rb +2 -2
  103. data/lib/when_exe/locales/sw.rb +2 -2
  104. data/lib/when_exe/locales/ta.rb +95 -0
  105. data/lib/when_exe/locales/th.rb +2 -2
  106. data/lib/when_exe/locales/tl.rb +3 -3
  107. data/lib/when_exe/locales/tr.rb +2 -2
  108. data/lib/when_exe/locales/transliteration_table.rb +62 -0
  109. data/lib/when_exe/locales/uk.rb +15 -15
  110. data/lib/when_exe/locales/ur.rb +2 -2
  111. data/lib/when_exe/locales/uz.rb +2 -2
  112. data/lib/when_exe/locales/vi.rb +2 -2
  113. data/lib/when_exe/locales/wo.rb +2 -2
  114. data/lib/when_exe/locales/zh_CN.rb +2 -2
  115. data/lib/when_exe/locales/zh_HK.rb +15 -15
  116. data/lib/when_exe/locales/zh_TW.rb +2 -2
  117. data/lib/when_exe/locales/zh_YUE.rb +77 -0
  118. data/lib/when_exe/mini_application.rb +22 -12
  119. data/lib/when_exe/parts/geometric_complex.rb +16 -1
  120. data/lib/when_exe/parts/method_cash.rb +184 -238
  121. data/lib/when_exe/parts/resource.rb +65 -16
  122. data/lib/when_exe/region/armenian.rb +56 -0
  123. data/lib/when_exe/region/bahai.rb +13 -13
  124. data/lib/when_exe/region/balinese.rb +33 -35
  125. data/lib/when_exe/region/chinese.rb +82 -78
  126. data/lib/when_exe/region/{chinese_calendar.rb → chinese/calendars.rb} +59 -40
  127. data/lib/when_exe/region/{chinese_epoch.rb → chinese/epochs.rb} +3 -4
  128. data/lib/when_exe/region/{chinese_twin.rb → chinese/twins.rb} +48 -51
  129. data/lib/when_exe/region/christian.rb +236 -127
  130. data/lib/when_exe/region/coptic.rb +9 -10
  131. data/lib/when_exe/region/dee.rb +48 -0
  132. data/lib/when_exe/region/discordian.rb +225 -0
  133. data/lib/when_exe/region/far_east.rb +2 -6
  134. data/lib/when_exe/region/french.rb +7 -17
  135. data/lib/when_exe/region/geologicalage.rb +0 -1
  136. data/lib/when_exe/region/goddess.rb +58 -0
  137. data/lib/when_exe/region/indian.rb +323 -231
  138. data/lib/when_exe/region/iranian.rb +159 -22
  139. data/lib/when_exe/region/islamic.rb +7 -9
  140. data/lib/when_exe/region/japanese.rb +14 -803
  141. data/lib/when_exe/region/japanese/calendars.rb +397 -0
  142. data/lib/when_exe/region/japanese/epochs.rb +426 -0
  143. data/lib/when_exe/region/{nihon_shoki.rb → japanese/nihon_shoki.rb} +0 -2
  144. data/lib/when_exe/region/{japanese_notes.rb → japanese/notes.rb} +179 -150
  145. data/lib/when_exe/region/japanese/residues.rb +1306 -0
  146. data/lib/when_exe/region/{japanese_twin.rb → japanese/twins.rb} +12 -15
  147. data/lib/when_exe/region/javanese.rb +16 -14
  148. data/lib/when_exe/region/jewish.rb +8 -9
  149. data/lib/when_exe/region/korean.rb +146 -35
  150. data/lib/when_exe/region/m17n.rb +8 -10
  151. data/lib/when_exe/region/martian.rb +44 -16
  152. data/lib/when_exe/region/mayan.rb +12 -10
  153. data/lib/when_exe/region/pope.rb +0 -1
  154. data/lib/when_exe/region/residue.rb +4 -5
  155. data/lib/when_exe/region/roman.rb +20 -24
  156. data/lib/when_exe/region/ryukyu.rb +3 -4
  157. data/lib/when_exe/region/shire.rb +97 -94
  158. data/lib/when_exe/region/symmetry.rb +50 -0
  159. data/lib/when_exe/region/thai.rb +164 -56
  160. data/lib/when_exe/region/tibetan.rb +86 -86
  161. data/lib/when_exe/region/vietnamese.rb +9 -12
  162. data/lib/when_exe/region/weekdate.rb +80 -0
  163. data/lib/when_exe/region/world.rb +65 -70
  164. data/lib/when_exe/region/yerm.rb +98 -0
  165. data/lib/when_exe/region/zoroastrian.rb +203 -0
  166. data/lib/when_exe/timestandard.rb +4 -4
  167. data/lib/when_exe/tmobjects.rb +1 -3
  168. data/lib/when_exe/tmposition.rb +13 -12
  169. data/lib/when_exe/tmreference.rb +11 -10
  170. data/lib/when_exe/version.rb +1 -1
  171. data/link_to_online_documents +3 -3
  172. data/test/examples/Residue.m17n +1 -1
  173. data/test/examples/Terms.m17n +1 -1
  174. data/test/test.rb +2 -1
  175. data/test/test/basictypes.rb +18 -2
  176. data/test/test/calendarnote.rb +1 -1
  177. data/test/test/calendartypes.rb +1 -1
  178. data/test/test/coordinates.rb +7 -7
  179. data/test/test/{region → ephemeris}/moon.rb +0 -0
  180. data/test/test/{region → ephemeris}/planets.rb +0 -0
  181. data/test/test/{region → ephemeris}/sun.rb +0 -0
  182. data/test/test/parts.rb +8 -13
  183. data/test/test/region/christian.rb +245 -0
  184. data/test/test/region/french.rb +16 -16
  185. data/test/test/region/iran.rb +34 -34
  186. data/test/test/region/japanese.rb +6 -4
  187. data/test/test/region/m17n.rb +8 -7
  188. data/test/test/region/mayan.rb +12 -12
  189. data/test/test/region/residue.rb +20 -4
  190. data/test/test/region/thai.rb +25 -3
  191. data/test/test/region/yerm.rb +146 -0
  192. metadata +39 -20
  193. data/lib/when_exe/region/japanese_residues.rb +0 -1212
  194. data/test/test/region/civil.rb +0 -124
@@ -58,7 +58,7 @@ module When::CalendarTypes
58
58
  def _normalize(args=[], options={})
59
59
  @label ||= m17n('Z')
60
60
  @indices ||= When::Coordinates::DefaultTimeIndices
61
- @note ||= 'JulianDayNotes'
61
+ @note ||= 'JulianDay'
62
62
  _normalize_spatial
63
63
  _normalize_temporal
64
64
  @second = (@second||1/When::TM::Duration::SECOND).to_f
@@ -144,6 +144,197 @@ module When::CalendarTypes
144
144
  end
145
145
  end
146
146
 
147
+ #
148
+ # 太陰(太陽)暦の朔閏パターンを扱うモジュール
149
+ #
150
+ module Lunar
151
+
152
+ # @private
153
+ Pattern = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ'
154
+
155
+ # 朔閏表を生成する
156
+ #
157
+ # @param [Range] range 生成範囲(西暦年)
158
+ # @param [Integer] length 大の月の日数
159
+ # @param [When::TM::Duration] duration チェックする月の間隔
160
+ #
161
+ # @return [Hash] 朔閏表
162
+ #
163
+ def lunar_table(range, length=30, duration=When::P1M)
164
+ date = When.TemporalPosition(range.first, {:frame=>self}).floor
165
+ table = []
166
+ hash = {
167
+ 'origin_of_MSC' => range.first,
168
+ 'origin_of_LSC' => date.to_i,
169
+ 'rule_table' => table
170
+ }
171
+ list = ''
172
+ while range.include?(date[YEAR])
173
+ month = date[MONTH] * 1
174
+ char = Pattern[month..month]
175
+ char = char.downcase unless date.length(MONTH) == length
176
+ list += char
177
+ succ = date + duration
178
+ unless date[YEAR] == succ[YEAR]
179
+ table << list
180
+ list = ''
181
+ end
182
+ date = succ
183
+ end
184
+ hash
185
+ end
186
+
187
+ # 朔閏表を比較する
188
+ #
189
+ # @param [When::TM::Calendar] base 基準とする暦法
190
+ # @param [Range] range 比較範囲(西暦年)
191
+ # @param [Integer] length 大の月の日数
192
+ # @param [When::TM::Duration] duration チェックする月の間隔
193
+ #
194
+ # @return [Hash] 朔閏表の差分
195
+ #
196
+ def verify(base, range=base.range, length=30, duration=When::P1M)
197
+ range = When::Parts::GeometricComplex.new(range) & When::Parts::GeometricComplex.new(self.range) if respond_to?(:range)
198
+ base_table = base.lunar_table(range, length, duration)
199
+ self_table = self.lunar_table(range, length, duration)
200
+ hash = {}
201
+ range.each do |year|
202
+ difference = _verify(base_table['rule_table'][year-range.first],
203
+ self_table['rule_table'][year-range.first])
204
+ hash[year] = difference if difference
205
+ end
206
+ hash
207
+ end
208
+
209
+ # @private
210
+ def _verify(source, target)
211
+ return nil if source == target
212
+ return {source => target} unless source.length == target.length
213
+ indices = []
214
+ index = []
215
+ source.length.times do |i|
216
+ if source[i..i] == target[i..i]
217
+ unless index.empty?
218
+ indices << index
219
+ index = []
220
+ end
221
+ else
222
+ index << i
223
+ end
224
+ end
225
+ indices << index unless index.empty?
226
+ ranges = []
227
+ indices.each do |index|
228
+ if ranges.empty? || index.first > ranges.last.last + 2
229
+ ranges << index
230
+ else
231
+ ranges[-1] = [ranges.last.first,index.last]
232
+ end
233
+ end
234
+ hash = {}
235
+ ranges.each do |index|
236
+ range = index.first..index.last
237
+ hash[source[range]] = target[range]
238
+ end
239
+ test = source.dup
240
+ hash.each_pair do |key, value|
241
+ test.sub!(key, value)
242
+ end
243
+ # raise ArgumentError, "can't replace '#{source}'=>'#{target}' by #{hash}." unless test == target
244
+ return hash if test == target
245
+ {source => target}
246
+ end
247
+ end
248
+
249
+ #
250
+ # 朔閏パターンの表の拡張
251
+ #
252
+ module TableExtend
253
+
254
+ # 年月日 -> 通日
255
+ #
256
+ # @param [Numeric] y 年
257
+ # @param [Integer] m 月 (0 始まり)
258
+ # @param [Integer] d 日 (0 始まり)
259
+ #
260
+ # @return [Integer] 通日
261
+ #
262
+ def _coordinates_to_number(y, m, d)
263
+ if @after && y >= @rule_table[@entry_key]['Years']
264
+ _normalize_after
265
+ return @after._coordinates_to_number(y + @_after_offset, m, d)
266
+ end
267
+ if @before && y < 0
268
+ _normalize_before
269
+ return @before._coordinates_to_number(y + @_before_offset, m, d)
270
+ end
271
+ super
272
+ end
273
+
274
+ # 通日 - > 年月日
275
+ #
276
+ # @param [Integer] sdn 通日
277
+ #
278
+ # @return [Array<Integer>] [ y, m, d ]
279
+ # y 年
280
+ # m 月 (0 始まり)
281
+ # d 日 (0 始まり)
282
+ #
283
+ def _number_to_coordinates(sdn)
284
+ if @after && sdn >= @origin_of_LSC + @rule_table[@entry_key]['Days']
285
+ _normalize_after
286
+ y, m, d = @after._number_to_coordinates(sdn)
287
+ return [y - @_after_offset, m, d]
288
+ end
289
+ if @before && sdn < @origin_of_LSC
290
+ _normalize_before
291
+ y, m, d = @before._number_to_coordinates(sdn)
292
+ return [y - @_before_offset, m, d]
293
+ end
294
+ super
295
+ end
296
+
297
+ #
298
+ # その他のテーブル参照
299
+ #
300
+ %w(ids_ length).each do |method|
301
+ module_eval %Q{
302
+ def _#{method}(date)
303
+ if @after && +date[0] >= @rule_table[@entry_key]['Years']
304
+ _normalize_after
305
+ date[0] += @_after_offset
306
+ return @after.send(:_#{method}, date)
307
+ end
308
+ if @before && +date[0] < 0
309
+ _normalize_before
310
+ date[0] += @_before_offset
311
+ return @before.send(:_#{method}, date)
312
+ end
313
+ super
314
+ end
315
+ }
316
+ end
317
+
318
+ private
319
+
320
+ def _normalize_after
321
+ raise RangeError, "Out of range: #{iri}" if @after.kind_of?(Symbol)
322
+ @after = When.Calendar(@after)
323
+ @_after_offset = @origin_of_MSC - @after.origin_of_MSC
324
+ class << self; alias :_normalize_after :_normalize_non end
325
+ end
326
+
327
+ def _normalize_before
328
+ raise RangeError, "Out of range: #{iri}" if @before.kind_of?(Symbol)
329
+ @before = When.Calendar(@before)
330
+ @_before_offset = @origin_of_MSC - @before.origin_of_MSC
331
+ class << self; alias :_normalize_before :_normalize_non end
332
+ end
333
+
334
+ def _normalize_non
335
+ end
336
+ end
337
+
147
338
  # 月日の配当パターンの種類が限定されている暦の抽象基底クラス
148
339
  #
149
340
  # Calendar which has some fixed arrangement rules for under year
@@ -245,6 +436,9 @@ module When::CalendarTypes
245
436
  @mean_month = Rational(@rule_table[@entry_key]['Days'], @rule_table[@entry_key]['Months'])
246
437
  @mean_year = Rational(@rule_table[@entry_key]['Days'], @rule_table[@entry_key]['Years' ])
247
438
  end
439
+
440
+ # range extension
441
+ extend(TableExtend) if @before || @after
248
442
  end
249
443
 
250
444
  # rule の正規化
@@ -349,20 +543,16 @@ module When::CalendarTypes
349
543
  rule = {
350
544
  'Years' => 1,
351
545
  'Months' => key.length,
352
- 'Days' => key.length * 29 + key.gsub(/[a-z]/,'').length,
546
+ 'Days' => _year_length(key),
353
547
  'IDs' => [],
354
548
  'Length' => [],
355
549
  'Offset' => []
356
550
  }
357
551
 
358
- key.length.times do |k|
359
- rule['Length'] << (key[k,1] =~ /[a-z]/ ? 29 : 30)
360
- rule['Offset'] << (k == 0 ? 0 : rule['Offset'][k-1]+rule['Length'][k-1])
361
- trunk = key.upcase[k]
362
- branch = (trunk == key.upcase[k-1]) ? 1 : 0
363
- trunk = trunk.ord if trunk.kind_of?(String)
364
- trunk -= 64
365
- rule['IDs'] << ((branch==0) ? trunk : When::Coordinates::Pair.new(trunk, branch))
552
+ key.length.times do |m|
553
+ rule['Length'] << _month_length(key, m)
554
+ rule['Offset'] << (m == 0 ? 0 : rule['Offset'][m-1]+rule['Length'][m-1])
555
+ rule['IDs'] << _month_id(key, m)
366
556
  end
367
557
  return rule
368
558
  end
@@ -374,6 +564,115 @@ module When::CalendarTypes
374
564
  #
375
565
  class PatternTableBasedLuniSolar < TableBased
376
566
 
567
+ include Lunar
568
+
569
+ class << self
570
+ #
571
+ # ひとつのひな型朔閏表からの差分で朔閏表を生成する
572
+ #
573
+ # @param [Array] definition ひな型朔閏表
574
+ # @param [Range] range 生成する朔閏表の年代範囲
575
+ # @param [Hash{Integer=>(String or Hash{String or Regexp=>String})}] difference 差分情報
576
+ #
577
+ # @return [Array] 生成された朔閏表定義
578
+ #
579
+ def patch(definition, range=nil, difference={})
580
+ When.Calendar(definition)
581
+ base = When::CalendarTypes.const_get(definition)
582
+ hash = base[-1].dup
583
+ range ||= hash['origin_of_MSC']...(hash['origin_of_MSC']+hash['rule_table'].size)
584
+ range = range.to_a
585
+ hash['origin_of_LSC'] += hash['rule_table'][range[0]-hash['origin_of_MSC']][1]
586
+ hash['rule_table'] = range.map {|year|
587
+ original = hash['rule_table'][year-hash['origin_of_MSC']][0]
588
+ case difference[year]
589
+ when String ; next difference[year]
590
+ when nil ; next original
591
+ end
592
+ original = original.dup
593
+ difference[year].each_pair {|key,value|
594
+ raise ArgumentError, "Can't patch \"#{original}\" by {#{key}=>#{value}} at #{year}" unless original.sub!(key,value)
595
+ }
596
+ original
597
+ }
598
+ hash['origin_of_MSC'] = range[0]
599
+ base[0..-2] + [hash]
600
+ end
601
+
602
+ #
603
+ # 複数のひな型朔閏表からの差分で朔閏表を生成する
604
+ #
605
+ # @param [[Array<Array<String, Range>>]] definitions ひな型朔閏表
606
+ # - String - もとにする太陰太陽暦のIRI文字列
607
+ # - Range - 朔閏表の年代範囲(デフォルトはもとにする太陰太陽暦の年代範囲)
608
+ # @param [Hash{Integer=>(String or Hash{String or Regexp=>String})}] difference 差分情報
609
+ #
610
+ # @return [Array] 生成された朔閏表定義
611
+ #
612
+ def join(definitions, difference={})
613
+ if definitions.first.kind_of?(Array)
614
+ base = When::CalendarTypes.const_get(definitions.first[0]).dup
615
+ else
616
+ base = []
617
+ base << definitions.shift until definitions.first.kind_of?(Array)
618
+ end
619
+ tables = definitions.map {|definition|
620
+ When.Calendar(definition[0]).lunar_table(definition[1])
621
+ }
622
+ hash = base.pop.merge({
623
+ 'origin_of_MSC' => tables.first['origin_of_MSC'],
624
+ 'origin_of_LSC' => tables.first['origin_of_LSC'],
625
+ 'rule_table' => tables.inject([]) {|rules, table| rules += table['rule_table']}
626
+ })
627
+ difference.each_pair do |year, pattern|
628
+ offset = year - hash['origin_of_MSC']
629
+ hash['rule_table'][offset] =
630
+ if pattern.kind_of?(Hash)
631
+ rule = hash['rule_table'][offset].dup
632
+ pattern.each_pair do |key,value|
633
+ raise ArgumentError, "Can't patch \"#{rule}\" by {#{key}=>#{value}} at #{year}" unless rule.sub!(key,value)
634
+ end
635
+ rule
636
+ else
637
+ pattern
638
+ end
639
+ end
640
+ base << hash
641
+ end
642
+ end
643
+
644
+ # 朔閏表を生成する
645
+ #
646
+ # @param [Range] sub_range 生成範囲(西暦年) デフォルトは self.range
647
+ # @param [Integer] length 大の月の日数(ダミー)
648
+ # @param [When::TM::Duration] duration チェックする月の間隔(ダミー)
649
+ #
650
+ # @return [Hash] 朔閏表
651
+ #
652
+ def lunar_table(sub_range=nil, length=nil, duration=nil)
653
+ sub_range ||= range
654
+ last = sub_range.last
655
+ last -= 1 if sub_range.exclude_end?
656
+ [sub_range.first, last].each do |edge|
657
+ raise RangeError, 'Range exceeded: ' + sub_range.to_s unless range.include?(edge)
658
+ end
659
+ {
660
+ 'origin_of_MSC' => sub_range.first,
661
+ 'origin_of_LSC' => @origin_of_LSC + @rule_table['T']['Rule'][sub_range.first-@origin_of_MSC][1],
662
+ 'rule_table' => sub_range.to_a.map {|year|
663
+ @rule_table['T']['Rule'][year-@origin_of_MSC][0]
664
+ }
665
+ }
666
+ end
667
+
668
+ # 朔閏表の有効範囲
669
+ #
670
+ # @return [Range] 有効範囲(西暦年)
671
+ #
672
+ def range
673
+ @origin_of_MSC...(@origin_of_MSC+@rule_table['T']['Rule'].length)
674
+ end
675
+
377
676
  private
378
677
 
379
678
  # new で指定された月日配当規則をプログラムで利用可能にします。
@@ -408,8 +707,8 @@ module When::CalendarTypes
408
707
 
409
708
  # オフセットの更新
410
709
  def _increment_offsets(offsets, subkey)
411
- offsets[1] += subkey.length # 月のオフセットを月数分進める
412
- offsets[0] += subkey.length * 29 + subkey.gsub(/[a-z]/,'').length # 日のオフセットを日数分進める
710
+ offsets[1] += subkey.length # 月のオフセットを月数分進める
711
+ offsets[0] += _year_length(subkey) # 日のオフセットを日数分進める
413
712
  end
414
713
 
415
714
  # 年初の通日によるセットアップ
@@ -453,12 +752,48 @@ module When::CalendarTypes
453
752
  return rule['Rule'][year][0]
454
753
  end
455
754
 
755
+ # 朔閏パターン -> 日数/年
756
+ #
757
+ # @param [String] key 朔閏パターン
758
+ #
759
+ # @return [Integer] 日数/年
760
+ #
761
+ def _year_length(key)
762
+ key.length * 29 + key.gsub(/[a-z]/,'').length
763
+ end
764
+
765
+ # 朔閏パターン -> 日数/年
766
+ #
767
+ # @param [String] key 朔閏パターン
768
+ # @param [Integer] m 月番号(0始まり)
769
+ #
770
+ # @return [Integer] 日数/月
771
+ #
772
+ def _month_length(key, m)
773
+ key[m,1] =~ /[a-z]/ ? 29 : 30
774
+ end
775
+
776
+ # 朔閏パターン -> 月のID
777
+ #
778
+ # @param [String] key 朔閏パターン
779
+ # @param [Integer] m 月番号(0始まり)
780
+ #
781
+ # @return [Integer] 月のID
782
+ #
783
+ def _month_id(key, m)
784
+ trunk = key.upcase[m]
785
+ branch = trunk == key.upcase[m-1] ? 1 : 0
786
+ trunk = trunk.ord if trunk.kind_of?(String)
787
+ trunk -= 64
788
+ branch == 0 ? trunk : When::Coordinates::Pair.new(trunk, branch)
789
+ end
790
+
456
791
  # オブジェクトの正規化
457
792
  #
458
793
  # @note インスタンス変数 @note は to_a でデフォルトとして用いる暦注
459
794
  #
460
795
  def _normalize(args=[], options={})
461
- @note ||= When.CalendarNote('ChineseNotes') # See when.rb
796
+ @note ||= When.CalendarNote('Chinese') # See when.rb
462
797
  super
463
798
  end
464
799
  end
@@ -484,6 +819,58 @@ module When::CalendarTypes
484
819
  end
485
820
  end
486
821
 
822
+ # 表引きにより実現する太陽暦(閏月なし, 5,6,27~34日の月に対応)
823
+ #
824
+ # Solar calendar which uses year / month /day table
825
+ #
826
+ class PatternTableBasedSolar < PatternTableBasedLuniSolar
827
+
828
+ private
829
+
830
+ # 朔閏パターン -> 日数/年
831
+ #
832
+ # @param [String] key 朔閏パターン
833
+ #
834
+ # @return [Integer] 日数/年
835
+ #
836
+ def _year_length(key)
837
+ length = 0
838
+ key.length.times do |m|
839
+ length += _month_length(key, m)
840
+ end
841
+ length
842
+ end
843
+
844
+ # 朔閏パターン -> 日数/年
845
+ #
846
+ # @param [String] key 朔閏パターン
847
+ # @param [Integer] m 月番号(0始まり)
848
+ #
849
+ # @return [Integer] 日数/月
850
+ #
851
+ def _month_length(key, m)
852
+ trunk = key.upcase[m]
853
+ trunk = trunk.ord if trunk.kind_of?(String)
854
+ trunk -= 48
855
+ case trunk
856
+ when 5, 6 ; trunk
857
+ when 7..9 ; trunk + 20
858
+ else ; trunk + 30
859
+ end
860
+ end
861
+
862
+ # 朔閏パターン -> 月のID
863
+ #
864
+ # @param [String] key 朔閏パターン
865
+ # @param [Integer] m 月番号(0始まり)
866
+ #
867
+ # @return [Integer] 月のID
868
+ #
869
+ def _month_id(key, m)
870
+ m + 1
871
+ end
872
+ end
873
+
487
874
  # 年の配当パターンが限定されている暦
488
875
  #
489
876
  # Calendar which has some fixed arrangement rules of year pattern
@@ -788,8 +1175,8 @@ module When::CalendarTypes
788
1175
  private
789
1176
 
790
1177
  # オブジェクトの正規化
791
- # @cycle_offset = 位相のオフセット / 1か月分の角度
792
- # @formula = 位相の計算に用いる太陽の Formula
1178
+ # cycle_offset = 位相のオフセット / 1か月分の角度
1179
+ # formula = 位相の計算に用いる太陽の Formula
793
1180
  #
794
1181
  def _normalize(args=[], options={})
795
1182
  @cycle_offset ||= -1.5
@@ -804,6 +1191,8 @@ module When::CalendarTypes
804
1191
  #
805
1192
  class EphemerisBasedLunar < EphemerisBased
806
1193
 
1194
+ include Lunar
1195
+
807
1196
  #protected
808
1197
 
809
1198
  # 月初の通日
@@ -819,13 +1208,13 @@ module When::CalendarTypes
819
1208
  private
820
1209
 
821
1210
  # オブジェクトの正規化
822
- # @cycle_offset = Goldstein Number に対する暦元の補正
1211
+ # cycle_offset = Goldstein Number に対する暦元の補正
823
1212
  #
824
1213
  def _normalize(args=[], options={})
825
1214
  @cycle_offset ||= 1671 * 12 + 4
826
1215
  super
827
1216
  end
828
- end
1217
+ end
829
1218
 
830
1219
  # 月日の配当が太陽および月の位置によって決定される太陰太陽暦
831
1220
  #
@@ -833,6 +1222,8 @@ module When::CalendarTypes
833
1222
  #
834
1223
  class EphemerisBasedLuniSolar < EphemerisBasedSolar
835
1224
 
1225
+ include Lunar
1226
+
836
1227
  # 計算方法
837
1228
  # @return [Array<When::Ephemeris::Formula>]
838
1229
  attr_reader :formula
@@ -847,7 +1238,7 @@ module When::CalendarTypes
847
1238
  #
848
1239
  # @return [Integer] 通日
849
1240
  #
850
- def _coordinates_to_number(yy, mm=0, dd=0)
1241
+ def _coordinates_to_number(yy, mm, dd)
851
1242
  _new_month(_new_year_month(+yy) + mm) + dd
852
1243
  end
853
1244
 
@@ -931,9 +1322,9 @@ module When::CalendarTypes
931
1322
 
932
1323
  # オブジェクトの正規化
933
1324
  #
934
- # @cycle_offset = 雨水の場合 -1
935
- # @formula = 位相の計算に用いる太陽と月の Formula
936
- # @notes = to_a でデフォルトとして用いる暦注
1325
+ # cycle_offset = 雨水の場合 -1
1326
+ # formula = 位相の計算に用いる太陽と月の Formula
1327
+ # notes = to_a でデフォルトとして用いる暦注
937
1328
  #
938
1329
  def _normalize(args=[], options={})
939
1330
  @formula ||= ['Formula?formula=12S', 'Formula?formula=1L']
@@ -1095,7 +1486,7 @@ module When::CalendarTypes
1095
1486
  #
1096
1487
  # @note 属性 @event によって境界を計算する (see {When::Ephemeris::Formula#day_event})
1097
1488
  #
1098
- def border(date=[], clock=When.utc)
1489
+ def border(date=[], clock=When::UTC)
1099
1490
  return @border unless date[0] && clock.formula
1100
1491
 
1101
1492
  clock._encode(