@jenova-marie/sumerian-date 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +199 -0
- package/dist/index.cjs +577 -0
- package/dist/index.mjs +10 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 jenova-marie
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# sumerian-date
|
|
2
|
+
|
|
3
|
+
Convert Gregorian dates to the **Nippur Sumerian ritual calendar** as documented by [The Ishtar Gate](https://web.archive.org/web/20250125122100/https://www.theishtargate.com/Calendar/) (archived January 2025).
|
|
4
|
+
|
|
5
|
+
Pure JavaScript, zero runtime dependencies, works in Node.js 14+.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Background
|
|
10
|
+
|
|
11
|
+
The Sumerian calendar is a **lunisolar calendar** rooted in the Nippur tradition, the sacred city of Enlil. Each month begins at the first sunset after the astronomical new moon. The year begins with the month whose new moon falls after the vernal equinox. Short years contain 12 months; long years contain 13, following the 19-year Metonic cycle.
|
|
12
|
+
|
|
13
|
+
Astronomical calculations implement the algorithms of Jean Meeus (*Astronomical Algorithms*, 2nd ed.) for:
|
|
14
|
+
- Vernal equinox (Ch. 27)
|
|
15
|
+
- New moon (Ch. 49)
|
|
16
|
+
- Sunset time for Nippur (32.13°N, 45.23°E by default)
|
|
17
|
+
|
|
18
|
+
The day-start rule (sunset) is verified against the Ishtar Gate app reference:
|
|
19
|
+
> New moon 8 April 2024 21:20 local (UTC+3) → year start **10 April 2024** ✓
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install sumerian-date
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
const { sumerianDate, sumerianYear } = require('sumerian-date');
|
|
35
|
+
|
|
36
|
+
// Today's Sumerian date
|
|
37
|
+
const today = sumerianDate();
|
|
38
|
+
console.log(today.toString());
|
|
39
|
+
// → "Day 15 of Šekinku — Gregorian 5 Mar 2026"
|
|
40
|
+
|
|
41
|
+
console.log(today.monthCuneiform); // 𒌗𒊺𒆥𒋻
|
|
42
|
+
console.log(today.monthMeaning); // "Reaping of Barley"
|
|
43
|
+
console.log(today.observances); // [{ name: 'Ešeš', description: '...' }, ...]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## API
|
|
49
|
+
|
|
50
|
+
### `sumerianDate([date], [opts])` → `SumerianDate`
|
|
51
|
+
|
|
52
|
+
Convert a JS `Date` to its Sumerian equivalent. Defaults to `new Date()` (now).
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
const sd = sumerianDate(new Date('2024-06-04T15:37:00Z'));
|
|
56
|
+
|
|
57
|
+
sd.monthName // "Gusisu"
|
|
58
|
+
sd.monthCuneiform // "𒌗𒄞𒋛𒁲"
|
|
59
|
+
sd.monthMeaning // "Marching Forth of Oxen"
|
|
60
|
+
sd.monthDescription // "Beginning of the agricultural season..."
|
|
61
|
+
sd.dayOfMonth // 27
|
|
62
|
+
sd.monthLengthDays // 29
|
|
63
|
+
sd.monthStartDate // Date object
|
|
64
|
+
sd.monthEndDate // Date object
|
|
65
|
+
sd.cyclePosition // 18 (position in the 19-year Metonic cycle)
|
|
66
|
+
sd.isIntercalaryYear // false
|
|
67
|
+
sd.isIntercalaryMonth // false
|
|
68
|
+
sd.observances // Array of { name, description } for today's observances
|
|
69
|
+
sd.toString() // "Day 27 of Gusisu — Gregorian 4 Jun 2024"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**opts:**
|
|
73
|
+
| Option | Default | Description |
|
|
74
|
+
|--------|---------|-------------|
|
|
75
|
+
| `latitude` | `32.13` | Reference latitude for sunset (Nippur) |
|
|
76
|
+
| `longitude` | `45.23` | Reference longitude for sunset (Nippur) |
|
|
77
|
+
|
|
78
|
+
### `sumerianYear([gregorianYear], [opts])` → `SumerianYear`
|
|
79
|
+
|
|
80
|
+
Get the full year structure including all months with start dates.
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const year = sumerianYear(2026);
|
|
84
|
+
|
|
85
|
+
year.springGregorianYear // 2026
|
|
86
|
+
year.cyclePosition // 1 (first year of new 19-year cycle)
|
|
87
|
+
year.isLongYear // false
|
|
88
|
+
year.yearStart // Date: ~late March / early April
|
|
89
|
+
year.yearEnd // Date
|
|
90
|
+
year.nextYearStart // Date
|
|
91
|
+
|
|
92
|
+
year.months.forEach(m => {
|
|
93
|
+
console.log(`${m.number}. ${m.name} — starts ${m.startDate.toDateString()} (${m.lengthDays} days)`);
|
|
94
|
+
});
|
|
95
|
+
// 1. Barazagar — starts Thu Apr 02 2026 (30 days)
|
|
96
|
+
// 2. Gusisu — starts Sat May 02 2026 (29 days)
|
|
97
|
+
// ...
|
|
98
|
+
// 12. Šekinku — starts Mon Feb 22 2027 (29 days)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### `cyclePosition(springGregorianYear)` → `number` (1–19)
|
|
102
|
+
|
|
103
|
+
Returns the position within the 19-year Metonic cycle.
|
|
104
|
+
Long years (13 months) are at positions: **3, 6, 8, 11, 14, 17, 19**.
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
cyclePosition(2007) // 1 — first year of cycle
|
|
108
|
+
cyclePosition(2009) // 3 — long year (Diri Šekinku appended)
|
|
109
|
+
cyclePosition(2023) // 17 — long year (Diri Kin Inana inserted after month 6)
|
|
110
|
+
cyclePosition(2026) // 1 — new cycle begins
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `vernalEquinox(year)` → `Date`
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
vernalEquinox(2024) // Thu Mar 20 2024 03:06 UTC
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `nextNewMoon(afterDate)` → `Date`
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
nextNewMoon(new Date('2024-03-20')) // Mon Apr 08 2024 18:21 UTC
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `months` — Array of month data
|
|
126
|
+
|
|
127
|
+
The twelve standard months. Each has:
|
|
128
|
+
- `number` (1–12)
|
|
129
|
+
- `name` — transliteration
|
|
130
|
+
- `cuneiform` — Unicode cuneiform
|
|
131
|
+
- `meaning` — English translation
|
|
132
|
+
- `season`
|
|
133
|
+
- `description`
|
|
134
|
+
- `festivals` — array of `{ day, name, description }`
|
|
135
|
+
|
|
136
|
+
### `intercalaryMonth` / `intercalaryMonthYear17`
|
|
137
|
+
|
|
138
|
+
The two intercalary month variants (Diri Šekinku and Diri Kin Inana).
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## The Twelve Months
|
|
143
|
+
|
|
144
|
+
| # | Name | 𒀭 | Meaning | Season |
|
|
145
|
+
|---|------|-----|---------|--------|
|
|
146
|
+
| 1 | Barazagar | 𒌗𒁈𒍠𒃻 | Dais of the Sanctuary | Spring |
|
|
147
|
+
| 2 | Gusisu | 𒌗𒄞𒋛𒁲 | Marching Forth of Oxen | Spring |
|
|
148
|
+
| 3 | Sig Ga | 𒌗𒋞𒂵 | Placing of Bricks | Spring |
|
|
149
|
+
| 4 | Šunumun | 𒌗𒋗𒆰𒈾 | Seeding | Summer |
|
|
150
|
+
| 5 | Nenegar | 𒌗𒉈𒉈𒃻 | Lighting of the Braziers | Summer |
|
|
151
|
+
| 6 | Kin Inana | 𒌗𒆥𒀭𒈹 | The Labours of Inana | Summer |
|
|
152
|
+
| 7 | Duku | 𒌗𒇯𒆬 | The Sacred Mound | Autumn |
|
|
153
|
+
| 8 | Apin Dua | 𒌗𒀳𒃮𒀀 | Releasing of the Plough | Autumn |
|
|
154
|
+
| 9 | Gan Gan-e | 𒌗𒃶𒃶𒈾 | Coming of Clouds | Autumn |
|
|
155
|
+
| 10 | Kusu | 𒌗𒆬𒋆 | Lady of the Grain | Autumn |
|
|
156
|
+
| 11 | Uduru | 𒌗𒍩𒀀 | Emmer | Winter |
|
|
157
|
+
| 12 | Šekinku | 𒌗𒊺𒆥𒋻 | Reaping of Barley | Winter |
|
|
158
|
+
| 13* | Diri Šekinku | 𒌗𒋛𒀀𒊺𒆥𒋻 | Second Reaping of Barley | Winter |
|
|
159
|
+
|
|
160
|
+
*Intercalary month, appended after Šekinku in cycle years 3, 6, 8, 11, 14, 19.
|
|
161
|
+
In cycle year 17, *Diri Kin Inana* is inserted after month 6 instead.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Monthly Observances
|
|
166
|
+
|
|
167
|
+
Two observances occur every month:
|
|
168
|
+
|
|
169
|
+
| Day | Name | Description |
|
|
170
|
+
|-----|------|-------------|
|
|
171
|
+
| 7 | **Ešeš** (Quarter Moon) | First-quarter moon; offering to household gods |
|
|
172
|
+
| 15 | **Ešeš** (Full Moon) | Great Offering to all household gods |
|
|
173
|
+
| Last | **Kisiga** (New Moon) | Funerary offerings; libation of fresh water for the dead |
|
|
174
|
+
|
|
175
|
+
These are returned in `sumerianDate().observances` for the current day.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Calendar Rules (Summary)
|
|
180
|
+
|
|
181
|
+
1. **Month start**: First sunset after the astronomical new moon (day begins at sunset, per Sumerian custom).
|
|
182
|
+
2. **Year start**: The month whose new moon falls first after the vernal equinox.
|
|
183
|
+
3. **Intercalation**: Metonic 19-year cycle. Years 3, 6, 8, 11, 14, 17, 19 have 13 months. Cycle began spring 2007.
|
|
184
|
+
4. **Month 13 placement**: After month 12 in most long years; after month 6 (as *Diri Kin Inana*) in cycle year 17.
|
|
185
|
+
5. **Reference location**: Nippur (32.13°N, 45.23°E) by default. Override with `opts.latitude` / `opts.longitude`.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Sources
|
|
190
|
+
|
|
191
|
+
- **The Ishtar Gate** — Ritual Calendar (archived): https://web.archive.org/web/20250125122100/https://www.theishtargate.com/Calendar/
|
|
192
|
+
- Mark E. Cohen, *Cultic Calendars of the Ancient Near East* (CDL Press, 1993)
|
|
193
|
+
- Jean Meeus, *Astronomical Algorithms* (2nd ed., Willmann-Bell, 1998) — Chapters 27 & 49
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
4
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/astronomy.js
|
|
8
|
+
var require_astronomy = __commonJS({
|
|
9
|
+
"src/astronomy.js"(exports2, module2) {
|
|
10
|
+
"use strict";
|
|
11
|
+
var DEG = Math.PI / 180;
|
|
12
|
+
function gregorianToJD(year, month, day) {
|
|
13
|
+
let y = year;
|
|
14
|
+
let m = month;
|
|
15
|
+
if (m <= 2) {
|
|
16
|
+
y -= 1;
|
|
17
|
+
m += 12;
|
|
18
|
+
}
|
|
19
|
+
const A = Math.floor(y / 100);
|
|
20
|
+
const B = 2 - A + Math.floor(A / 4);
|
|
21
|
+
return Math.floor(365.25 * (y + 4716)) + Math.floor(30.6001 * (m + 1)) + day + B - 1524.5;
|
|
22
|
+
}
|
|
23
|
+
function jdToGregorian2(jd) {
|
|
24
|
+
const z = Math.floor(jd + 0.5);
|
|
25
|
+
const f = jd + 0.5 - z;
|
|
26
|
+
let A;
|
|
27
|
+
if (z < 2299161) {
|
|
28
|
+
A = z;
|
|
29
|
+
} else {
|
|
30
|
+
const alpha = Math.floor((z - 186721625e-2) / 36524.25);
|
|
31
|
+
A = z + 1 + alpha - Math.floor(alpha / 4);
|
|
32
|
+
}
|
|
33
|
+
const B = A + 1524;
|
|
34
|
+
const C = Math.floor((B - 122.1) / 365.25);
|
|
35
|
+
const D = Math.floor(365.25 * C);
|
|
36
|
+
const E = Math.floor((B - D) / 30.6001);
|
|
37
|
+
const dayFrac = B - D - Math.floor(30.6001 * E) + f;
|
|
38
|
+
const day = Math.floor(dayFrac);
|
|
39
|
+
const month = E < 14 ? E - 1 : E - 13;
|
|
40
|
+
const year = month > 2 ? C - 4716 : C - 4715;
|
|
41
|
+
const fracDay = dayFrac - day;
|
|
42
|
+
const hour = Math.floor(fracDay * 24);
|
|
43
|
+
const fracHour = fracDay * 24 - hour;
|
|
44
|
+
const minute = Math.floor(fracHour * 60);
|
|
45
|
+
const second = Math.round((fracHour * 60 - minute) * 60);
|
|
46
|
+
return { year, month, day, hour, minute, second };
|
|
47
|
+
}
|
|
48
|
+
function vernalEquinoxJDE2(year) {
|
|
49
|
+
let JDE0;
|
|
50
|
+
if (year >= 1e3) {
|
|
51
|
+
const Y = (year - 2e3) / 1e3;
|
|
52
|
+
JDE0 = 245162380984e-5 + 365242.37404 * Y + 0.05169 * Y * Y - 411e-5 * Y * Y * Y - 57e-5 * Y * Y * Y * Y;
|
|
53
|
+
} else {
|
|
54
|
+
const Y = year / 1e3;
|
|
55
|
+
JDE0 = 17211392855e-4 + 365242.1376 * Y + 0.06679 * Y * Y - 669e-5 * Y * Y * Y;
|
|
56
|
+
}
|
|
57
|
+
const T = (JDE0 - 2451545) / 36525;
|
|
58
|
+
const W = 35999.373 * T - 2.47;
|
|
59
|
+
const dL = 1 + 0.0334 * Math.cos(W * DEG) + 7e-4 * Math.cos(2 * W * DEG);
|
|
60
|
+
const corrections = [
|
|
61
|
+
[485, 324.96, 1934.136],
|
|
62
|
+
[203, 337.23, 32964.467],
|
|
63
|
+
[199, 342.08, 20.186],
|
|
64
|
+
[182, 27.85, 445267.112],
|
|
65
|
+
[156, 73.14, 45036.886],
|
|
66
|
+
[136, 171.52, 22518.443],
|
|
67
|
+
[77, 222.54, 65928.934],
|
|
68
|
+
[74, 296.72, 3034.906],
|
|
69
|
+
[70, 243.58, 9037.513],
|
|
70
|
+
[58, 119.81, 33718.147],
|
|
71
|
+
[52, 297.17, 150.678],
|
|
72
|
+
[50, 21.02, 2281.226],
|
|
73
|
+
[45, 247.54, 29929.562],
|
|
74
|
+
[44, 325.15, 31555.956],
|
|
75
|
+
[29, 60.93, 4443.417],
|
|
76
|
+
[18, 155.12, 67555.328],
|
|
77
|
+
[17, 288.79, 4562.452],
|
|
78
|
+
[16, 198.04, 62894.029],
|
|
79
|
+
[14, 199.76, 31557.381],
|
|
80
|
+
[12, 95.39, 14577.848],
|
|
81
|
+
[10, 49.69, 31557.381],
|
|
82
|
+
[9, 162.03, 31557.381],
|
|
83
|
+
[9, 35.47, 1222.114],
|
|
84
|
+
[9, 32.43, 1191.013],
|
|
85
|
+
[9, 36.4, 1232.124],
|
|
86
|
+
[9, 57.03, 1229.225]
|
|
87
|
+
];
|
|
88
|
+
const S = corrections.reduce((sum, [a, b, c]) => sum + a * Math.cos(DEG * (b + c * T)), 0);
|
|
89
|
+
return JDE0 + 1e-5 * S / dL;
|
|
90
|
+
}
|
|
91
|
+
function newMoonJDE(k) {
|
|
92
|
+
const T = k / 1236.85;
|
|
93
|
+
const T2 = T * T;
|
|
94
|
+
const T3 = T2 * T;
|
|
95
|
+
const T4 = T3 * T;
|
|
96
|
+
let JDE = 245155009766e-5 + 29.530588861 * k + 15437e-8 * T2 - 15e-8 * T3 + 73e-11 * T4;
|
|
97
|
+
const E = 1 - 2516e-6 * T - 74e-7 * T2;
|
|
98
|
+
const M = (2.5534 + 29.1053567 * k - 14e-7 * T2 - 11e-8 * T3) * DEG;
|
|
99
|
+
const Mp = (201.5643 + 385.81693528 * k + 0.0107582 * T2 + 1238e-8 * T3 - 58e-9 * T4) * DEG;
|
|
100
|
+
const F = (160.7108 + 390.67050284 * k - 16118e-7 * T2 - 227e-8 * T3 + 11e-9 * T4) * DEG;
|
|
101
|
+
const Om = (124.7746 - 1.56375588 * k + 20672e-7 * T2 + 215e-8 * T3) * DEG;
|
|
102
|
+
JDE += -0.4072 * Math.sin(Mp) + 0.17241 * E * Math.sin(M) + 0.01608 * Math.sin(2 * Mp) + 0.01039 * Math.sin(2 * F) + 739e-5 * E * Math.sin(Mp - M) - 514e-5 * E * Math.sin(Mp + M) + 208e-5 * E * E * Math.sin(2 * M) - 111e-5 * Math.sin(Mp - 2 * F) - 57e-5 * Math.sin(Mp + 2 * F) + 56e-5 * E * Math.sin(2 * Mp + M) - 42e-5 * Math.sin(3 * Mp) + 42e-5 * E * Math.sin(M + 2 * F) + 38e-5 * E * Math.sin(M - 2 * F) - 24e-5 * E * Math.sin(2 * Mp - M) - 17e-5 * Math.sin(Om) - 7e-5 * Math.sin(Mp + 2 * M) + 4e-5 * Math.sin(2 * Mp - 2 * F) + 4e-5 * Math.sin(3 * M) + 3e-5 * Math.sin(Mp + M - 2 * F) + 3e-5 * Math.sin(2 * Mp + 2 * F) - 3e-5 * Math.sin(Mp + M + 2 * F) + 3e-5 * Math.sin(Mp - M + 2 * F) - 2e-5 * Math.sin(Mp - M - 2 * F) - 2e-5 * Math.sin(3 * Mp + M) + 2e-5 * Math.sin(4 * Mp);
|
|
103
|
+
return JDE;
|
|
104
|
+
}
|
|
105
|
+
function kNearJDE(jde) {
|
|
106
|
+
return (jde - 245155009766e-5) / 29.530588861;
|
|
107
|
+
}
|
|
108
|
+
function firstNewMoonAfter2(afterJDE) {
|
|
109
|
+
let k = Math.ceil(kNearJDE(afterJDE));
|
|
110
|
+
let nm = newMoonJDE(k);
|
|
111
|
+
while (nm <= afterJDE + 0.01) {
|
|
112
|
+
k++;
|
|
113
|
+
nm = newMoonJDE(k);
|
|
114
|
+
}
|
|
115
|
+
return nm;
|
|
116
|
+
}
|
|
117
|
+
function sunsetUTHour(jdNoon, latitude, longitude) {
|
|
118
|
+
const lngHour = longitude / 15;
|
|
119
|
+
const { year, month, day } = jdToGregorian2(jdNoon);
|
|
120
|
+
const N = Math.floor(275 * month / 9) - 2 * Math.floor((month + 9) / 12) + day - 30;
|
|
121
|
+
const t = N + (18 - lngHour) / 24;
|
|
122
|
+
const M = (0.9856 * t - 3.289) % 360;
|
|
123
|
+
let L = M + 1.916 * Math.sin(M * DEG) + 0.02 * Math.sin(2 * M * DEG) + 282.634;
|
|
124
|
+
L = (L % 360 + 360) % 360;
|
|
125
|
+
let RA = (Math.atan(0.91764 * Math.tan(L * DEG)) / DEG + 360) % 360;
|
|
126
|
+
const Lq = Math.floor(L / 90) * 90;
|
|
127
|
+
const RAq = Math.floor(RA / 90) * 90;
|
|
128
|
+
RA = (RA + Lq - RAq) / 15;
|
|
129
|
+
const sinDec = 0.39782 * Math.sin(L * DEG);
|
|
130
|
+
const cosDec = Math.cos(Math.asin(sinDec));
|
|
131
|
+
const cosH = (Math.cos(90.833 * DEG) - sinDec * Math.sin(latitude * DEG)) / (cosDec * Math.cos(latitude * DEG));
|
|
132
|
+
if (cosH > 1) return null;
|
|
133
|
+
if (cosH < -1) return null;
|
|
134
|
+
const H = Math.acos(cosH) / DEG / 15;
|
|
135
|
+
let T = H + RA - 0.06571 * t - 6.622;
|
|
136
|
+
let UT = T - lngHour;
|
|
137
|
+
return (UT % 24 + 24) % 24;
|
|
138
|
+
}
|
|
139
|
+
module2.exports = {
|
|
140
|
+
gregorianToJD,
|
|
141
|
+
jdToGregorian: jdToGregorian2,
|
|
142
|
+
vernalEquinoxJDE: vernalEquinoxJDE2,
|
|
143
|
+
newMoonJDE,
|
|
144
|
+
firstNewMoonAfter: firstNewMoonAfter2,
|
|
145
|
+
sunsetUTHour,
|
|
146
|
+
kNearJDE
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// src/months.js
|
|
152
|
+
var require_months = __commonJS({
|
|
153
|
+
"src/months.js"(exports2, module2) {
|
|
154
|
+
"use strict";
|
|
155
|
+
var MONTHS2 = [
|
|
156
|
+
{
|
|
157
|
+
number: 1,
|
|
158
|
+
name: "Barazagar",
|
|
159
|
+
cuneiform: "\u{12317}\u{12048}\u{12360}\u{120FB}",
|
|
160
|
+
meaning: "Dais of the Sanctuary",
|
|
161
|
+
season: "spring",
|
|
162
|
+
description: "New Year. The throne-dais of Enlil at the E-kur temple of Nippur. The zagmuk (akitu) New Year festival begins, commemorating the bond between humanity and the gods.",
|
|
163
|
+
festivals: [
|
|
164
|
+
{ day: 1, name: "Zagmuk (New Year / Akitu)", description: "Multi-day New Year festival begins." },
|
|
165
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering to all household gods." }
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
number: 2,
|
|
170
|
+
name: "Gusisu",
|
|
171
|
+
cuneiform: "\u{12317}\u{1211E}\u{122DB}\u{12072}",
|
|
172
|
+
meaning: "Marching Forth of Oxen",
|
|
173
|
+
season: "spring",
|
|
174
|
+
description: "Beginning of the agricultural season. Sacred to Ninurta, Lord of the Plough. A time to prepare resources and reflect on intentions set at New Year.",
|
|
175
|
+
festivals: [
|
|
176
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "First-quarter moon offering." },
|
|
177
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." },
|
|
178
|
+
{ day: 20, name: "Ezem Gusisu (Day 1)", description: "Three-day Festival of Marching Oxen begins." },
|
|
179
|
+
{ day: 21, name: "Ezem Gusisu (Day 2)", description: "" },
|
|
180
|
+
{ day: 22, name: "Ezem Gusisu (Day 3)", description: "Ninurta receives highest honours." }
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
number: 3,
|
|
185
|
+
name: "Sig Ga",
|
|
186
|
+
cuneiform: "\u{12317}\u{122DE}\u{120B5}",
|
|
187
|
+
meaning: "Placing of Bricks",
|
|
188
|
+
season: "spring",
|
|
189
|
+
description: "Labour of the cities and making of mud bricks. A time to lay firm foundations. Holy days sacred to the brick god Kulla.",
|
|
190
|
+
festivals: [
|
|
191
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
192
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." }
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
number: 4,
|
|
197
|
+
name: "\u0160unumun",
|
|
198
|
+
cuneiform: "\u{12317}\u{122D7}\u{121B0}\u{1223E}",
|
|
199
|
+
meaning: "Seeding",
|
|
200
|
+
season: "summer",
|
|
201
|
+
description: "Ceremonial onset of the seeding season; fields prepared by weeding. Month of ritual mourning for Dumuzi (Tammuz), consort of Inana, who descends to the Underworld for six months.",
|
|
202
|
+
festivals: [
|
|
203
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
204
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." },
|
|
205
|
+
{ day: null, name: "Mourning of Dumuzi", description: "Ritual mourning for Dumuzi throughout the month." }
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
number: 5,
|
|
210
|
+
name: "Nenegar",
|
|
211
|
+
cuneiform: "\u{12317}\u{12248}\u{12248}\u{120FB}",
|
|
212
|
+
meaning: "Lighting of the Braziers",
|
|
213
|
+
season: "summer",
|
|
214
|
+
description: "Height of the Mesopotamian summer. The worlds of the living and dead are most closely connected. Fires lit as invitation to and protection from spirits of the dead.",
|
|
215
|
+
festivals: [
|
|
216
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
217
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." },
|
|
218
|
+
{ day: 27, name: "Festival of Spirits", description: "Braziers lit; ceremonial meal with the dead; offerings to chthonic deities and gods of the Underworld." }
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
number: 6,
|
|
223
|
+
name: "Kin Inana",
|
|
224
|
+
cuneiform: "\u{12317}\u{121A5}\u{1202D}\u{12239}",
|
|
225
|
+
meaning: "The Labours of Inana",
|
|
226
|
+
season: "summer",
|
|
227
|
+
description: "Month-long celebration and adoration of Inana. Her statue is adorned and processed to the temples of Enlil and Nanna. The second half recreates Inana's Descent to the Underworld and triumphant return.",
|
|
228
|
+
festivals: [
|
|
229
|
+
{ day: 1, name: "Adornment of Inana", description: "Inana's statue robed in jewellery and divine icons." },
|
|
230
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
231
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon) / Great Offering of Inana", description: "Peak of the month's festivities." },
|
|
232
|
+
{ day: 21, name: "Return of Inana", description: "Statues ceremonially bathed and re-invested." },
|
|
233
|
+
{ day: 26, name: "Inana's Glory", description: "Further offerings; recitations of myths of Inana's power." }
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
number: 7,
|
|
238
|
+
name: "Duku",
|
|
239
|
+
cuneiform: "\u{12317}\u{121EF}\u{121AC}",
|
|
240
|
+
meaning: "The Sacred Mound",
|
|
241
|
+
season: "autumn",
|
|
242
|
+
description: "Second half of the year begins with its own akitu festival. The Sacred Mound is where earth first emerged from the primordial waters and life was first created. The seventh day of the seventh month is a day to petition the gods for peace and vitality.",
|
|
243
|
+
festivals: [
|
|
244
|
+
{ day: 1, name: "Akitu (Autumnal)", description: "Second half-year festival; honouring primordial ancestors." },
|
|
245
|
+
{ day: 7, name: "Petition Day / E\u0161e\u0161", description: "Petition the gods for peace, health, and vitality." },
|
|
246
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." }
|
|
247
|
+
]
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
number: 8,
|
|
251
|
+
name: "Apin Dua",
|
|
252
|
+
cuneiform: "\u{12317}\u{12033}\u{120EE}\u{12000}",
|
|
253
|
+
meaning: "Releasing of the Plough",
|
|
254
|
+
season: "autumn",
|
|
255
|
+
description: "The plough is put away; seeding is complete and the harvest awaited. A time to check milestones and tie off loose ends. Cities of Ur, Isin, Larsa, and Adab also celebrate a Festival of Spirits this month.",
|
|
256
|
+
festivals: [
|
|
257
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
258
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." }
|
|
259
|
+
]
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
number: 9,
|
|
263
|
+
name: "Gan Gan-e",
|
|
264
|
+
cuneiform: "\u{12317}\u{120F6}\u{120F6}\u{1223E}",
|
|
265
|
+
meaning: "Coming of Clouds",
|
|
266
|
+
season: "autumn",
|
|
267
|
+
description: "Start of the growing season; clouds appear over the plain of Sumer. Sacred to the storm god I\u0161kur. A time of anticipation and perseverance.",
|
|
268
|
+
festivals: [
|
|
269
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
270
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." },
|
|
271
|
+
{ day: 28, name: "Festival of Clouds", description: "Offerings to I\u0161kur, god of storms." }
|
|
272
|
+
]
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
number: 10,
|
|
276
|
+
name: "Kusu",
|
|
277
|
+
cuneiform: "\u{12317}\u{121AC}\u{122C6}",
|
|
278
|
+
meaning: "Lady of the Grain",
|
|
279
|
+
season: "autumn",
|
|
280
|
+
description: "Named for Ezina-Kusu, grain goddess of Nippur, associated with Nisaba. The amber waves of grain approach full height. A time of preparation for the imminent harvest. (Also known as Abbe after c. 2000 BCE at Nippur.)",
|
|
281
|
+
festivals: [
|
|
282
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
283
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." }
|
|
284
|
+
]
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
number: 11,
|
|
288
|
+
name: "Uduru",
|
|
289
|
+
cuneiform: "\u{12317}\u{12369}\u{12000}",
|
|
290
|
+
meaning: "Emmer",
|
|
291
|
+
season: "winter",
|
|
292
|
+
description: "The harvest season begins in earnest. Emmer and barley \u2014 principal crops of Sumer \u2014 are reaped. The work of the year comes to a close.",
|
|
293
|
+
festivals: [
|
|
294
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
295
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." }
|
|
296
|
+
]
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
number: 12,
|
|
300
|
+
name: "\u0160ekinku",
|
|
301
|
+
cuneiform: "\u{12317}\u{122BA}\u{121A5}\u{122FB}",
|
|
302
|
+
meaning: "Reaping of Barley",
|
|
303
|
+
season: "winter",
|
|
304
|
+
description: "Culmination of the year. The barley harvest \u2014 high point of the Sumerian agricultural cycle \u2014 is celebrated with great hope and joy. Contains the vernal equinox, after which the new year begins.",
|
|
305
|
+
festivals: [
|
|
306
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
307
|
+
{ day: 15, name: "Festival of Barley / E\u0161e\u0161 (Full Moon)", description: "Honour, offerings, and praise given to Enlil and Ezina." }
|
|
308
|
+
]
|
|
309
|
+
}
|
|
310
|
+
];
|
|
311
|
+
var DIRI_\u0160EKINKU2 = {
|
|
312
|
+
number: 13,
|
|
313
|
+
name: "Diri \u0160ekinku",
|
|
314
|
+
cuneiform: "\u{12317}\u{122DB}\u{12000}\u{122BA}\u{121A5}\u{122FB}",
|
|
315
|
+
meaning: "Second Reaping of Barley",
|
|
316
|
+
season: "winter",
|
|
317
|
+
intercalary: true,
|
|
318
|
+
description: "Intercalary month; observations mirror those of \u0160ekinku.",
|
|
319
|
+
festivals: [
|
|
320
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
321
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." }
|
|
322
|
+
]
|
|
323
|
+
};
|
|
324
|
+
var DIRI_KIN_INANA2 = {
|
|
325
|
+
number: 7,
|
|
326
|
+
// inserted before standard month 7 (Duku)
|
|
327
|
+
name: "Diri Kin Inana",
|
|
328
|
+
cuneiform: null,
|
|
329
|
+
// not attested in the source document
|
|
330
|
+
meaning: "Second Labours of Inana",
|
|
331
|
+
season: "summer",
|
|
332
|
+
intercalary: true,
|
|
333
|
+
description: "Intercalary month in cycle year 17 only; inserted after Kin Inana. Observations likely mirror those of Kin Inana.",
|
|
334
|
+
festivals: [
|
|
335
|
+
{ day: 7, name: "E\u0161e\u0161 (Quarter Moon)", description: "" },
|
|
336
|
+
{ day: 15, name: "E\u0161e\u0161 (Full Moon)", description: "Great Offering." }
|
|
337
|
+
]
|
|
338
|
+
};
|
|
339
|
+
module2.exports = { MONTHS: MONTHS2, DIRI_\u0160EKINKU: DIRI_\u0160EKINKU2, DIRI_KIN_INANA: DIRI_KIN_INANA2 };
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// src/calendar.js
|
|
344
|
+
var require_calendar = __commonJS({
|
|
345
|
+
"src/calendar.js"(exports2, module2) {
|
|
346
|
+
"use strict";
|
|
347
|
+
var {
|
|
348
|
+
gregorianToJD,
|
|
349
|
+
jdToGregorian: jdToGregorian2,
|
|
350
|
+
vernalEquinoxJDE: vernalEquinoxJDE2,
|
|
351
|
+
firstNewMoonAfter: firstNewMoonAfter2,
|
|
352
|
+
sunsetUTHour
|
|
353
|
+
} = require_astronomy();
|
|
354
|
+
var { MONTHS: MONTHS2, DIRI_\u0160EKINKU: DIRI_\u0160EKINKU2, DIRI_KIN_INANA: DIRI_KIN_INANA2 } = require_months();
|
|
355
|
+
var LONG_YEAR_POSITIONS = /* @__PURE__ */ new Set([3, 6, 8, 11, 14, 17, 19]);
|
|
356
|
+
var CYCLE_EPOCH_GREGORIAN_YEAR = 2007;
|
|
357
|
+
function getCyclePosition2(springYear) {
|
|
358
|
+
const offset = ((springYear - CYCLE_EPOCH_GREGORIAN_YEAR) % 19 + 19) % 19;
|
|
359
|
+
return offset + 1;
|
|
360
|
+
}
|
|
361
|
+
function buildMonthSequence(cyclePosition2) {
|
|
362
|
+
const isLong = LONG_YEAR_POSITIONS.has(cyclePosition2);
|
|
363
|
+
if (!isLong) {
|
|
364
|
+
return MONTHS2.slice(0, 12).map((m) => ({ ...m }));
|
|
365
|
+
}
|
|
366
|
+
if (cyclePosition2 === 17) {
|
|
367
|
+
const seq = [];
|
|
368
|
+
for (let i = 0; i < 12; i++) {
|
|
369
|
+
const m = { ...MONTHS2[i] };
|
|
370
|
+
if (i >= 6) m.number = i + 2;
|
|
371
|
+
seq.push(m);
|
|
372
|
+
if (i === 5) {
|
|
373
|
+
seq.push({ ...DIRI_KIN_INANA2, number: 7 });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return seq;
|
|
377
|
+
}
|
|
378
|
+
return [
|
|
379
|
+
...MONTHS2.slice(0, 12).map((m) => ({ ...m })),
|
|
380
|
+
{ ...DIRI_\u0160EKINKU2 }
|
|
381
|
+
];
|
|
382
|
+
}
|
|
383
|
+
var NIPPUR_LAT = 32.13;
|
|
384
|
+
var NIPPUR_LON = 45.23;
|
|
385
|
+
function monthStartDate(nmJDE, latitude = NIPPUR_LAT, longitude = NIPPUR_LON) {
|
|
386
|
+
const g = jdToGregorian2(nmJDE);
|
|
387
|
+
const jdNoon = gregorianToJD(g.year, g.month, g.day);
|
|
388
|
+
const sunsetUT = sunsetUTHour(jdNoon, latitude, longitude);
|
|
389
|
+
const nmUTHour = (nmJDE - jdNoon) * 24 + 12;
|
|
390
|
+
const effectiveSunset = sunsetUT !== null ? sunsetUT : 18;
|
|
391
|
+
const daysToAdd = nmUTHour < effectiveSunset ? 1 : 2;
|
|
392
|
+
const start = new Date(Date.UTC(g.year, g.month - 1, g.day));
|
|
393
|
+
start.setUTCDate(start.getUTCDate() + daysToAdd);
|
|
394
|
+
return start;
|
|
395
|
+
}
|
|
396
|
+
function computeSumerianYear2(springGregorianYear, opts = {}) {
|
|
397
|
+
const lat = opts.latitude ?? NIPPUR_LAT;
|
|
398
|
+
const lon = opts.longitude ?? NIPPUR_LON;
|
|
399
|
+
const cyclePosition2 = getCyclePosition2(springGregorianYear);
|
|
400
|
+
const monthSequence = buildMonthSequence(cyclePosition2);
|
|
401
|
+
const isLongYear = LONG_YEAR_POSITIONS.has(cyclePosition2);
|
|
402
|
+
const veJDE = vernalEquinoxJDE2(springGregorianYear);
|
|
403
|
+
const yearNmJDE = firstNewMoonAfter2(veJDE);
|
|
404
|
+
const yearStart = monthStartDate(yearNmJDE, lat, lon);
|
|
405
|
+
let searchAfterJDE = yearNmJDE - 0.5;
|
|
406
|
+
const months2 = [];
|
|
407
|
+
for (let i = 0; i < monthSequence.length; i++) {
|
|
408
|
+
const nm = i === 0 ? yearNmJDE : firstNewMoonAfter2(searchAfterJDE);
|
|
409
|
+
const start = i === 0 ? yearStart : monthStartDate(nm, lat, lon);
|
|
410
|
+
months2.push({
|
|
411
|
+
...monthSequence[i],
|
|
412
|
+
startDate: start,
|
|
413
|
+
newMoonJDE: nm
|
|
414
|
+
});
|
|
415
|
+
searchAfterJDE = nm;
|
|
416
|
+
}
|
|
417
|
+
const nextYearVeJDE = vernalEquinoxJDE2(springGregorianYear + 1);
|
|
418
|
+
const nextYearNmJDE = firstNewMoonAfter2(nextYearVeJDE);
|
|
419
|
+
const nextYearStart = monthStartDate(nextYearNmJDE, lat, lon);
|
|
420
|
+
for (let i = 0; i < months2.length; i++) {
|
|
421
|
+
const nextStart = i + 1 < months2.length ? months2[i + 1].startDate : nextYearStart;
|
|
422
|
+
const msMs = months2[i].startDate.getTime();
|
|
423
|
+
const nxMs = nextStart.getTime();
|
|
424
|
+
months2[i].endDate = new Date(nxMs - 864e5);
|
|
425
|
+
months2[i].lengthDays = Math.round((nxMs - msMs) / 864e5);
|
|
426
|
+
}
|
|
427
|
+
return {
|
|
428
|
+
springGregorianYear,
|
|
429
|
+
cyclePosition: cyclePosition2,
|
|
430
|
+
isLongYear,
|
|
431
|
+
yearStart,
|
|
432
|
+
yearEnd: new Date(nextYearStart.getTime() - 864e5),
|
|
433
|
+
nextYearStart,
|
|
434
|
+
months: months2,
|
|
435
|
+
vernalEquinoxJDE: veJDE,
|
|
436
|
+
/** Gregorian date of the vernal equinox */
|
|
437
|
+
get vernalEquinoxDate() {
|
|
438
|
+
const g = jdToGregorian2(veJDE);
|
|
439
|
+
return new Date(Date.UTC(g.year, g.month - 1, g.day));
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function toSumerianDate2(date, opts = {}) {
|
|
444
|
+
if (!(date instanceof Date)) {
|
|
445
|
+
opts = date || {};
|
|
446
|
+
date = /* @__PURE__ */ new Date();
|
|
447
|
+
}
|
|
448
|
+
const gregorianYear = date.getUTCFullYear();
|
|
449
|
+
const candidates = [gregorianYear, gregorianYear - 1, gregorianYear + 1];
|
|
450
|
+
let sYear = null;
|
|
451
|
+
for (const candidate of candidates) {
|
|
452
|
+
const sy = computeSumerianYear2(candidate, opts);
|
|
453
|
+
if (date >= sy.yearStart && date < sy.nextYearStart) {
|
|
454
|
+
sYear = sy;
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
if (!sYear) {
|
|
459
|
+
throw new Error(`Could not determine Sumerian year for ${date.toISOString()}`);
|
|
460
|
+
}
|
|
461
|
+
let monthObj = null;
|
|
462
|
+
let dayOfMonth = null;
|
|
463
|
+
for (let i = 0; i < sYear.months.length; i++) {
|
|
464
|
+
const m = sYear.months[i];
|
|
465
|
+
const next = i + 1 < sYear.months.length ? sYear.months[i + 1].startDate : sYear.nextYearStart;
|
|
466
|
+
if (date >= m.startDate && date < next) {
|
|
467
|
+
monthObj = m;
|
|
468
|
+
dayOfMonth = Math.floor((date - m.startDate) / 864e5) + 1;
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (!monthObj) {
|
|
473
|
+
throw new Error(`Could not determine Sumerian month for ${date.toISOString()}`);
|
|
474
|
+
}
|
|
475
|
+
const observances = [];
|
|
476
|
+
if (dayOfMonth === 7) {
|
|
477
|
+
observances.push({ name: "E\u0161e\u0161", description: "First-quarter moon offering to all household gods." });
|
|
478
|
+
}
|
|
479
|
+
if (dayOfMonth === 15) {
|
|
480
|
+
observances.push({ name: "E\u0161e\u0161", description: "Full moon \u2014 Great Offering to all household gods." });
|
|
481
|
+
}
|
|
482
|
+
if (dayOfMonth === monthObj.lengthDays) {
|
|
483
|
+
observances.push({ name: "Kisiga", description: "New moon \u2014 Funerary offerings and libations for the beloved dead." });
|
|
484
|
+
}
|
|
485
|
+
(monthObj.festivals || []).forEach((f) => {
|
|
486
|
+
if (f.day === dayOfMonth) observances.push(f);
|
|
487
|
+
});
|
|
488
|
+
return {
|
|
489
|
+
gregorianDate: date,
|
|
490
|
+
springGregorianYear: sYear.springGregorianYear,
|
|
491
|
+
cyclePosition: sYear.cyclePosition,
|
|
492
|
+
monthNumber: monthObj.number,
|
|
493
|
+
monthName: monthObj.name,
|
|
494
|
+
monthCuneiform: monthObj.cuneiform,
|
|
495
|
+
monthMeaning: monthObj.meaning,
|
|
496
|
+
monthDescription: monthObj.description,
|
|
497
|
+
dayOfMonth,
|
|
498
|
+
monthLengthDays: monthObj.lengthDays,
|
|
499
|
+
monthStartDate: monthObj.startDate,
|
|
500
|
+
monthEndDate: monthObj.endDate,
|
|
501
|
+
isIntercalaryYear: sYear.isLongYear,
|
|
502
|
+
isIntercalaryMonth: !!monthObj.intercalary,
|
|
503
|
+
observances,
|
|
504
|
+
sumerianYear: sYear,
|
|
505
|
+
toString() {
|
|
506
|
+
const g = date;
|
|
507
|
+
const months2 = [
|
|
508
|
+
"Jan",
|
|
509
|
+
"Feb",
|
|
510
|
+
"Mar",
|
|
511
|
+
"Apr",
|
|
512
|
+
"May",
|
|
513
|
+
"Jun",
|
|
514
|
+
"Jul",
|
|
515
|
+
"Aug",
|
|
516
|
+
"Sep",
|
|
517
|
+
"Oct",
|
|
518
|
+
"Nov",
|
|
519
|
+
"Dec"
|
|
520
|
+
];
|
|
521
|
+
return `Day ${dayOfMonth} of ${monthObj.name} \u2014 Gregorian ${g.getUTCDate()} ${months2[g.getUTCMonth()]} ${g.getUTCFullYear()}`;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
module2.exports = {
|
|
526
|
+
computeSumerianYear: computeSumerianYear2,
|
|
527
|
+
toSumerianDate: toSumerianDate2,
|
|
528
|
+
getCyclePosition: getCyclePosition2,
|
|
529
|
+
LONG_YEAR_POSITIONS,
|
|
530
|
+
NIPPUR_LAT,
|
|
531
|
+
NIPPUR_LON
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// src/index.js
|
|
537
|
+
var { toSumerianDate, computeSumerianYear, getCyclePosition } = require_calendar();
|
|
538
|
+
var { MONTHS, DIRI_\u0160EKINKU, DIRI_KIN_INANA } = require_months();
|
|
539
|
+
var { vernalEquinoxJDE, firstNewMoonAfter, jdToGregorian } = require_astronomy();
|
|
540
|
+
function sumerianDate(date, opts) {
|
|
541
|
+
return toSumerianDate(date, opts);
|
|
542
|
+
}
|
|
543
|
+
function sumerianYear(gregorianYear, opts) {
|
|
544
|
+
if (typeof gregorianYear !== "number") {
|
|
545
|
+
opts = gregorianYear;
|
|
546
|
+
gregorianYear = (/* @__PURE__ */ new Date()).getUTCFullYear();
|
|
547
|
+
}
|
|
548
|
+
return computeSumerianYear(gregorianYear, opts || {});
|
|
549
|
+
}
|
|
550
|
+
function cyclePosition(springGregorianYear) {
|
|
551
|
+
return getCyclePosition(springGregorianYear);
|
|
552
|
+
}
|
|
553
|
+
function vernalEquinox(year) {
|
|
554
|
+
const jde = vernalEquinoxJDE(year);
|
|
555
|
+
const g = jdToGregorian(jde);
|
|
556
|
+
return new Date(Date.UTC(g.year, g.month - 1, g.day, g.hour, g.minute));
|
|
557
|
+
}
|
|
558
|
+
function nextNewMoon(afterDate) {
|
|
559
|
+
const jdEpoch = 24405875e-1;
|
|
560
|
+
const afterJDE = jdEpoch + afterDate.getTime() / 864e5;
|
|
561
|
+
const nmJDE = firstNewMoonAfter(afterJDE);
|
|
562
|
+
const g = jdToGregorian(nmJDE);
|
|
563
|
+
return new Date(Date.UTC(g.year, g.month - 1, g.day, g.hour, g.minute));
|
|
564
|
+
}
|
|
565
|
+
var months = MONTHS;
|
|
566
|
+
var intercalaryMonth = DIRI_\u0160EKINKU;
|
|
567
|
+
var intercalaryMonthYear17 = DIRI_KIN_INANA;
|
|
568
|
+
module.exports = {
|
|
569
|
+
sumerianDate,
|
|
570
|
+
sumerianYear,
|
|
571
|
+
cyclePosition,
|
|
572
|
+
vernalEquinox,
|
|
573
|
+
nextNewMoon,
|
|
574
|
+
months,
|
|
575
|
+
intercalaryMonth,
|
|
576
|
+
intercalaryMonthYear17
|
|
577
|
+
};
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import mod from './index.cjs';
|
|
2
|
+
export const sumerianDate = mod.sumerianDate;
|
|
3
|
+
export const sumerianYear = mod.sumerianYear;
|
|
4
|
+
export const cyclePosition = mod.cyclePosition;
|
|
5
|
+
export const vernalEquinox = mod.vernalEquinox;
|
|
6
|
+
export const nextNewMoon = mod.nextNewMoon;
|
|
7
|
+
export const months = mod.months;
|
|
8
|
+
export const intercalaryMonth = mod.intercalaryMonth;
|
|
9
|
+
export const intercalaryMonthYear17 = mod.intercalaryMonthYear17;
|
|
10
|
+
export default mod;
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jenova-marie/sumerian-date",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Convert Gregorian dates to the Nippur Sumerian ritual calendar",
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.mjs",
|
|
10
|
+
"require": "./dist/index.cjs"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "node build.js",
|
|
18
|
+
"test": "node test/index.test.js",
|
|
19
|
+
"prepublishOnly": "npm test && npm run build"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"sumerian",
|
|
23
|
+
"calendar",
|
|
24
|
+
"nippur",
|
|
25
|
+
"lunisolar",
|
|
26
|
+
"metonic",
|
|
27
|
+
"ancient",
|
|
28
|
+
"mesopotamia",
|
|
29
|
+
"date",
|
|
30
|
+
"astronomy"
|
|
31
|
+
],
|
|
32
|
+
"author": "jenova-marie",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/jenova-marie/sumerian-date.git"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=14"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"esbuild": "^0.27.3"
|
|
43
|
+
}
|
|
44
|
+
}
|