when_exe 0.4.0 → 0.4.1

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