when_exe 0.3.5 → 0.3.6

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.
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(