-
Notifications
You must be signed in to change notification settings - Fork 5
/
moment.easter.js
109 lines (103 loc) · 4.28 KB
/
moment.easter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
'use strict';
var moment;
if (typeof require !== 'undefined') {
moment = require('moment');
} else {
moment = this.moment;
}
/*
* I found this algorithm on
* http://www.merlyn.demon.co.uk/estralgs.txt
*
* Given by
* Al Petrofsky, San Mateo County, California, U.S.A., E-mail 2009-05-22
*
*
* To get Month & Day in 23 total arithmetic operations, use:
* c = 148 - b - ((year * 5 / 4 | 0) + a - b) % 7;
* Month = (c / 31 | 0);
* Day = c % 31 + 1;
*
* The coefficients in the formula for A were chosen so that both of
* these equations would hold:
*
* a / 25 % 30 == ((y / 100 * 17 + 11) / 25 - y / 400 + 16) % 30
* a % 7 == (y / 400 + y / 100 * 6 + 2) % 7
*
* As a result, the formulae for B and the return value are
* equivalent to:
*
* b = ( 29 * 11 * (15 + y % 19 * 19
* + y / 100 - y / 400
* - ( (y / 100 + 25 - 14) * 8 / 25
* - ( 25 - 14) * 8 / 25)
* + 1)
* - 1 - y % 19)
* % (30 * 29 * 11) / (30 * 11)
* return 28 + b - (2 + b + y + y / 4 - y / 100 + y / 400) % 7
*
* B represents the date of the Paschal Full Moon, ranging from 0
* for March 21st to 28 for April 18th.
*
* Here are some pertinent facts about the constants in these
* formulae:
*
* 400 is the number of years in the cycle of solar corrections.
* 100 is the number of years between solar or lunar corrections.
* 30 is the number of different epacts (not distinguishing xxv and 25).
* 29 is the number of different Paschal Full Moon dates.
* 28 is the day of March one week after the equinox.
* 25 is the number of centuries in the cycle of lunar corrections.
* 19 is the number of years in the Metonic cycle.
* 19 is also the ordinary decrement from one year's epact to the next.
* 15 is the number of days after the equinox that the Paschal
* Full Moon falls, in the year zero.
* 14 is one hundredth of the year at the start of the first span of
* four centuries between lunar corrections.
* 11 is the number of golden numbers for which epact xxv/25 maps to
* a Paschal Full Moon date of April 18th rather than April 17th.
* 8 is the number of lunar corrections per 25 centuries.
* 7 is the number of days in the week.
* 4 is the number of years in the uncorrected leap year cycle.
* 2 is the number of days that are after the first Sunday after the
* equinox, but on or before March 28, in the year zero.
*
* Implementation limits:
*
* In C and other languages and systems with ordinary fixed-width
* 32-bit unsigned integer arithmetic, the function fails due to
* overflow at year 58,714,311, and with 64-bit integers, it fails
* at year 252,188,329,394,345,111. In either case, if a "y = y %
* 5700000" line is added at the start of the function, then correct
* results will be returned for all possible inputs.
*
* In ECMAscript/javascript: the language has no integer division
* operator, and non-integer division results must somehow be
* rounded down. If division results are truncated by using a
* bitwise logical operation (e.g. "|0") to cause an internal
* floating-point-to-integer conversion, then the first year for
* which the function fails is 1,717,986,919, which is when (y * 5 /
* 4) first exceeds the 31-bit range for unsigned logical integer
* values. If division results are truncated using the Math.floor
* function, then first failure comes at year 123,138,832,709,500,
* shortly after the sum in the B formula first exceeds the 53-bit
* positive range over which IEEE 64-bit floating point values have
* integer precision. In either case, if a "y = y % 5700000" line
* is added at the start of the function, then the correct result
* will be returned for any input that is a non-negative integer.
*/
moment.easter = function Easter20ops(year) {
/*jslint bitwise: true, vars: true */
var a = (year / 100 | 0) * 1483 - (year / 400 | 0) * 2225 + 2613;
var b = ((year % 19 * 3510 + (a / 25 | 0) * 319) / 330 | 0) % 29;
var c = 148 - b - ((year * 5 / 4 | 0) + a - b) % 7;
return moment({year: year, month: (c / 31 | 0) - 1, day: c % 31 + 1});
};
moment.fn.easter = function () {
return moment.easter(this.year());
};
if (typeof module !== 'undefined') {
module.exports = moment;
} else {
this.moment = moment;
}