when_exe 0.3.6 → 0.3.7

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 (117) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +171 -0
  3. data/lib/when_exe.rb +78 -47
  4. data/lib/when_exe/basictypes.rb +752 -747
  5. data/lib/when_exe/calendarnote.rb +805 -801
  6. data/lib/when_exe/calendartypes.rb +1583 -1531
  7. data/lib/when_exe/coordinates.rb +16 -15
  8. data/lib/when_exe/core/duration.rb +114 -110
  9. data/lib/when_exe/core/extension.rb +504 -504
  10. data/lib/when_exe/ephemeris.rb +1917 -1913
  11. data/lib/when_exe/ephemeris/moon.rb +333 -333
  12. data/lib/when_exe/ephemeris/notes.rb +389 -387
  13. data/lib/when_exe/ephemeris/planets.rb +585 -585
  14. data/lib/when_exe/ephemeris/sun.rb +214 -214
  15. data/lib/when_exe/googlecalendar.rb +144 -140
  16. data/lib/when_exe/icalendar.rb +1636 -1636
  17. data/lib/when_exe/inspect.rb +46 -22
  18. data/lib/when_exe/locales/akt.rb +176 -176
  19. data/lib/when_exe/locales/encoding_conversion.rb +134 -126
  20. data/lib/when_exe/locales/iast.rb +90 -90
  21. data/lib/when_exe/locales/locale.rb +750 -746
  22. data/lib/when_exe/locales/transliteration_table.rb +62 -62
  23. data/lib/when_exe/mini_application.rb +307 -305
  24. data/lib/when_exe/parts/enumerator.rb +2 -2
  25. data/lib/when_exe/parts/geometric_complex.rb +397 -397
  26. data/lib/when_exe/parts/method_cash.rb +224 -224
  27. data/lib/when_exe/parts/resource.rb +1069 -1071
  28. data/lib/when_exe/parts/timezone.rb +240 -230
  29. data/lib/when_exe/region/armenian.rb +56 -56
  30. data/lib/when_exe/region/babylonian.rb +405 -0
  31. data/lib/when_exe/region/bahai.rb +146 -146
  32. data/lib/when_exe/region/balinese.rb +622 -622
  33. data/lib/when_exe/region/chinese.rb +95 -25
  34. data/lib/when_exe/region/chinese/calendars.rb +1016 -1016
  35. data/lib/when_exe/region/chinese/epochs.rb +1 -1
  36. data/lib/when_exe/region/chinese/twins.rb +803 -795
  37. data/lib/when_exe/region/christian.rb +824 -824
  38. data/lib/when_exe/region/coptic.rb +106 -87
  39. data/lib/when_exe/region/discordian.rb +225 -225
  40. data/lib/when_exe/region/far_east.rb +188 -188
  41. data/lib/when_exe/region/french.rb +56 -56
  42. data/lib/when_exe/region/geologicalage.rb +639 -639
  43. data/lib/when_exe/region/goddess.rb +58 -58
  44. data/lib/when_exe/region/indian.rb +1254 -1251
  45. data/lib/when_exe/region/iranian.rb +8 -8
  46. data/lib/when_exe/region/islamic.rb +3 -3
  47. data/lib/when_exe/region/japanese.rb +93 -99
  48. data/lib/when_exe/region/japanese/calendars.rb +396 -397
  49. data/lib/when_exe/region/japanese/epochs.rb +26 -26
  50. data/lib/when_exe/region/japanese/nihon_shoki.rb +71 -71
  51. data/lib/when_exe/region/japanese/notes.rb +1383 -1386
  52. data/lib/when_exe/region/japanese/residues.rb +1306 -1306
  53. data/lib/when_exe/region/japanese/twins.rb +225 -225
  54. data/lib/when_exe/region/japanese/weeks.rb +112 -0
  55. data/lib/when_exe/region/javanese.rb +230 -230
  56. data/lib/when_exe/region/jewish.rb +126 -126
  57. data/lib/when_exe/region/korean.rb +378 -378
  58. data/lib/when_exe/region/m17n.rb +114 -113
  59. data/lib/when_exe/region/martian.rb +258 -255
  60. data/lib/when_exe/region/mayan.rb +32 -32
  61. data/lib/when_exe/region/residue.rb +89 -89
  62. data/lib/when_exe/region/roman.rb +36 -24
  63. data/lib/when_exe/region/ryukyu.rb +97 -97
  64. data/lib/when_exe/region/shire.rb +240 -240
  65. data/lib/when_exe/region/soviet.rb +209 -0
  66. data/lib/when_exe/region/symmetry.rb +50 -50
  67. data/lib/when_exe/region/thai.rb +336 -335
  68. data/lib/when_exe/region/tibetan.rb +316 -315
  69. data/lib/when_exe/region/vietnamese.rb +440 -439
  70. data/lib/when_exe/region/weekdate.rb +80 -80
  71. data/lib/when_exe/region/world.rb +175 -175
  72. data/lib/when_exe/region/yerm.rb +14 -14
  73. data/lib/when_exe/region/zoroastrian.rb +203 -203
  74. data/lib/when_exe/timestandard.rb +707 -681
  75. data/lib/when_exe/tmduration.rb +338 -330
  76. data/lib/when_exe/tmobjects.rb +1346 -1325
  77. data/lib/when_exe/tmposition.rb +2115 -2072
  78. data/lib/when_exe/tmreference.rb +1693 -1669
  79. data/lib/when_exe/version.rb +1 -1
  80. data/link_to_online_documents +1 -1
  81. data/test/examples/JapanHolidaysRFC6350.ics +1 -1
  82. data/test/test.rb +67 -61
  83. data/test/test/basictypes.rb +409 -409
  84. data/test/test/calendarnote.rb +86 -69
  85. data/test/test/calendartypes.rb +97 -97
  86. data/test/test/coordinates.rb +396 -396
  87. data/test/test/ephemeris.rb +83 -74
  88. data/test/test/ephemeris/moon.rb +14 -14
  89. data/test/test/ephemeris/planets.rb +14 -14
  90. data/test/test/ephemeris/sun.rb +14 -14
  91. data/test/test/googlecalendar.rb +194 -176
  92. data/test/test/icalendar.rb +867 -858
  93. data/test/test/inspect.rb +117 -117
  94. data/test/test/parts.rb +487 -487
  95. data/test/test/region/balinese.rb +34 -0
  96. data/test/test/region/chinese.rb +218 -206
  97. data/test/test/region/christian.rb +245 -245
  98. data/test/test/region/coptic.rb +27 -27
  99. data/test/test/region/french.rb +33 -33
  100. data/test/test/region/geologicalage.rb +17 -17
  101. data/test/test/region/indian.rb +57 -57
  102. data/test/test/region/iran.rb +54 -54
  103. data/test/test/region/islamic.rb +18 -18
  104. data/test/test/region/japanese.rb +237 -219
  105. data/test/test/region/jewish.rb +61 -61
  106. data/test/test/region/m17n.rb +184 -184
  107. data/test/test/region/mayan.rb +195 -195
  108. data/test/test/region/residue.rb +147 -139
  109. data/test/test/region/thai.rb +116 -116
  110. data/test/test/region/tibetan.rb +30 -30
  111. data/test/test/region/vietnamese.rb +102 -102
  112. data/test/test/region/yerm.rb +146 -146
  113. data/test/test/timestandard.rb +81 -81
  114. data/test/test/tmobjects.rb +328 -328
  115. data/test/test/tmposition.rb +397 -284
  116. data/test/test/tmreference.rb +157 -157
  117. metadata +13 -10
@@ -1,824 +1,824 @@
1
- # -*- coding: utf-8 -*-
2
- =begin
3
- Copyright (C) 2011-2014 Takashi SUGA
4
-
5
- You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
- =end
7
-
8
- module When
9
-
10
- class BasicTypes::M17n
11
-
12
- Christian = [self, [
13
- "locale:[=en:, ja=ja:, alias]",
14
- "names:[Christian=]",
15
- "[Julian=en:Julian_calendar, ユリウス暦 ]",
16
- "[Gregorian=en:Gregorian_calendar, グレゴリオ暦 ]",
17
- "[RevisedJulian=en:Revised_Julian_calendar, 修正ユリウス暦]",
18
- "[Swedish=en:Swedish_calendar, スウェーデン暦]",
19
- "[Civil in the West=en:Civil_calendar, 西暦, *alias:Civil]"
20
- ]]
21
- end
22
-
23
- class TM::CalendarEra
24
- # Anno Mundi Era
25
- Byzantine = [self, [
26
- "locale:[=en:, ja=ja:, alias]",
27
- "period:[Byzantine=en:Byzantine_calendar, ビザンティン暦=ja:%%<世界創造紀元>]",
28
- ["[AM=en:Anno_Mundi, 世界創造紀元, alias:Anno_Mundi]6497.9.1",
29
- "Calendar Epoch", "989-09-01^Julian?border=[-1,9,1]&note=Roman", "1453=5-29"]
30
- ]]
31
- end
32
-
33
- module CalendarTypes
34
-
35
- #
36
- # Christian Base Calendar
37
- #
38
- class Christian < When::TM::Calendar
39
-
40
- # デフォルトの改暦日付(ユリウス通日)
41
- #
42
- # @private
43
- DefaultReformDate = 2299161 # 1582-10-15
44
-
45
- # @private
46
- #
47
- # ::Date オブジェクトに対応する暦法名
48
- # (require 'Date' されていることの保証は呼び出し側)
49
- #
50
- def self._default_start(date)
51
- case date.start
52
- when ::Date::JULIAN ; 'Julian'
53
- when ::Date::GREGORIAN ; 'Gregorian'
54
- else ; "Civil?reform_jdn=#{date.start}"
55
- end
56
- end
57
-
58
- # 年月日 -> 通日
59
- #
60
- # @see When::CalendarTypes::TableBased#_coordinates_to_number
61
- #
62
- def _coordinates_to_number(y,m,d)
63
- m = (+m + 10) % 12
64
- y = +y + 4716 - m / 10
65
- a = (1461*y.to_i ).div(4)
66
- b = ( 153*m.to_i + 2).div(5)
67
- return a + b + (+d) - 1401
68
- end
69
-
70
- # 通日 - > 年月日
71
- #
72
- # @see When::CalendarTypes::TableBased#_number_to_coordinates
73
- #
74
- def _number_to_coordinates(jdn)
75
- j = jdn.to_i + 1401
76
- y, t = (4*j + 3).divmod(1461)
77
- t = t.div(4)
78
- m, d = (5*t + 2).divmod(153)
79
- d = d.div(5)
80
- m = (m+2) % 12
81
- y = y - 4716 + (13-m) / 12
82
- return [y,m,d]
83
- end
84
-
85
- # 暦要素数
86
- #
87
- # @see When::CalendarTypes::TableBased#_length
88
- #
89
- def _length(date)
90
- yy, mm = date
91
- return super unless(mm)
92
- return ((yy % 4) == 0) ? 29 : 28 if (mm == 1)
93
- return (((((mm + 10) % 12) % 5) % 2) == 0) ? 31 : 30
94
- end
95
-
96
- # 復活祭の遅延日数
97
- #
98
- # @private
99
- def _easter_delay(year)
100
- 0
101
- end
102
-
103
- private
104
-
105
- def _normalize(args=[], options={})
106
- raise TypeError, "#{self.class} is abstract class" unless @label
107
- @note = When.CalendarNote(@note || 'Christian')
108
- super
109
- end
110
- end
111
-
112
- #
113
- # Julian Calendar
114
- #
115
- class Julian < Christian
116
-
117
- # 太陰方程式
118
- #
119
- # @param [Numeric] year 西暦の年数
120
- # @return [Integer] 0 (ユリウス暦では補正なし)
121
- #
122
- def _lunar_equation(year)
123
- 0
124
- end
125
-
126
- # @private
127
- #
128
- # 対応する ::Date の start 属性
129
- def _default_start
130
- ::Date::JULIAN
131
- end
132
-
133
- private
134
-
135
- def _normalize(args=[], options={})
136
- @label ||= 'Christian::Julian'
137
- super
138
- end
139
- end
140
-
141
- #
142
- # Swedish Calendar
143
- #
144
- class Swedish < Julian
145
-
146
- # デフォルトの改暦日付(ユリウス通日)
147
- #
148
- # @private
149
- DefaultReformDate = 2361390 # 1753-03-01
150
-
151
- # @private
152
- # Julian - 17000229 17120229
153
- SwedishCalendarRange = 2342042...2346425
154
-
155
- # @private
156
- ExtraDate = [1712,1,29]
157
-
158
- # @private
159
- Length = {
160
- [1700, nil] => 365,
161
- [1700, 1] => 28,
162
- [1712, nil] => 367,
163
- [1712, 1] => 30
164
- }
165
-
166
- # Ref: http://www.ortelius.de/kalender/east_en.php
167
- # @private
168
- EasterDelay = {
169
- 1741 => -7,
170
- 1742 => -35,
171
- 1744 => -7,
172
- 1745 => -7,
173
- 1747 => -28,
174
- 1748 => -7,
175
- 1750 => -28,
176
- 1751 => -7,
177
- 1752 => -7,
178
- 1802 => +7,
179
- 1805 => +7,
180
- 1818 => +7
181
- }
182
-
183
- # 年月日 -> 通日
184
- #
185
- # @see When::CalendarTypes::TableBased#_coordinates_to_number
186
- #
187
- def _coordinates_to_number(y,m,d)
188
- jdn = super
189
- return SwedishCalendarRange.last if [+y, m, d] == ExtraDate
190
- SwedishCalendarRange.include?(jdn-1) ? jdn-1 : jdn
191
- end
192
-
193
- # 通日 - > 年月日
194
- #
195
- # @see When::CalendarTypes::TableBased#_number_to_coordinates
196
- #
197
- def _number_to_coordinates(jdn)
198
- return ExtraDate.dup if jdn == SwedishCalendarRange.last
199
- super(SwedishCalendarRange.include?(jdn) ? jdn+1 : jdn)
200
- end
201
-
202
- # 暦要素数
203
- #
204
- # @see When::CalendarTypes::TableBased#_length
205
- #
206
- def _length(date)
207
- y, m = date
208
- Length[[+y,m]] || super
209
- end
210
-
211
- # 復活祭の遅延日数
212
- #
213
- # @private
214
- def _easter_delay(year)
215
- EasterDelay[year] || 0
216
- end
217
-
218
- private
219
-
220
- def _normalize(args=[], options={})
221
- @label ||= 'Christian::Swedish'
222
- super
223
- end
224
- end
225
-
226
- #
227
- # Variation of Christian Calendar
228
- #
229
- class ReformVariation < Christian
230
-
231
- # 年月日 -> 通日
232
- #
233
- # @see When::CalendarTypes::TableBased#_coordinates_to_number
234
- #
235
- def _coordinates_to_number(y,m,d)
236
- super - _diff_from_century(((m < 2) ? +y-1 : +y).to_i.div(100))
237
- end
238
-
239
- # 通日 - > 年月日
240
- #
241
- # @see When::CalendarTypes::TableBased#_number_to_coordinates
242
- #
243
- def _number_to_coordinates(jdn)
244
- super(jdn + _diff_from_century(_century_from_jdn(jdn)))
245
- end
246
-
247
- # 暦要素数
248
- #
249
- # @see When::CalendarTypes::TableBased#_length
250
- #
251
- def _length(date)
252
- yy, mm = date
253
- return super unless mm == 1 # 2月でなければユリウス暦と同じ
254
- cc, yy = yy.divmod(100)
255
- return super unless yy == 0 # 100で割り切れない年はユリウス暦と同じ
256
- 29 - (_diff_from_century(cc) - _diff_from_century(cc-1))
257
- end
258
-
259
- # 太陰方程式
260
- #
261
- # @param [Numeric] year 西暦の年数
262
- # @return [Integer] 19年7閏のペースに対する満月の日付の補正量
263
- # @note 太陽暦日の補正も、本メソッドで行う
264
- #
265
- def _lunar_equation(year)
266
- h = +year.div(100)
267
- (8*(h+11)).div(25) - (_diff_from_century(h) + 5)
268
- end
269
- end
270
-
271
- #
272
- # Gregorian Calendar
273
- #
274
- class Gregorian < ReformVariation
275
-
276
- # 百年代 - > ユリウス暦とグレゴリオ暦の差
277
- #
278
- # @param [Integer] century 百年代
279
- #
280
- # @return [Integer] ユリウス暦とグレゴリオ暦の差
281
- #
282
- def _diff_from_century(century)
283
- (3*(century-3)).div(4)+1
284
- end
285
-
286
- # 通日 - > 百年代
287
- #
288
- # @param [Integer] jdn 通日
289
- #
290
- # @return [Integer] 百年代
291
- #
292
- def _century_from_jdn(jdn)
293
- (4 * jdn - 6884477).div(146097)
294
- end
295
-
296
- private
297
-
298
- def _normalize(args=[], options={})
299
- @label ||= 'Christian::Gregorian'
300
- super
301
- end
302
- end
303
-
304
- #
305
- # Revised Julian Calendar
306
- #
307
- class RevisedJulian < ReformVariation
308
-
309
- # デフォルトの改暦日付(ユリウス通日)
310
- #
311
- # @private
312
- DefaultReformDate = 2423707 # 1923-10-14
313
-
314
- # 百年代 - > ユリウス暦と修正ユリウス暦の差
315
- #
316
- # @param [Integer] century 百年代
317
- #
318
- # @return [Integer] ユリウス暦と修正ユリウス暦の差
319
- #
320
- def _diff_from_century(century)
321
- (7*(century-1)).div(9)-1
322
- end
323
-
324
- # 通日 - > 百年代
325
- #
326
- # @param [Integer] jdn 通日
327
- #
328
- # @return [Integer] 百年代
329
- #
330
- def _century_from_jdn(jdn)
331
- (9 * jdn - 15490078).div(328718)
332
- end
333
-
334
- private
335
-
336
- def _normalize(args=[], options={})
337
- @label ||= 'Christian::RevisedJulian'
338
- # @diff ||= [-2, -1, -1, 0, 1, 2, 2, 3, 4, 5] # 1~10世紀の各世紀のユリウス暦と差の日数
339
- super
340
- end
341
- end
342
-
343
- #
344
- # Civil Calendar
345
- #
346
- class Civil < Gregorian
347
-
348
- #
349
- # 改暦日付
350
- #
351
- # @return [Integer]
352
- #
353
- attr_reader :reform_jdn
354
-
355
- # @private
356
- #
357
- # 対応する ::Date の start 属性
358
- alias :_default_start :reform_jdn
359
-
360
- #
361
- # 年初の最初の定義の年
362
- #
363
- # @return [Integer] 年初の最初の定義の年
364
- # @return nil
365
- #
366
- def first_year_of_border
367
- return nil unless @border.kind_of?(When::CalendarTypes::MultiBorder)
368
- year = @border.borders[-1][:key]
369
- year.kind_of?(Integer) ? year : nil
370
- end
371
-
372
- # 年月日 -> 通日
373
- #
374
- # @see When::CalendarTypes::TableBased#_coordinates_to_number
375
- #
376
- def _coordinates_to_number(y,m,d)
377
- skip, limit = @the_length[[y,m]]
378
- d += skip if skip && d >= limit
379
- jdn = @new._coordinates_to_number(y,m,d)
380
- jdn >= @reform_jdn ? jdn : @old._coordinates_to_number(y + @origin_of_MSC - @old.origin_of_MSC, m, d)
381
- end
382
-
383
- # 通日 - > 年月日
384
- #
385
- # @see When::CalendarTypes::TableBased#_number_to_coordinates
386
- #
387
- def _number_to_coordinates(jdn)
388
- if jdn >= @reform_jdn
389
- date = @new._number_to_coordinates(jdn)
390
- else
391
- date = @old._number_to_coordinates(jdn)
392
- date[0] -= @origin_of_MSC - @old.origin_of_MSC
393
- end
394
- skip, limit = @the_length[date[0..-2]]
395
- date[2] -= skip if skip && date[2] >= limit
396
- date
397
- end
398
-
399
- # 暦要素数
400
- #
401
- # @see When::CalendarTypes::TableBased#_length
402
- #
403
- def _length(date)
404
- return @the_length[date][2] if @the_length[date]
405
- yy, mm = date
406
- (yy > @reform_date[0]) ||
407
- (yy == @reform_date[0] && (!mm || mm >= @reform_date[1])) ?
408
- @new._length(date) :
409
- @old._length([yy + @origin_of_MSC - @old.origin_of_MSC, mm])
410
- end
411
-
412
- # 太陰方程式
413
- #
414
- # @param [Numeric] year 西暦の年数
415
- # @return [Integer] 19年7閏のペースに対する満月の日付の補正量
416
- # @note 太陽暦日の補正も、本メソッドで行う
417
- #
418
- def _lunar_equation(year)
419
- year >= @the_easter ? @new._lunar_equation(year) : @old._lunar_equation(year)
420
- end
421
-
422
- # 復活祭の遅延日数
423
- #
424
- # @private
425
- def _easter_delay(year)
426
- @old._easter_delay(year)
427
- end
428
-
429
- private
430
-
431
- # オブジェクトの正規化
432
- #
433
- # @old = 改暦前の暦法(デフォルトはユリウス暦)
434
- # @new = 改暦後の暦法(デフォルトはグレゴリオ暦)
435
- # @reform_date = 改暦日付(月日は 1 オリジンで指定し、0 オリジンに直して保持)
436
- # @reform_jdn = 改暦日付のユリウス通日
437
- # @reform = reform_date か reform_jdn を内容で判別し、どちらかに反映する
438
- # @the_easter = 新暦法の復活祭計算の適用を始める年
439
- # @the_length = 通常と異なる日付となる年月の情報({[年,月]=>[スキップした日数, スキップし始める日, 月の日数]})
440
- #
441
- def _normalize(args=[], options={})
442
- @label ||= 'Christian::Civil'
443
-
444
- # 前後の暦法
445
- @old = When.Calendar(@old || 'Julian')
446
- @new = When.Calendar(@new || 'Gregorian')
447
- @indices ||= @old.indices
448
-
449
- # 改暦日付 (0 オリジン)
450
- @reform = When::Coordinates::Pair._en_pair_date_time(@reform) if @reform.kind_of?(String)
451
- case @reform.length
452
- when 0 ;
453
- when 1 ; @reform_jdn = @reform[0]
454
- else ; @reform_date = @reform
455
- end if @reform.kind_of?(Array)
456
-
457
- if @reform_date
458
- @reform_date = When::Coordinates::Pair._en_pair_date_time(@reform_date) if @reform_date.kind_of?(String)
459
- @reform_date = @reform_date.map {|c| c.to_i}
460
- (1..2).each {|i| @reform_date[i] = @reform_date[i] ? @reform_date[i] - 1 : 0 }
461
- @reform_jdn = @new._coordinates_to_number(*@reform_date)
462
- else
463
- @reform_jdn ||= [@old.class::DefaultReformDate, @new.class::DefaultReformDate].max
464
- @reform_jdn = @reform_jdn.to_i
465
- @reform_date = @new._number_to_coordinates(@reform_jdn)
466
- end
467
- last_date = @old._number_to_coordinates(@reform_jdn-1)
468
-
469
- # 復活祭との前後関係
470
- @the_easter = @reform_jdn > When.CalendarNote('Christian').easter(@reform_date[0], @new) ? @reform_date[0]+1 : @reform_date[0]
471
-
472
- # 月の日数
473
- this_month = @reform_date[0..1]
474
- new_length = @new._length(this_month)
475
- @the_length = {}
476
- if @reform_date[1] == last_date[1] # 同一月内に閉じた改暦
477
- skipped_length = @reform_date[2] - last_date[2] - 1
478
- @the_length[this_month] = [skipped_length, last_date[2]+1, new_length-skipped_length]
479
- else
480
- last_month = [(@reform_date[1] > last_date[1] ? @reform_date[0] : @reform_date[0]-1), last_date[1]]
481
- @the_length[this_month] = [@reform_date[2], 0, new_length - @reform_date[2]]
482
- @the_length[last_month] = [false, false, last_date[2]+1]
483
- end
484
-
485
- super
486
- end
487
-
488
- #
489
- # 整数のindex化
490
- #
491
- def _to_index(date)
492
- digit = date[-1] - @base[date.length-1]
493
- skip, limit = @the_length[date[0..-2]]
494
- skip && digit >= limit ? digit-skip : digit
495
- end
496
-
497
- #
498
- # indexの整数化
499
- #
500
- def _from_index(date)
501
- digit = date[-1]
502
- skip, limit = @the_length[date[0..-2]]
503
- (skip && digit >= limit ? digit+skip : digit)+@base[date.length-1]
504
- end
505
- end
506
-
507
- #
508
- # 日時要素の境界 - 復活祭
509
- #
510
- class Easter < Border
511
-
512
- # 境界の取得
513
- #
514
- # @param [Array<Numeric>] date 境界を計算する年
515
- # @param [When::TM::ReferenceSystem] frame 使用する暦法
516
- #
517
- # @return [Array<Numeric>] その年の境界
518
- #
519
- def border(date=[], frame=When::Gregorian)
520
- frame._encode(frame._number_to_coordinates(frame.note.easter(date[0], frame)), false)
521
- end
522
-
523
- private
524
-
525
- # 要素の正規化
526
- def _normalize(args=[], options={})
527
- @border = [0,0,0]
528
- end
529
- end
530
- end
531
-
532
- #
533
- # キリスト教の暦注(クリスマスと復活祭)
534
- #
535
- class CalendarNote::Christian < CalendarNote
536
-
537
- Notes = [When::BasicTypes::M17n, [
538
- "locale:[=en:, ja=ja:, alias]",
539
- "names:[Christian]",
540
-
541
- # 年の暦注 ----------------------------
542
- [When::BasicTypes::M17n,
543
- "names:[year]"
544
- ],
545
-
546
- # 月の暦注 ----------------------------
547
- [When::BasicTypes::M17n,
548
- "names:[month]",
549
- [When::BasicTypes::M17n,
550
- "names:[Month]"
551
- ]
552
- ],
553
-
554
- # 日の暦注 ----------------------------
555
- [When::BasicTypes::M17n,
556
- "names:[day]",
557
- [When::BasicTypes::M17n, "names:[Week, 七曜]" ],
558
- [When::BasicTypes::M17n, "names:[Easter, 復活祭]" ],
559
- [When::BasicTypes::M17n, "names:[Christmas, クリスマス]"],
560
- [When::BasicTypes::M17n, "names:[Fixed_feast=, 固定祝日=]" ],
561
- [When::BasicTypes::M17n, "names:[Moveable_feast, 移動祝日]" ]
562
- ]
563
- ]]
564
-
565
- # 固定祝日
566
- Fixed_feasts = {
567
- [ 1, 6] => "Epiphany",
568
- [ 3, 1] => "St.David's Day",
569
- [ 3, 17] => "St.Patrick's Day",
570
- [ 3, 25] => "Annunciation-Lady Day",
571
- [ 4, 23] => "St.George's Day",
572
- [ 6, 24] => "Midsummer Day",
573
- [ 9, 14] => "Holy Cross Day",
574
- [ 9, 29] => "Michaelmas Day",
575
- [11, 30] => "St.Andrew's Day",
576
- [12, 13] => "St.Lucia's Day",
577
- [12, 21] => "St.Thomas's Day",
578
- # [12, 25] => "Christmas Day"
579
- }
580
-
581
- # 移動祝日 (日付と曜日による)
582
- moveable_feasts = {}
583
- [[[ 9, 15, 2], "III Quatember"],
584
- [[11, 27, 6], "Advent Sunday"],
585
- [[12, 14, 2], "IV Quatember" ]].each do |pair|
586
- date, name = pair
587
- 7.times do
588
- moveable_feasts[date.dup] = name
589
- date[1] += 1
590
- if date[1] > 30
591
- date[0] += 1
592
- date[1] = 1
593
- end
594
- end
595
- end
596
-
597
- # 移動祝日
598
- Moveable_feasts = {
599
- # 復活祭からの日数による
600
- -63 => "Septuagesima Sunday",
601
- -56 => "Sexagesima Sunday",
602
- -49 => "Quinquagesima Sunday",
603
- -46 => "Ash Wednesday",
604
- -42 => "Quadragesima Sunday",
605
- -40 => "I Quatember",
606
- -35 => "Reminizer Sunday",
607
- -28 => "Oculi Sunday",
608
- -21 => "Laetare Sunday",
609
- -14 => "Judica Sunday",
610
- -7 => "Palmarum",
611
- -2 => "Good Friday",
612
- # 0 => "Easter Day",
613
- 7 => "Low Sunday",
614
- 35 => "Rogation Sunday",
615
- 39 => "Ascension Day",
616
- 49 => "Whitsunday",
617
- 53 => "II Quatember",
618
- 56 => "Trinity Sunday",
619
- 60 => "Corpus Christi",
620
- }.update(moveable_feasts)
621
-
622
- #
623
- # 暦法によってイベントの動作を変えるか否か
624
- #
625
- CalendarDepend = true
626
-
627
- # 週日補正フラグ
628
- # @return [Integer]
629
- attr_reader :w
630
-
631
- # 最も遅い満月の3月0日からの日数
632
- # @return [Integer]
633
- attr_reader :d
634
-
635
- # クリスマスの3月0日からの日数
636
- # @return [Integer]
637
- attr_reader :x
638
-
639
- # 平年数
640
- # @return [Integer]
641
- attr_reader :n
642
-
643
- # 置閏周期
644
- # @return [Integer]
645
- attr_reader :s
646
-
647
- # 月の位相の補正
648
- # @return [Integer]
649
- attr_reader :c
650
-
651
- # ガード
652
- # @return [Integer]
653
- attr_reader :g
654
-
655
- # ベース
656
- # @return [Integer]
657
- attr_reader :b
658
-
659
- # 満月補正フラグ
660
- # @return [Integer]
661
- attr_reader :f
662
-
663
- # 七曜
664
- #
665
- # @param [When::TM::TemporalPosition] date
666
- # @param [When::TM::CalDate] base (not used)
667
- #
668
- # @return [When::Coordinates::Residue] 七曜
669
- #
670
- def week(date, base=nil)
671
- When.Residue('Week')[date.to_i % 7]
672
- end
673
-
674
- # クリスマス
675
- #
676
- # @param [Numeric] date 西暦の年数
677
- # @param [When::TM::TemporalPosition] date
678
- # @param [When::TM::ReferenceSystem] frame 使用する暦法(デフォルトは When::Gregorian)
679
- #
680
- # @return [Integer] クリスマスのユリウス通日(dateが西暦の年数の場合)
681
- # @return [When::TM::CalDate] クリスマスのWhen::TM::CalDate(yearがWhen::TM::TemporalPositionの場合)
682
- #
683
- def christmas(date, frame=nil)
684
- _event(date, 'christmas', frame) do |year, frame|
685
- @x - 1 + frame._coordinates_to_number(year, 2, 0)
686
- end
687
- end
688
-
689
- # 復活祭
690
- #
691
- # @param [Numeric] date 西暦の年数
692
- # @param [When::TM::TemporalPosition] date
693
- # @param [When::TM::ReferenceSystem] frame 使用する暦法(デフォルトは When::Gregorian)
694
- #
695
- # @return [Integer] 復活祭のユリウス通日(dateが西暦の年数の場合)
696
- # @return [When::TM::CalDate] 復活祭のWhen::TM::CalDate(yearがWhen::TM::TemporalPositionの場合)
697
- #
698
- def easter(date, frame=nil)
699
- _event(date, 'easter', frame) do |year, frame|
700
- golden = (year+@b) % @s + 1
701
- m = (frame._lunar_equation(year) + 11*golden + @c) % 30
702
- if @f == 0
703
- m += 1 if m==0 || m==1 && golden>=@n
704
- else
705
- m += (golden-1) / @f
706
- m -= 30 if m>=@n
707
- end
708
- result = frame._coordinates_to_number(year, 2, 0) + @d - 1 - m
709
- result += @g - (result-@w) % 7 if @w<7
710
- result + frame._easter_delay(year)
711
- end
712
- end
713
-
714
- # イベントの標準的な間隔を返す
715
- # @private
716
- def _delta(parameter=nil)
717
- return When::P1Y
718
- end
719
-
720
- # @private
721
- alias :christmas_delta :_delta
722
-
723
- # @private
724
- alias :easter_delta :_delta
725
-
726
- # 固定祝日
727
- #
728
- # @param [When::TM::TemporalPosition] date
729
- # @param [When::TM::ReferenceSystem] frame 使用する暦法(デフォルトは When::Gregorian)
730
- #
731
- # @return [String] 祝日の名称
732
- # @return [nil] 祝日に該当しない
733
- #
734
- def fixed_feast(date, frame=nil)
735
- date = When.Calendar(frame||'Gregorian') ^ date unless date.frame.kind_of?(When::CalendarTypes::Christian)
736
- Fixed_feasts[date.cal_date[-2..-1]]
737
- end
738
-
739
- # 移動祝日
740
- #
741
- # @param [When::TM::TemporalPosition] date
742
- # @param [When::TM::ReferenceSystem] frame 使用する暦法(デフォルトは When::Gregorian)
743
- #
744
- # @return [String] 祝日の名称
745
- # @return [nil] 祝日に該当しない
746
- #
747
- def moveable_feast(date, frame=nil)
748
- result = Moveable_feasts[date.to_i - easter(date, frame).to_i]
749
- return result if result
750
- date = When.Calendar(frame||'Gregorian') ^ date unless date.frame.kind_of?(When::CalendarTypes::Christian)
751
- Moveable_feasts[date.cal_date[-2..-1] + [date.to_i % 7]]
752
- end
753
-
754
- private
755
-
756
- # オブジェクトの正規化
757
- # w - 週日補正フラグ(デフォルト 6)
758
- # d - 最も遅い満月 (デフォルト 3月0日から 50日)
759
- # x - クリスマス (デフォルト 3月0日から300日)
760
- # n - 平年数 (デフォルト 12)
761
- # s - 置閏周期 (デフォルト 19)
762
- # c - 月の位相の補正(デフォルト 3)
763
- # g - ガード (デフォルト 7)
764
- # b - ベース (デフォルト 0)
765
- # f - 満月補正フラグ(デフォルト 0)
766
- def _normalize(args=[], options={})
767
- w, d, x, n, s, c, g, b, f = args
768
- @w = (w || @w || 6).to_i
769
- @d = (d || @d || 50).to_i
770
- @x = (x || @x || 300).to_i
771
- @n = (n || @n || 12).to_i
772
- @s = (s || @s || 19).to_i
773
- @c = (c || @c || 3).to_i
774
- @g = (g || @g || 7).to_i
775
- @b = (b || @b || 0).to_i
776
- @f = (f || @f || 0).to_i
777
- @event = 'easter'
778
- @prime ||= [['Month'], ['Week']]
779
- super
780
- end
781
-
782
- #
783
- # 任意の暦をグレゴリオorユリウス暦日に変換
784
- #
785
- def _to_date_for_note(date)
786
- return When.Calendar(When::CalendarTypes::Christian._default_start(date)) ^ date if ::Object.const_defined?(:Date) && date.kind_of?(::Date)
787
- return When::Gregorian ^ date if date.kind_of?(::Time)
788
- return date if date.frame.kind_of?(When::CalendarTypes::Christian)
789
- When.Calendar(date.frame.iri =~ /Coptic/ || date.to_i < 2299161 ? 'Julian' : 'Gregorian') ^ date
790
- end
791
-
792
- # 当該年のイベントの日付
793
- # date : 西暦の年数 or When::TM::(Temporal)Position
794
- # event : イベント名 (String)
795
- # frame : 暦法(デフォルトは When:Gregorian)
796
- #
797
- # @return [Integer] イベントのユリウス通日(dateが西暦の年数の場合)
798
- # @return [When::TM::CalDate] イベントのWhen::TM::CalDate(yearがWhen::TM::(Temporal)Positionの場合)
799
- #
800
- def _event(date, event, frame=nil)
801
- case date
802
- when Numeric
803
- year = date * 1
804
- when When::TimeValue
805
- options = date._attr
806
- options[:precision] = When::DAY
807
- options[:events] = [event]
808
- if frame
809
- frame = When.Calendar(frame)
810
- date = frame.jul_trans(date, options)
811
- else
812
- frame = date.frame
813
- end
814
- year = date.most_significant_coordinate * 1
815
- else
816
- raise TypeError, "Irregal date type: #{date.class}"
817
- end
818
- frame ||= When::Gregorian
819
- result = yield(year, frame)
820
- return result if date.kind_of?(Numeric)
821
- return frame.jul_trans(result, options)
822
- end
823
- end
824
- end
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2011-2014 Takashi SUGA
4
+
5
+ You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
+ =end
7
+
8
+ module When
9
+
10
+ class BasicTypes::M17n
11
+
12
+ Christian = [self, [
13
+ "locale:[=en:, ja=ja:, alias]",
14
+ "names:[Christian=]",
15
+ "[Julian=en:Julian_calendar, ユリウス暦 ]",
16
+ "[Gregorian=en:Gregorian_calendar, グレゴリオ暦 ]",
17
+ "[RevisedJulian=en:Revised_Julian_calendar, 修正ユリウス暦]",
18
+ "[Swedish=en:Swedish_calendar, スウェーデン暦]",
19
+ "[Civil in the West=en:Civil_calendar, 西暦, *alias:Civil]"
20
+ ]]
21
+ end
22
+
23
+ class TM::CalendarEra
24
+ # Anno Mundi Era
25
+ Byzantine = [self, [
26
+ "locale:[=en:, ja=ja:, alias]",
27
+ "period:[Byzantine=en:Byzantine_calendar, ビザンティン暦=ja:%%<世界創造紀元>]",
28
+ ["[AM=en:Anno_Mundi, 世界創造紀元, alias:Anno_Mundi]6497*9.1",
29
+ '@CE', "989*09-01^Julian?border=0*9-1&note=Roman", "1453-5-29"]
30
+ ]]
31
+ end
32
+
33
+ module CalendarTypes
34
+
35
+ #
36
+ # Christian Base Calendar
37
+ #
38
+ class Christian < When::TM::Calendar
39
+
40
+ # デフォルトの改暦日付(ユリウス通日)
41
+ #
42
+ # @private
43
+ DefaultReformDate = 2299161 # 1582-10-15
44
+
45
+ # @private
46
+ #
47
+ # ::Date オブジェクトに対応する暦法名
48
+ # (require 'Date' されていることの保証は呼び出し側)
49
+ #
50
+ def self._default_start(date)
51
+ case date.start
52
+ when ::Date::JULIAN ; 'Julian'
53
+ when ::Date::GREGORIAN ; 'Gregorian'
54
+ else ; "Civil?reform_jdn=#{date.start}"
55
+ end
56
+ end
57
+
58
+ # 年月日 -> 通日
59
+ #
60
+ # @see When::CalendarTypes::TableBased#_coordinates_to_number
61
+ #
62
+ def _coordinates_to_number(y,m,d)
63
+ m = (+m + 10) % 12
64
+ y = +y + 4716 - m / 10
65
+ a = (1461*y.to_i ).div(4)
66
+ b = ( 153*m.to_i + 2).div(5)
67
+ return a + b + (+d) - 1401
68
+ end
69
+
70
+ # 通日 - > 年月日
71
+ #
72
+ # @see When::CalendarTypes::TableBased#_number_to_coordinates
73
+ #
74
+ def _number_to_coordinates(jdn)
75
+ j = jdn.to_i + 1401
76
+ y, t = (4*j + 3).divmod(1461)
77
+ t = t.div(4)
78
+ m, d = (5*t + 2).divmod(153)
79
+ d = d.div(5)
80
+ m = (m+2) % 12
81
+ y = y - 4716 + (13-m) / 12
82
+ return [y,m,d]
83
+ end
84
+
85
+ # 暦要素数
86
+ #
87
+ # @see When::CalendarTypes::TableBased#_length
88
+ #
89
+ def _length(date)
90
+ yy, mm = date
91
+ return super unless(mm)
92
+ return ((yy % 4) == 0) ? 29 : 28 if (mm == 1)
93
+ return (((((mm + 10) % 12) % 5) % 2) == 0) ? 31 : 30
94
+ end
95
+
96
+ # 復活祭の遅延日数
97
+ #
98
+ # @private
99
+ def _easter_delay(year)
100
+ 0
101
+ end
102
+
103
+ private
104
+
105
+ def _normalize(args=[], options={})
106
+ raise TypeError, "#{self.class} is abstract class" unless @label
107
+ @note = When.CalendarNote(@note || 'Christian')
108
+ super
109
+ end
110
+ end
111
+
112
+ #
113
+ # Julian Calendar
114
+ #
115
+ class Julian < Christian
116
+
117
+ # 太陰方程式
118
+ #
119
+ # @param [Numeric] year 西暦の年数
120
+ # @return [Integer] 0 (ユリウス暦では補正なし)
121
+ #
122
+ def _lunar_equation(year)
123
+ 0
124
+ end
125
+
126
+ # @private
127
+ #
128
+ # 対応する ::Date の start 属性
129
+ def _default_start
130
+ ::Date::JULIAN
131
+ end
132
+
133
+ private
134
+
135
+ def _normalize(args=[], options={})
136
+ @label ||= 'Christian::Julian'
137
+ super
138
+ end
139
+ end
140
+
141
+ #
142
+ # Swedish Calendar
143
+ #
144
+ class Swedish < Julian
145
+
146
+ # デフォルトの改暦日付(ユリウス通日)
147
+ #
148
+ # @private
149
+ DefaultReformDate = 2361390 # 1753-03-01
150
+
151
+ # @private
152
+ # Julian - 17000229 17120229
153
+ SwedishCalendarRange = 2342042...2346425
154
+
155
+ # @private
156
+ ExtraDate = [1712,1,29]
157
+
158
+ # @private
159
+ Length = {
160
+ [1700, nil] => 365,
161
+ [1700, 1] => 28,
162
+ [1712, nil] => 367,
163
+ [1712, 1] => 30
164
+ }
165
+
166
+ # Ref: http://www.ortelius.de/kalender/east_en.php
167
+ # @private
168
+ EasterDelay = {
169
+ 1741 => -7,
170
+ 1742 => -35,
171
+ 1744 => -7,
172
+ 1745 => -7,
173
+ 1747 => -28,
174
+ 1748 => -7,
175
+ 1750 => -28,
176
+ 1751 => -7,
177
+ 1752 => -7,
178
+ 1802 => +7,
179
+ 1805 => +7,
180
+ 1818 => +7
181
+ }
182
+
183
+ # 年月日 -> 通日
184
+ #
185
+ # @see When::CalendarTypes::TableBased#_coordinates_to_number
186
+ #
187
+ def _coordinates_to_number(y,m,d)
188
+ jdn = super
189
+ return SwedishCalendarRange.last if [+y, m, d] == ExtraDate
190
+ SwedishCalendarRange.include?(jdn-1) ? jdn-1 : jdn
191
+ end
192
+
193
+ # 通日 - > 年月日
194
+ #
195
+ # @see When::CalendarTypes::TableBased#_number_to_coordinates
196
+ #
197
+ def _number_to_coordinates(jdn)
198
+ return ExtraDate.dup if jdn == SwedishCalendarRange.last
199
+ super(SwedishCalendarRange.include?(jdn) ? jdn+1 : jdn)
200
+ end
201
+
202
+ # 暦要素数
203
+ #
204
+ # @see When::CalendarTypes::TableBased#_length
205
+ #
206
+ def _length(date)
207
+ y, m = date
208
+ Length[[+y,m]] || super
209
+ end
210
+
211
+ # 復活祭の遅延日数
212
+ #
213
+ # @private
214
+ def _easter_delay(year)
215
+ EasterDelay[year] || 0
216
+ end
217
+
218
+ private
219
+
220
+ def _normalize(args=[], options={})
221
+ @label ||= 'Christian::Swedish'
222
+ super
223
+ end
224
+ end
225
+
226
+ #
227
+ # Variation of Christian Calendar
228
+ #
229
+ class ReformVariation < Christian
230
+
231
+ # 年月日 -> 通日
232
+ #
233
+ # @see When::CalendarTypes::TableBased#_coordinates_to_number
234
+ #
235
+ def _coordinates_to_number(y,m,d)
236
+ super - _diff_from_century(((m < 2) ? +y-1 : +y).to_i.div(100))
237
+ end
238
+
239
+ # 通日 - > 年月日
240
+ #
241
+ # @see When::CalendarTypes::TableBased#_number_to_coordinates
242
+ #
243
+ def _number_to_coordinates(jdn)
244
+ super(jdn + _diff_from_century(_century_from_jdn(jdn)))
245
+ end
246
+
247
+ # 暦要素数
248
+ #
249
+ # @see When::CalendarTypes::TableBased#_length
250
+ #
251
+ def _length(date)
252
+ yy, mm = date
253
+ return super unless mm == 1 # 2月でなければユリウス暦と同じ
254
+ cc, yy = yy.divmod(100)
255
+ return super unless yy == 0 # 100で割り切れない年はユリウス暦と同じ
256
+ 29 - (_diff_from_century(cc) - _diff_from_century(cc-1))
257
+ end
258
+
259
+ # 太陰方程式
260
+ #
261
+ # @param [Numeric] year 西暦の年数
262
+ # @return [Integer] 19年7閏のペースに対する満月の日付の補正量
263
+ # @note 太陽暦日の補正も、本メソッドで行う
264
+ #
265
+ def _lunar_equation(year)
266
+ h = +year.div(100)
267
+ (8*(h+11)).div(25) - (_diff_from_century(h) + 5)
268
+ end
269
+ end
270
+
271
+ #
272
+ # Gregorian Calendar
273
+ #
274
+ class Gregorian < ReformVariation
275
+
276
+ # 百年代 - > ユリウス暦とグレゴリオ暦の差
277
+ #
278
+ # @param [Integer] century 百年代
279
+ #
280
+ # @return [Integer] ユリウス暦とグレゴリオ暦の差
281
+ #
282
+ def _diff_from_century(century)
283
+ (3*(century-3)).div(4)+1
284
+ end
285
+
286
+ # 通日 - > 百年代
287
+ #
288
+ # @param [Integer] jdn 通日
289
+ #
290
+ # @return [Integer] 百年代
291
+ #
292
+ def _century_from_jdn(jdn)
293
+ (4 * jdn - 6884477).div(146097)
294
+ end
295
+
296
+ private
297
+
298
+ def _normalize(args=[], options={})
299
+ @label ||= 'Christian::Gregorian'
300
+ super
301
+ end
302
+ end
303
+
304
+ #
305
+ # Revised Julian Calendar
306
+ #
307
+ class RevisedJulian < ReformVariation
308
+
309
+ # デフォルトの改暦日付(ユリウス通日)
310
+ #
311
+ # @private
312
+ DefaultReformDate = 2423707 # 1923-10-14
313
+
314
+ # 百年代 - > ユリウス暦と修正ユリウス暦の差
315
+ #
316
+ # @param [Integer] century 百年代
317
+ #
318
+ # @return [Integer] ユリウス暦と修正ユリウス暦の差
319
+ #
320
+ def _diff_from_century(century)
321
+ (7*(century-1)).div(9)-1
322
+ end
323
+
324
+ # 通日 - > 百年代
325
+ #
326
+ # @param [Integer] jdn 通日
327
+ #
328
+ # @return [Integer] 百年代
329
+ #
330
+ def _century_from_jdn(jdn)
331
+ (9 * jdn - 15490078).div(328718)
332
+ end
333
+
334
+ private
335
+
336
+ def _normalize(args=[], options={})
337
+ @label ||= 'Christian::RevisedJulian'
338
+ # @diff ||= [-2, -1, -1, 0, 1, 2, 2, 3, 4, 5] # 1~10世紀の各世紀のユリウス暦と差の日数
339
+ super
340
+ end
341
+ end
342
+
343
+ #
344
+ # Civil Calendar
345
+ #
346
+ class Civil < Gregorian
347
+
348
+ #
349
+ # 改暦日付
350
+ #
351
+ # @return [Integer]
352
+ #
353
+ attr_reader :reform_jdn
354
+
355
+ # @private
356
+ #
357
+ # 対応する ::Date の start 属性
358
+ alias :_default_start :reform_jdn
359
+
360
+ #
361
+ # 年初の最初の定義の年
362
+ #
363
+ # @return [Integer] 年初の最初の定義の年
364
+ # @return nil
365
+ #
366
+ def first_year_of_border
367
+ return nil unless @border.kind_of?(When::CalendarTypes::MultiBorder)
368
+ year = @border.borders[-1][:key]
369
+ year.kind_of?(Integer) ? year : nil
370
+ end
371
+
372
+ # 年月日 -> 通日
373
+ #
374
+ # @see When::CalendarTypes::TableBased#_coordinates_to_number
375
+ #
376
+ def _coordinates_to_number(y,m,d)
377
+ skip, limit = @the_length[[y,m]]
378
+ d += skip if skip && d >= limit
379
+ jdn = @new._coordinates_to_number(y,m,d)
380
+ jdn >= @reform_jdn ? jdn : @old._coordinates_to_number(y + @origin_of_MSC - @old.origin_of_MSC, m, d)
381
+ end
382
+
383
+ # 通日 - > 年月日
384
+ #
385
+ # @see When::CalendarTypes::TableBased#_number_to_coordinates
386
+ #
387
+ def _number_to_coordinates(jdn)
388
+ if jdn >= @reform_jdn
389
+ date = @new._number_to_coordinates(jdn)
390
+ else
391
+ date = @old._number_to_coordinates(jdn)
392
+ date[0] -= @origin_of_MSC - @old.origin_of_MSC
393
+ end
394
+ skip, limit = @the_length[date[0..-2]]
395
+ date[2] -= skip if skip && date[2] >= limit
396
+ date
397
+ end
398
+
399
+ # 暦要素数
400
+ #
401
+ # @see When::CalendarTypes::TableBased#_length
402
+ #
403
+ def _length(date)
404
+ return @the_length[date][2] if @the_length[date]
405
+ yy, mm = date
406
+ (yy > @reform_date[0]) ||
407
+ (yy == @reform_date[0] && (!mm || mm >= @reform_date[1])) ?
408
+ @new._length(date) :
409
+ @old._length([yy + @origin_of_MSC - @old.origin_of_MSC, mm])
410
+ end
411
+
412
+ # 太陰方程式
413
+ #
414
+ # @param [Numeric] year 西暦の年数
415
+ # @return [Integer] 19年7閏のペースに対する満月の日付の補正量
416
+ # @note 太陽暦日の補正も、本メソッドで行う
417
+ #
418
+ def _lunar_equation(year)
419
+ year >= @the_easter ? @new._lunar_equation(year) : @old._lunar_equation(year)
420
+ end
421
+
422
+ # 復活祭の遅延日数
423
+ #
424
+ # @private
425
+ def _easter_delay(year)
426
+ @old._easter_delay(year)
427
+ end
428
+
429
+ private
430
+
431
+ # オブジェクトの正規化
432
+ #
433
+ # @old = 改暦前の暦法(デフォルトはユリウス暦)
434
+ # @new = 改暦後の暦法(デフォルトはグレゴリオ暦)
435
+ # @reform_date = 改暦日付(月日は 1 オリジンで指定し、0 オリジンに直して保持)
436
+ # @reform_jdn = 改暦日付のユリウス通日
437
+ # @reform = reform_date か reform_jdn を内容で判別し、どちらかに反映する
438
+ # @the_easter = 新暦法の復活祭計算の適用を始める年
439
+ # @the_length = 通常と異なる日付となる年月の情報({[年,月]=>[スキップした日数, スキップし始める日, 月の日数]})
440
+ #
441
+ def _normalize(args=[], options={})
442
+ @label ||= 'Christian::Civil'
443
+
444
+ # 前後の暦法
445
+ @old = When.Calendar(@old || 'Julian')
446
+ @new = When.Calendar(@new || 'Gregorian')
447
+ @indices ||= @old.indices
448
+
449
+ # 改暦日付 (0 オリジン)
450
+ @reform = When::Coordinates::Pair._en_pair_date_time(@reform) if @reform.kind_of?(String)
451
+ case @reform.length
452
+ when 0 ;
453
+ when 1 ; @reform_jdn = @reform[0]
454
+ else ; @reform_date = @reform
455
+ end if @reform.kind_of?(Array)
456
+
457
+ if @reform_date
458
+ @reform_date = When::Coordinates::Pair._en_pair_date_time(@reform_date) if @reform_date.kind_of?(String)
459
+ @reform_date = @reform_date.map {|c| c.to_i}
460
+ (1..2).each {|i| @reform_date[i] = @reform_date[i] ? @reform_date[i] - 1 : 0 }
461
+ @reform_jdn = @new._coordinates_to_number(*@reform_date)
462
+ else
463
+ @reform_jdn ||= [@old.class::DefaultReformDate, @new.class::DefaultReformDate].max
464
+ @reform_jdn = @reform_jdn.to_i
465
+ @reform_date = @new._number_to_coordinates(@reform_jdn)
466
+ end
467
+ last_date = @old._number_to_coordinates(@reform_jdn-1)
468
+
469
+ # 復活祭との前後関係
470
+ @the_easter = @reform_jdn > When.CalendarNote('Christian').easter(@reform_date[0], @new) ? @reform_date[0]+1 : @reform_date[0]
471
+
472
+ # 月の日数
473
+ this_month = @reform_date[0..1]
474
+ new_length = @new._length(this_month)
475
+ @the_length = {}
476
+ if @reform_date[1] == last_date[1] # 同一月内に閉じた改暦
477
+ skipped_length = @reform_date[2] - last_date[2] - 1
478
+ @the_length[this_month] = [skipped_length, last_date[2]+1, new_length-skipped_length]
479
+ else
480
+ last_month = [(@reform_date[1] > last_date[1] ? @reform_date[0] : @reform_date[0]-1), last_date[1]]
481
+ @the_length[this_month] = [@reform_date[2], 0, new_length - @reform_date[2]]
482
+ @the_length[last_month] = [false, false, last_date[2]+1]
483
+ end
484
+
485
+ super
486
+ end
487
+
488
+ #
489
+ # 整数のindex化
490
+ #
491
+ def _to_index(date)
492
+ digit = date[-1] - @base[date.length-1]
493
+ skip, limit = @the_length[date[0..-2]]
494
+ skip && digit >= limit ? digit-skip : digit
495
+ end
496
+
497
+ #
498
+ # indexの整数化
499
+ #
500
+ def _from_index(date)
501
+ digit = date[-1]
502
+ skip, limit = @the_length[date[0..-2]]
503
+ (skip && digit >= limit ? digit+skip : digit)+@base[date.length-1]
504
+ end
505
+ end
506
+
507
+ #
508
+ # 日時要素の境界 - 復活祭
509
+ #
510
+ class Easter < Border
511
+
512
+ # 境界の取得
513
+ #
514
+ # @param [Array<Numeric>] date 境界を計算する年
515
+ # @param [When::TM::ReferenceSystem] frame 使用する暦法
516
+ #
517
+ # @return [Array<Numeric>] その年の境界
518
+ #
519
+ def border(date=[], frame=When::Gregorian)
520
+ frame._encode(frame._number_to_coordinates(frame.note.easter(date[0], frame)), false)
521
+ end
522
+
523
+ private
524
+
525
+ # 要素の正規化
526
+ def _normalize(args=[], options={})
527
+ @border = [0,0,0]
528
+ end
529
+ end
530
+ end
531
+
532
+ #
533
+ # キリスト教の暦注(クリスマスと復活祭)
534
+ #
535
+ class CalendarNote::Christian < CalendarNote
536
+
537
+ Notes = [When::BasicTypes::M17n, [
538
+ "locale:[=en:, ja=ja:, alias]",
539
+ "names:[Christian]",
540
+
541
+ # 年の暦注 ----------------------------
542
+ [When::BasicTypes::M17n,
543
+ "names:[year]"
544
+ ],
545
+
546
+ # 月の暦注 ----------------------------
547
+ [When::BasicTypes::M17n,
548
+ "names:[month]",
549
+ [When::BasicTypes::M17n,
550
+ "names:[Month]"
551
+ ]
552
+ ],
553
+
554
+ # 日の暦注 ----------------------------
555
+ [When::BasicTypes::M17n,
556
+ "names:[day]",
557
+ [When::BasicTypes::M17n, "names:[Week, 七曜]" ],
558
+ [When::BasicTypes::M17n, "names:[Easter, 復活祭]" ],
559
+ [When::BasicTypes::M17n, "names:[Christmas, クリスマス]"],
560
+ [When::BasicTypes::M17n, "names:[Fixed_feast=, 固定祝日=]" ],
561
+ [When::BasicTypes::M17n, "names:[Moveable_feast, 移動祝日]" ]
562
+ ]
563
+ ]]
564
+
565
+ # 固定祝日
566
+ Fixed_feasts = {
567
+ [ 1, 6] => "Epiphany",
568
+ [ 3, 1] => "St.David's Day",
569
+ [ 3, 17] => "St.Patrick's Day",
570
+ [ 3, 25] => "Annunciation-Lady Day",
571
+ [ 4, 23] => "St.George's Day",
572
+ [ 6, 24] => "Midsummer Day",
573
+ [ 9, 14] => "Holy Cross Day",
574
+ [ 9, 29] => "Michaelmas Day",
575
+ [11, 30] => "St.Andrew's Day",
576
+ [12, 13] => "St.Lucia's Day",
577
+ [12, 21] => "St.Thomas's Day",
578
+ # [12, 25] => "Christmas Day"
579
+ }
580
+
581
+ # 移動祝日 (日付と曜日による)
582
+ moveable_feasts = {}
583
+ [[[ 9, 15, 2], "III Quatember"],
584
+ [[11, 27, 6], "Advent Sunday"],
585
+ [[12, 14, 2], "IV Quatember" ]].each do |pair|
586
+ date, name = pair
587
+ 7.times do
588
+ moveable_feasts[date.dup] = name
589
+ date[1] += 1
590
+ if date[1] > 30
591
+ date[0] += 1
592
+ date[1] = 1
593
+ end
594
+ end
595
+ end
596
+
597
+ # 移動祝日
598
+ Moveable_feasts = {
599
+ # 復活祭からの日数による
600
+ -63 => "Septuagesima Sunday",
601
+ -56 => "Sexagesima Sunday",
602
+ -49 => "Quinquagesima Sunday",
603
+ -46 => "Ash Wednesday",
604
+ -42 => "Quadragesima Sunday",
605
+ -40 => "I Quatember",
606
+ -35 => "Reminizer Sunday",
607
+ -28 => "Oculi Sunday",
608
+ -21 => "Laetare Sunday",
609
+ -14 => "Judica Sunday",
610
+ -7 => "Palmarum",
611
+ -2 => "Good Friday",
612
+ # 0 => "Easter Day",
613
+ 7 => "Low Sunday",
614
+ 35 => "Rogation Sunday",
615
+ 39 => "Ascension Day",
616
+ 49 => "Whitsunday",
617
+ 53 => "II Quatember",
618
+ 56 => "Trinity Sunday",
619
+ 60 => "Corpus Christi",
620
+ }.update(moveable_feasts)
621
+
622
+ #
623
+ # 暦法によってイベントの動作を変えるか否か
624
+ #
625
+ CalendarDepend = true
626
+
627
+ # 週日補正フラグ
628
+ # @return [Integer]
629
+ attr_reader :w
630
+
631
+ # 最も遅い満月の3月0日からの日数
632
+ # @return [Integer]
633
+ attr_reader :d
634
+
635
+ # クリスマスの3月0日からの日数
636
+ # @return [Integer]
637
+ attr_reader :x
638
+
639
+ # 平年数
640
+ # @return [Integer]
641
+ attr_reader :n
642
+
643
+ # 置閏周期
644
+ # @return [Integer]
645
+ attr_reader :s
646
+
647
+ # 月の位相の補正
648
+ # @return [Integer]
649
+ attr_reader :c
650
+
651
+ # ガード
652
+ # @return [Integer]
653
+ attr_reader :g
654
+
655
+ # ベース
656
+ # @return [Integer]
657
+ attr_reader :b
658
+
659
+ # 満月補正フラグ
660
+ # @return [Integer]
661
+ attr_reader :f
662
+
663
+ # 七曜
664
+ #
665
+ # @param [When::TM::TemporalPosition] date
666
+ # @param [When::TM::CalDate] base (not used)
667
+ #
668
+ # @return [When::Coordinates::Residue] 七曜
669
+ #
670
+ def week(date, base=nil)
671
+ When.Residue('Week')[date.to_i % 7]
672
+ end
673
+
674
+ # クリスマス
675
+ #
676
+ # @param [Numeric] date 西暦の年数
677
+ # @param [When::TM::TemporalPosition] date
678
+ # @param [When::TM::ReferenceSystem] frame 使用する暦法(デフォルトは When::Gregorian)
679
+ #
680
+ # @return [Integer] クリスマスのユリウス通日(dateが西暦の年数の場合)
681
+ # @return [When::TM::CalDate] クリスマスのWhen::TM::CalDate(yearがWhen::TM::TemporalPositionの場合)
682
+ #
683
+ def christmas(date, frame=nil)
684
+ _event(date, 'christmas', frame) do |year, frame|
685
+ @x - 1 + frame._coordinates_to_number(year, 2, 0)
686
+ end
687
+ end
688
+
689
+ # 復活祭
690
+ #
691
+ # @param [Numeric] date 西暦の年数
692
+ # @param [When::TM::TemporalPosition] date
693
+ # @param [When::TM::ReferenceSystem] frame 使用する暦法(デフォルトは When::Gregorian)
694
+ #
695
+ # @return [Integer] 復活祭のユリウス通日(dateが西暦の年数の場合)
696
+ # @return [When::TM::CalDate] 復活祭のWhen::TM::CalDate(yearがWhen::TM::TemporalPositionの場合)
697
+ #
698
+ def easter(date, frame=nil)
699
+ _event(date, 'easter', frame) do |year, frame|
700
+ golden = (year+@b) % @s + 1
701
+ m = (frame._lunar_equation(year) + 11*golden + @c) % 30
702
+ if @f == 0
703
+ m += 1 if m==0 || m==1 && golden>=@n
704
+ else
705
+ m += (golden-1) / @f
706
+ m -= 30 if m>=@n
707
+ end
708
+ result = frame._coordinates_to_number(year, 2, 0) + @d - 1 - m
709
+ result += @g - (result-@w) % 7 if @w<7
710
+ result + frame._easter_delay(year)
711
+ end
712
+ end
713
+
714
+ # イベントの標準的な間隔を返す
715
+ # @private
716
+ def _delta(parameter=nil)
717
+ return When::P1Y
718
+ end
719
+
720
+ # @private
721
+ alias :christmas_delta :_delta
722
+
723
+ # @private
724
+ alias :easter_delta :_delta
725
+
726
+ # 固定祝日
727
+ #
728
+ # @param [When::TM::TemporalPosition] date
729
+ # @param [When::TM::ReferenceSystem] frame 使用する暦法(デフォルトは When::Gregorian)
730
+ #
731
+ # @return [String] 祝日の名称
732
+ # @return [nil] 祝日に該当しない
733
+ #
734
+ def fixed_feast(date, frame=nil)
735
+ date = When.Calendar(frame||'Gregorian') ^ date unless date.frame.kind_of?(When::CalendarTypes::Christian)
736
+ Fixed_feasts[date.cal_date[-2..-1]]
737
+ end
738
+
739
+ # 移動祝日
740
+ #
741
+ # @param [When::TM::TemporalPosition] date
742
+ # @param [When::TM::ReferenceSystem] frame 使用する暦法(デフォルトは When::Gregorian)
743
+ #
744
+ # @return [String] 祝日の名称
745
+ # @return [nil] 祝日に該当しない
746
+ #
747
+ def moveable_feast(date, frame=nil)
748
+ result = Moveable_feasts[date.to_i - easter(date, frame).to_i]
749
+ return result if result
750
+ date = When.Calendar(frame||'Gregorian') ^ date unless date.frame.kind_of?(When::CalendarTypes::Christian)
751
+ Moveable_feasts[date.cal_date[-2..-1] + [date.to_i % 7]]
752
+ end
753
+
754
+ private
755
+
756
+ # オブジェクトの正規化
757
+ # w - 週日補正フラグ(デフォルト 6)
758
+ # d - 最も遅い満月 (デフォルト 3月0日から 50日)
759
+ # x - クリスマス (デフォルト 3月0日から300日)
760
+ # n - 平年数 (デフォルト 12)
761
+ # s - 置閏周期 (デフォルト 19)
762
+ # c - 月の位相の補正(デフォルト 3)
763
+ # g - ガード (デフォルト 7)
764
+ # b - ベース (デフォルト 0)
765
+ # f - 満月補正フラグ(デフォルト 0)
766
+ def _normalize(args=[], options={})
767
+ w, d, x, n, s, c, g, b, f = args
768
+ @w = (w || @w || 6).to_i
769
+ @d = (d || @d || 50).to_i
770
+ @x = (x || @x || 300).to_i
771
+ @n = (n || @n || 12).to_i
772
+ @s = (s || @s || 19).to_i
773
+ @c = (c || @c || 3).to_i
774
+ @g = (g || @g || 7).to_i
775
+ @b = (b || @b || 0).to_i
776
+ @f = (f || @f || 0).to_i
777
+ @event = 'easter'
778
+ @prime ||= [['Month'], ['Week']]
779
+ super
780
+ end
781
+
782
+ #
783
+ # 任意の暦をグレゴリオorユリウス暦日に変換
784
+ #
785
+ def _to_date_for_note(date)
786
+ return When.Calendar(When::CalendarTypes::Christian._default_start(date)) ^ date if ::Object.const_defined?(:Date) && date.kind_of?(::Date)
787
+ return When::Gregorian ^ date if date.kind_of?(::Time)
788
+ return date if date.frame.kind_of?(When::CalendarTypes::Christian)
789
+ When.Calendar(date.frame.iri =~ /Coptic/ || date.to_i < 2299161 ? 'Julian' : 'Gregorian') ^ date
790
+ end
791
+
792
+ # 当該年のイベントの日付
793
+ # date : 西暦の年数 or When::TM::(Temporal)Position
794
+ # event : イベント名 (String)
795
+ # frame : 暦法(デフォルトは When:Gregorian)
796
+ #
797
+ # @return [Integer] イベントのユリウス通日(dateが西暦の年数の場合)
798
+ # @return [When::TM::CalDate] イベントのWhen::TM::CalDate(yearがWhen::TM::(Temporal)Positionの場合)
799
+ #
800
+ def _event(date, event, frame=nil)
801
+ case date
802
+ when Numeric
803
+ year = date * 1
804
+ when When::TimeValue
805
+ options = date._attr
806
+ options[:precision] = When::DAY
807
+ options[:events] = [event]
808
+ if frame
809
+ frame = When.Calendar(frame)
810
+ date = frame.jul_trans(date, options)
811
+ else
812
+ frame = date.frame
813
+ end
814
+ year = date.most_significant_coordinate * 1
815
+ else
816
+ raise TypeError, "Irregal date type: #{date.class}"
817
+ end
818
+ frame ||= When::Gregorian
819
+ result = yield(year, frame)
820
+ return result if date.kind_of?(Numeric)
821
+ return frame.jul_trans(result, options)
822
+ end
823
+ end
824
+ end