mihrab-methods 0.0.0-stage → 1.0.1
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 +373 -0
- package/README.md +319 -2
- package/certification.json +120 -0
- package/data/corrections/algeria.json +784 -0
- package/data/corrections/diyanet.json +18444 -0
- package/data/corrections/indonesia.json +210 -0
- package/data/corrections/morocco.json +993 -0
- package/data/corrections/sweden.json +516 -0
- package/dist/cjs/algeria.d.ts +4 -0
- package/dist/cjs/algeria.js +22 -0
- package/dist/cjs/authorities/algeria.d.ts +3 -0
- package/dist/cjs/authorities/algeria.js +57 -0
- package/dist/cjs/authorities/diyanet.d.ts +9 -0
- package/dist/cjs/authorities/diyanet.js +90 -0
- package/dist/cjs/authorities/indonesia.d.ts +4 -0
- package/dist/cjs/authorities/indonesia.js +82 -0
- package/dist/cjs/authorities/morocco.d.ts +5 -0
- package/dist/cjs/authorities/morocco.js +65 -0
- package/dist/cjs/authorities/slug.d.ts +2 -0
- package/dist/cjs/authorities/slug.js +17 -0
- package/dist/cjs/authorities/sweden.d.ts +3 -0
- package/dist/cjs/authorities/sweden.js +58 -0
- package/dist/cjs/core/api.d.ts +61 -0
- package/dist/cjs/core/api.js +177 -0
- package/dist/cjs/core/civilDate.d.ts +17 -0
- package/dist/cjs/core/civilDate.js +41 -0
- package/dist/cjs/core/clock.d.ts +22 -0
- package/dist/cjs/core/clock.js +67 -0
- package/dist/cjs/core/compute.d.ts +10 -0
- package/dist/cjs/core/compute.js +59 -0
- package/dist/cjs/core/correctionList.d.ts +25 -0
- package/dist/cjs/core/correctionList.js +62 -0
- package/dist/cjs/core/fetchLatest.d.ts +61 -0
- package/dist/cjs/core/fetchLatest.js +192 -0
- package/dist/cjs/core/index.d.ts +14 -0
- package/dist/cjs/core/index.js +45 -0
- package/dist/cjs/core/registry.d.ts +28 -0
- package/dist/cjs/core/registry.js +34 -0
- package/dist/cjs/core/types.d.ts +193 -0
- package/dist/cjs/core/types.js +22 -0
- package/dist/cjs/core.d.ts +2 -0
- package/dist/cjs/core.js +18 -0
- package/dist/cjs/data/generated/algeriaCertification.d.ts +3 -0
- package/dist/cjs/data/generated/algeriaCertification.js +4 -0
- package/dist/cjs/data/generated/algeriaCities.d.ts +8 -0
- package/dist/cjs/data/generated/algeriaCities.js +5 -0
- package/dist/cjs/data/generated/algeriaCorrections.d.ts +3 -0
- package/dist/cjs/data/generated/algeriaCorrections.js +4 -0
- package/dist/cjs/data/generated/algeriaMethodPoints.d.ts +2 -0
- package/dist/cjs/data/generated/algeriaMethodPoints.js +5 -0
- package/dist/cjs/data/generated/countryOutlines.d.ts +5 -0
- package/dist/cjs/data/generated/countryOutlines.js +5 -0
- package/dist/cjs/data/generated/diyanetCertification.d.ts +3 -0
- package/dist/cjs/data/generated/diyanetCertification.js +4 -0
- package/dist/cjs/data/generated/diyanetCorrections.d.ts +3 -0
- package/dist/cjs/data/generated/diyanetCorrections.js +4 -0
- package/dist/cjs/data/generated/diyanetCountries.d.ts +5 -0
- package/dist/cjs/data/generated/diyanetCountries.js +5 -0
- package/dist/cjs/data/generated/diyanetTurkeyPoints.d.ts +7 -0
- package/dist/cjs/data/generated/diyanetTurkeyPoints.js +5 -0
- package/dist/cjs/data/generated/diyanetWorldPoints.d.ts +10 -0
- package/dist/cjs/data/generated/diyanetWorldPoints.js +5 -0
- package/dist/cjs/data/generated/indonesiaCertification.d.ts +3 -0
- package/dist/cjs/data/generated/indonesiaCertification.js +4 -0
- package/dist/cjs/data/generated/indonesiaCorrections.d.ts +3 -0
- package/dist/cjs/data/generated/indonesiaCorrections.js +4 -0
- package/dist/cjs/data/generated/kemenagMethodPoints.d.ts +2 -0
- package/dist/cjs/data/generated/kemenagMethodPoints.js +5 -0
- package/dist/cjs/data/generated/kemenagPlaces.d.ts +8 -0
- package/dist/cjs/data/generated/kemenagPlaces.js +5 -0
- package/dist/cjs/data/generated/moroccoCertification.d.ts +3 -0
- package/dist/cjs/data/generated/moroccoCertification.js +4 -0
- package/dist/cjs/data/generated/moroccoCities.d.ts +8 -0
- package/dist/cjs/data/generated/moroccoCities.js +5 -0
- package/dist/cjs/data/generated/moroccoCorrections.d.ts +3 -0
- package/dist/cjs/data/generated/moroccoCorrections.js +4 -0
- package/dist/cjs/data/generated/moroccoMethodPoints.d.ts +2 -0
- package/dist/cjs/data/generated/moroccoMethodPoints.js +5 -0
- package/dist/cjs/data/generated/swedenCertification.d.ts +3 -0
- package/dist/cjs/data/generated/swedenCertification.js +4 -0
- package/dist/cjs/data/generated/swedenCorrections.d.ts +3 -0
- package/dist/cjs/data/generated/swedenCorrections.js +4 -0
- package/dist/cjs/data/generated/swedenPlaces.d.ts +5 -0
- package/dist/cjs/data/generated/swedenPlaces.js +5 -0
- package/dist/cjs/diyanet.d.ts +4 -0
- package/dist/cjs/diyanet.js +22 -0
- package/dist/cjs/index.d.ts +19 -0
- package/dist/cjs/index.js +37 -0
- package/dist/cjs/indonesia.d.ts +4 -0
- package/dist/cjs/indonesia.js +22 -0
- package/dist/cjs/locate.d.ts +21 -0
- package/dist/cjs/locate.js +204 -0
- package/dist/cjs/methods/algeria.d.ts +56 -0
- package/dist/cjs/methods/algeria.js +119 -0
- package/dist/cjs/methods/indonesia.d.ts +31 -0
- package/dist/cjs/methods/indonesia.js +94 -0
- package/dist/cjs/methods/morocco.d.ts +61 -0
- package/dist/cjs/methods/morocco.js +113 -0
- package/dist/cjs/methods/revisions.d.ts +15 -0
- package/dist/cjs/methods/revisions.js +18 -0
- package/dist/cjs/methods/scratch-congress.d.ts +87 -0
- package/dist/cjs/methods/scratch-congress.js +539 -0
- package/dist/cjs/methods/sweden.d.ts +88 -0
- package/dist/cjs/methods/sweden.js +568 -0
- package/dist/cjs/morocco.d.ts +4 -0
- package/dist/cjs/morocco.js +22 -0
- package/dist/cjs/sun/preciseSun.d.ts +19 -0
- package/dist/cjs/sun/preciseSun.js +185 -0
- package/dist/cjs/sweden.d.ts +4 -0
- package/dist/cjs/sweden.js +22 -0
- package/dist/esm/algeria.d.ts +4 -0
- package/dist/esm/algeria.js +4 -0
- package/dist/esm/authorities/algeria.d.ts +3 -0
- package/dist/esm/authorities/algeria.js +51 -0
- package/dist/esm/authorities/diyanet.d.ts +9 -0
- package/dist/esm/authorities/diyanet.js +83 -0
- package/dist/esm/authorities/indonesia.d.ts +4 -0
- package/dist/esm/authorities/indonesia.js +75 -0
- package/dist/esm/authorities/morocco.d.ts +5 -0
- package/dist/esm/authorities/morocco.js +59 -0
- package/dist/esm/authorities/slug.d.ts +2 -0
- package/dist/esm/authorities/slug.js +14 -0
- package/dist/esm/authorities/sweden.d.ts +3 -0
- package/dist/esm/authorities/sweden.js +52 -0
- package/dist/esm/core/api.d.ts +61 -0
- package/dist/esm/core/api.js +163 -0
- package/dist/esm/core/civilDate.d.ts +17 -0
- package/dist/esm/core/civilDate.js +36 -0
- package/dist/esm/core/clock.d.ts +22 -0
- package/dist/esm/core/clock.js +60 -0
- package/dist/esm/core/compute.d.ts +10 -0
- package/dist/esm/core/compute.js +56 -0
- package/dist/esm/core/correctionList.d.ts +25 -0
- package/dist/esm/core/correctionList.js +56 -0
- package/dist/esm/core/fetchLatest.d.ts +61 -0
- package/dist/esm/core/fetchLatest.js +184 -0
- package/dist/esm/core/index.d.ts +14 -0
- package/dist/esm/core/index.js +14 -0
- package/dist/esm/core/registry.d.ts +28 -0
- package/dist/esm/core/registry.js +28 -0
- package/dist/esm/core/types.d.ts +193 -0
- package/dist/esm/core/types.js +18 -0
- package/dist/esm/core.d.ts +2 -0
- package/dist/esm/core.js +2 -0
- package/dist/esm/data/generated/algeriaCertification.d.ts +3 -0
- package/dist/esm/data/generated/algeriaCertification.js +2 -0
- package/dist/esm/data/generated/algeriaCities.d.ts +8 -0
- package/dist/esm/data/generated/algeriaCities.js +3 -0
- package/dist/esm/data/generated/algeriaCorrections.d.ts +3 -0
- package/dist/esm/data/generated/algeriaCorrections.js +2 -0
- package/dist/esm/data/generated/algeriaMethodPoints.d.ts +2 -0
- package/dist/esm/data/generated/algeriaMethodPoints.js +3 -0
- package/dist/esm/data/generated/countryOutlines.d.ts +5 -0
- package/dist/esm/data/generated/countryOutlines.js +3 -0
- package/dist/esm/data/generated/diyanetCertification.d.ts +3 -0
- package/dist/esm/data/generated/diyanetCertification.js +2 -0
- package/dist/esm/data/generated/diyanetCorrections.d.ts +3 -0
- package/dist/esm/data/generated/diyanetCorrections.js +2 -0
- package/dist/esm/data/generated/diyanetCountries.d.ts +5 -0
- package/dist/esm/data/generated/diyanetCountries.js +3 -0
- package/dist/esm/data/generated/diyanetTurkeyPoints.d.ts +7 -0
- package/dist/esm/data/generated/diyanetTurkeyPoints.js +3 -0
- package/dist/esm/data/generated/diyanetWorldPoints.d.ts +10 -0
- package/dist/esm/data/generated/diyanetWorldPoints.js +3 -0
- package/dist/esm/data/generated/indonesiaCertification.d.ts +3 -0
- package/dist/esm/data/generated/indonesiaCertification.js +2 -0
- package/dist/esm/data/generated/indonesiaCorrections.d.ts +3 -0
- package/dist/esm/data/generated/indonesiaCorrections.js +2 -0
- package/dist/esm/data/generated/kemenagMethodPoints.d.ts +2 -0
- package/dist/esm/data/generated/kemenagMethodPoints.js +3 -0
- package/dist/esm/data/generated/kemenagPlaces.d.ts +8 -0
- package/dist/esm/data/generated/kemenagPlaces.js +3 -0
- package/dist/esm/data/generated/moroccoCertification.d.ts +3 -0
- package/dist/esm/data/generated/moroccoCertification.js +2 -0
- package/dist/esm/data/generated/moroccoCities.d.ts +8 -0
- package/dist/esm/data/generated/moroccoCities.js +3 -0
- package/dist/esm/data/generated/moroccoCorrections.d.ts +3 -0
- package/dist/esm/data/generated/moroccoCorrections.js +2 -0
- package/dist/esm/data/generated/moroccoMethodPoints.d.ts +2 -0
- package/dist/esm/data/generated/moroccoMethodPoints.js +3 -0
- package/dist/esm/data/generated/swedenCertification.d.ts +3 -0
- package/dist/esm/data/generated/swedenCertification.js +2 -0
- package/dist/esm/data/generated/swedenCorrections.d.ts +3 -0
- package/dist/esm/data/generated/swedenCorrections.js +2 -0
- package/dist/esm/data/generated/swedenPlaces.d.ts +5 -0
- package/dist/esm/data/generated/swedenPlaces.js +3 -0
- package/dist/esm/diyanet.d.ts +4 -0
- package/dist/esm/diyanet.js +4 -0
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.js +19 -0
- package/dist/esm/indonesia.d.ts +4 -0
- package/dist/esm/indonesia.js +4 -0
- package/dist/esm/locate.d.ts +21 -0
- package/dist/esm/locate.js +196 -0
- package/dist/esm/methods/algeria.d.ts +56 -0
- package/dist/esm/methods/algeria.js +114 -0
- package/dist/esm/methods/indonesia.d.ts +31 -0
- package/dist/esm/methods/indonesia.js +90 -0
- package/dist/esm/methods/morocco.d.ts +61 -0
- package/dist/esm/methods/morocco.js +107 -0
- package/dist/esm/methods/revisions.d.ts +15 -0
- package/dist/esm/methods/revisions.js +15 -0
- package/dist/esm/methods/scratch-congress.d.ts +87 -0
- package/dist/esm/methods/scratch-congress.js +534 -0
- package/dist/esm/methods/sweden.d.ts +88 -0
- package/dist/esm/methods/sweden.js +563 -0
- package/dist/esm/morocco.d.ts +4 -0
- package/dist/esm/morocco.js +4 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/sun/preciseSun.d.ts +19 -0
- package/dist/esm/sun/preciseSun.js +181 -0
- package/dist/esm/sweden.d.ts +4 -0
- package/dist/esm/sweden.js +4 -0
- package/docs/methods.md +190 -0
- package/package.json +178 -4
- package/schemas/certification.schema.json +59 -0
- package/schemas/corrections.schema.json +29 -0
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The International Prayer Times Congress method (Istanbul, 2021 — the
|
|
4
|
+
* Diyanet and the European Council for Fatwa and Research) as Diyanet's
|
|
5
|
+
* tables realise it. Islamiska Förbundet's Swedish tables are those
|
|
6
|
+
* tables, row for row, so this is Sweden's method (id 24).
|
|
7
|
+
*
|
|
8
|
+
* The published rules (awqatsalah.com, "Tespit Kriterleri"):
|
|
9
|
+
* - Dhuhr five minutes after transit; Asr one shadow (Dhuhr when the
|
|
10
|
+
* shadow never forms), four minutes late; sunrise seven early,
|
|
11
|
+
* Maghrib seven late ("temkin").
|
|
12
|
+
* - Neither the day nor the night is shorter than five hours.
|
|
13
|
+
* - True Fajr at 18°, true Isha at 16°. Where the 18° dawn no longer
|
|
14
|
+
* forms, the share of the night the sharia night's third took on the
|
|
15
|
+
* last day it did is carried: Isha that share of the night after
|
|
16
|
+
* Maghrib, Fajr the same share scaled by 18/16 before sunrise.
|
|
17
|
+
* - The move from true times to the carried ones is gradual, starting
|
|
18
|
+
* twenty minutes before (Isha) or after (Fajr) the takdir.
|
|
19
|
+
*
|
|
20
|
+
* What the tables turn out to do with them, read off Diyanet's own tables
|
|
21
|
+
* for all 160 Swedish places, 2024–2027 (99.98 % of times on the printed
|
|
22
|
+
* minute, the rest a fraction of a second from the rounding point):
|
|
23
|
+
* - The sun is taken once a day, at 0h UT less 45 s: Meeus's mean
|
|
24
|
+
* elements and equation of the centre, the TRUE (geometric) longitude,
|
|
25
|
+
* the apparent obliquity (mean plus nutation), the equation of time as
|
|
26
|
+
* the mean longitude less the right ascension, 0.106 s later; and
|
|
27
|
+
* two small waves by the mean longitude the formula leaves out: a few
|
|
28
|
+
* hundredths of a second on the transit, a tenth of an arc-second on
|
|
29
|
+
* the declination.
|
|
30
|
+
* - Coordinates are kept to three decimals of a degree.
|
|
31
|
+
* - Asr that never forms is printed at Dhuhr's time.
|
|
32
|
+
* - The night a share is taken of is the day's own: 24 h less the
|
|
33
|
+
* printed day, sunrise to Maghrib.
|
|
34
|
+
* - The five-hour floors hold each end separately, 150 minutes from the
|
|
35
|
+
* printed Dhuhr or from the midnight after it. Where midsummer's
|
|
36
|
+
* night is floored at both ends (to within a minute), that night
|
|
37
|
+
* anchors the season, and the floored times never step back: before
|
|
38
|
+
* midsummer no sunrise earlier than midsummer's and a floored Maghrib
|
|
39
|
+
* no earlier than the day before; after it no sunrise earlier nor
|
|
40
|
+
* Maghrib later than on any day since midsummer — and Fajr and Isha
|
|
41
|
+
* carried the same way.
|
|
42
|
+
* - The gradual transition is a straight line across the days next to
|
|
43
|
+
* the gap on which the true time lies within twenty minutes of the
|
|
44
|
+
* takdir at the gap's edge: twenty minutes away at the far end, the
|
|
45
|
+
* takdir at the edge.
|
|
46
|
+
*
|
|
47
|
+
* Beyond Sweden the same code gives Diyanet's tables worldwide, read off
|
|
48
|
+
* them for places on six continents:
|
|
49
|
+
* - Where the dawn forms all summer but midsummer's true Isha (at 16°)
|
|
50
|
+
* falls later than the share carried from that night, midsummer is the
|
|
51
|
+
* takdir's day — a gap of one day, with its ramps (from about 44.4°
|
|
52
|
+
* north: Austria, central France, northern Bosnia).
|
|
53
|
+
* - Isha is printed at 16° in some countries and 17° in others; the
|
|
54
|
+
* high-latitude rules are worked at 16° either way (`ishaDeg`).
|
|
55
|
+
*
|
|
56
|
+
* Times are minutes past 0h UT of the date, a frame the clock changes
|
|
57
|
+
* cannot bend; `congressTimes` turns them into instants.
|
|
58
|
+
*/
|
|
59
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
|
+
exports.DIYANET_ISHA_DEG = exports.CONGRESS_ISHA_DEG = void 0;
|
|
61
|
+
exports.congressTimes = congressTimes;
|
|
62
|
+
exports.congressYearInfo = congressYearInfo;
|
|
63
|
+
const RAD = Math.PI / 180;
|
|
64
|
+
const DAY_MS = 86_400_000;
|
|
65
|
+
const RISE_SET = -0.833;
|
|
66
|
+
const FAJR_ANGLE = -18;
|
|
67
|
+
/**
|
|
68
|
+
* Isha's depression: the Congress's 16° (Diyanet's in much of Europe,
|
|
69
|
+
* Russia, Central Asia, China and North America), or Diyanet's own 17°
|
|
70
|
+
* (elsewhere). The high-latitude rules are the Congress's at 16° either way;
|
|
71
|
+
* the angle sets only the true Isha printed.
|
|
72
|
+
*/
|
|
73
|
+
exports.CONGRESS_ISHA_DEG = 16;
|
|
74
|
+
exports.DIYANET_ISHA_DEG = 17;
|
|
75
|
+
const TEMKIN = { sunrise: -7, dhuhr: 5, asr: 4, maghrib: 7 };
|
|
76
|
+
/** Minutes: the day and the night are never shorter. */
|
|
77
|
+
const FLOOR = 300;
|
|
78
|
+
/** Minutes: the gradual transition's reach. */
|
|
79
|
+
const BAND = 20;
|
|
80
|
+
/** Minutes: a midsummer night this close to the five-hour floor counts as floored. */
|
|
81
|
+
const ANCHOR_SLACK = 1;
|
|
82
|
+
/** Days to look for a dawn or a transition before giving up. */
|
|
83
|
+
const SEARCH_DAYS = 200;
|
|
84
|
+
const dayKeyOf = (y, m, d) => Date.UTC(y, m, d) / DAY_MS;
|
|
85
|
+
const yearOf = (k) => new Date(k * DAY_MS).getUTCFullYear();
|
|
86
|
+
const midsummerOf = (k) => dayKeyOf(yearOf(k), 5, 21);
|
|
87
|
+
/** Seconds before 0h UT at which Diyanet takes the day's sun. */
|
|
88
|
+
const SUN_INSTANT_S = -45;
|
|
89
|
+
/** Minutes Diyanet's equation of time runs ahead of the formula below. */
|
|
90
|
+
const EOT_ADD_MIN = 0.00176;
|
|
91
|
+
/**
|
|
92
|
+
* Seconds Diyanet's transit runs later than the formula below, by the sun's
|
|
93
|
+
* mean longitude: an annual wave of a few hundredths of a second, read off
|
|
94
|
+
* every Dhuhr of Diyanet's Swedish tables 2024–2027 (the largest margin that
|
|
95
|
+
* leaves none of them off; the two halves of the span give the same wave).
|
|
96
|
+
*/
|
|
97
|
+
function eotResidualS(L) {
|
|
98
|
+
return (0.033377 * Math.sin(L) + 0.007721 * Math.cos(L) -
|
|
99
|
+
0.000229 * Math.sin(2 * L) + 0.004198 * Math.cos(2 * L) -
|
|
100
|
+
0.02346 * Math.sin(3 * L) - 0.026434 * Math.cos(3 * L));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Degrees Diyanet's declination runs above the formula below: a wave of a
|
|
104
|
+
* tenth of an arc-second by the sun's mean longitude, read off the times of
|
|
105
|
+
* Diyanet's Swedish tables 2024–2027 that sit at a minute's edge (fitted on
|
|
106
|
+
* either two years, it holds on the other two).
|
|
107
|
+
*/
|
|
108
|
+
function decResidualDeg(L) {
|
|
109
|
+
return -1.1539e-5 - 3.6174e-5 * Math.sin(L) - 2.1101e-5 * Math.cos(L) + 2.0235e-5 * Math.sin(2 * L) - 2.2534e-5 * Math.cos(2 * L);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Declination (radians) and equation of time (minutes), as Diyanet's tables
|
|
113
|
+
* take them: Meeus's mean elements, the true longitude, the apparent obliquity.
|
|
114
|
+
*/
|
|
115
|
+
function sunAt(utcMs) {
|
|
116
|
+
const T = (utcMs / DAY_MS - 10957.5) / 36525; // Julian centuries since J2000.0
|
|
117
|
+
const L0 = (((280.46646 + T * (36000.76983 + 0.0003032 * T)) % 360) + 360) % 360;
|
|
118
|
+
const M = (357.52911 + T * (35999.05029 - 0.0001537 * T)) * RAD;
|
|
119
|
+
const C = (1.914602 - T * (0.004817 + 0.000014 * T)) * Math.sin(M) +
|
|
120
|
+
(0.019993 - 0.000101 * T) * Math.sin(2 * M) +
|
|
121
|
+
0.000289 * Math.sin(3 * M);
|
|
122
|
+
const om = (125.04 - 1934.136 * T) * RAD;
|
|
123
|
+
const Ls = (280.4665 + 36000.7698 * T) * RAD;
|
|
124
|
+
const Lm = (218.3165 + 481267.8813 * T) * RAD;
|
|
125
|
+
const eps = 23 +
|
|
126
|
+
(26 + (21.448 - T * (46.815 + T * (0.00059 - T * 0.001813))) / 60) / 60 +
|
|
127
|
+
(9.2 * Math.cos(om) + 0.57 * Math.cos(2 * Ls) + 0.1 * Math.cos(2 * Lm) - 0.09 * Math.cos(2 * om)) / 3600;
|
|
128
|
+
const lam = (L0 + C) * RAD;
|
|
129
|
+
const ra = ((((Math.atan2(Math.cos(eps * RAD) * Math.sin(lam), Math.cos(lam)) / RAD) % 360) + 360) % 360);
|
|
130
|
+
const dec = Math.asin(Math.sin(eps * RAD) * Math.sin(lam)) + decResidualDeg(L0 * RAD) * RAD;
|
|
131
|
+
const eot = (((((L0 - ra + 180) % 360) + 360) % 360) - 180) * 4 + EOT_ADD_MIN - eotResidualS(L0 * RAD) / 60;
|
|
132
|
+
return { dec, eot };
|
|
133
|
+
}
|
|
134
|
+
/** One day's sun: transit and the crossings, minutes past the day's 0h UT. */
|
|
135
|
+
class Solar {
|
|
136
|
+
day;
|
|
137
|
+
lat;
|
|
138
|
+
lon;
|
|
139
|
+
dec;
|
|
140
|
+
transit;
|
|
141
|
+
constructor(day, lat, lon) {
|
|
142
|
+
this.day = day;
|
|
143
|
+
this.lat = lat;
|
|
144
|
+
this.lon = lon;
|
|
145
|
+
const { dec, eot } = sunAt(day * DAY_MS + SUN_INSTANT_S * 1000);
|
|
146
|
+
this.dec = dec;
|
|
147
|
+
this.transit = 720 - 4 * lon - eot;
|
|
148
|
+
}
|
|
149
|
+
hourAngle(alt) {
|
|
150
|
+
const c = (Math.sin(alt * RAD) - Math.sin(this.lat * RAD) * Math.sin(this.dec)) /
|
|
151
|
+
(Math.cos(this.lat * RAD) * Math.cos(this.dec));
|
|
152
|
+
if (c < -1 || c > 1)
|
|
153
|
+
return null;
|
|
154
|
+
return (Math.acos(c) / RAD) * 4;
|
|
155
|
+
}
|
|
156
|
+
rising(alt) {
|
|
157
|
+
const h = this.hourAngle(alt);
|
|
158
|
+
return h === null ? null : this.transit - h;
|
|
159
|
+
}
|
|
160
|
+
setting(alt) {
|
|
161
|
+
const h = this.hourAngle(alt);
|
|
162
|
+
return h === null ? null : this.transit + h;
|
|
163
|
+
}
|
|
164
|
+
/** Asr: the shadow of a thing is its noon shadow plus `shadow` lengths. */
|
|
165
|
+
asr(shadow) {
|
|
166
|
+
const noonAlt = 90 - Math.abs(this.lat - this.dec / RAD);
|
|
167
|
+
if (noonAlt <= 0)
|
|
168
|
+
return null;
|
|
169
|
+
const alt = Math.atan(1 / (shadow + Math.tan((90 - noonAlt) * RAD))) / RAD;
|
|
170
|
+
return this.setting(alt);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/** The method for one place and one year; everything it needs of the year is worked out once. */
|
|
174
|
+
class CongressYear {
|
|
175
|
+
lat;
|
|
176
|
+
lon;
|
|
177
|
+
year;
|
|
178
|
+
clockOffset;
|
|
179
|
+
solars = new Map();
|
|
180
|
+
riseSets = new Map();
|
|
181
|
+
ratioValue;
|
|
182
|
+
gap;
|
|
183
|
+
floors;
|
|
184
|
+
ramps = new Map();
|
|
185
|
+
extremes = new Map();
|
|
186
|
+
carriedCache = new Map();
|
|
187
|
+
ishaAngle;
|
|
188
|
+
/**
|
|
189
|
+
* `clockOffset`: minutes east of UTC of the clock the table is printed in,
|
|
190
|
+
* when known. Diyanet walks the gradual transition on that clock, which
|
|
191
|
+
* matters only where the true time just past the gap falls on the other
|
|
192
|
+
* side of local midnight from the takdir (far east of a zone's meridian,
|
|
193
|
+
* as at Aihui): see `ramp`.
|
|
194
|
+
*/
|
|
195
|
+
constructor(lat, lon, year, ishaDeg = exports.CONGRESS_ISHA_DEG, clockOffset) {
|
|
196
|
+
this.lat = lat;
|
|
197
|
+
this.lon = lon;
|
|
198
|
+
this.year = year;
|
|
199
|
+
this.clockOffset = clockOffset;
|
|
200
|
+
this.ishaAngle = -ishaDeg;
|
|
201
|
+
}
|
|
202
|
+
solar(day) {
|
|
203
|
+
let s = this.solars.get(day);
|
|
204
|
+
if (!s) {
|
|
205
|
+
s = new Solar(day, this.lat, this.lon);
|
|
206
|
+
this.solars.set(day, s);
|
|
207
|
+
}
|
|
208
|
+
return s;
|
|
209
|
+
}
|
|
210
|
+
/** Printed (temkin) sunrise and Maghrib with the five-hour floors. */
|
|
211
|
+
riseSet(day) {
|
|
212
|
+
const cached = this.riseSets.get(day);
|
|
213
|
+
if (cached)
|
|
214
|
+
return cached;
|
|
215
|
+
const s = this.solar(day);
|
|
216
|
+
const dhuhr = s.transit + TEMKIN.dhuhr;
|
|
217
|
+
const half = FLOOR / 2;
|
|
218
|
+
const rawSr = s.rising(RISE_SET);
|
|
219
|
+
const rawSs = s.setting(RISE_SET);
|
|
220
|
+
// the night no shorter than five hours, 2.5 h either side of the midnight after the printed
|
|
221
|
+
// Dhuhr — or, where midsummer's night is floored at both ends, of the season's anchoring
|
|
222
|
+
// Dhuhr (dhuhrExtremes): the floored times never step back
|
|
223
|
+
let nsr;
|
|
224
|
+
let nss;
|
|
225
|
+
if (this.midsummerFloors(day)) {
|
|
226
|
+
const [hi, lo] = this.dhuhrExtremes(day);
|
|
227
|
+
nsr = hi - 720 + half;
|
|
228
|
+
nss = lo + 720 - half;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
nsr = dhuhr - 720 + half;
|
|
232
|
+
nss = dhuhr + 720 - half;
|
|
233
|
+
}
|
|
234
|
+
let sr;
|
|
235
|
+
let ss;
|
|
236
|
+
if (rawSr === null || rawSs === null) {
|
|
237
|
+
// the sun neither rises nor sets: midnight sun (up at noon) or polar night
|
|
238
|
+
const noonUp = 90 - Math.abs(this.lat - s.dec / RAD) > RISE_SET;
|
|
239
|
+
[sr, ss] = noonUp ? [nsr, nss] : [dhuhr - half, dhuhr + half];
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
sr = rawSr + TEMKIN.sunrise;
|
|
243
|
+
ss = rawSs + TEMKIN.maghrib;
|
|
244
|
+
}
|
|
245
|
+
// the day no shorter than five hours about the printed Dhuhr, each end on its own; then the night
|
|
246
|
+
sr = Math.max(Math.min(sr, dhuhr - half), nsr);
|
|
247
|
+
ss = Math.min(Math.max(ss, dhuhr + half), nss);
|
|
248
|
+
// where midsummer anchors the season, Maghrib is held at the latest since midsummer until it
|
|
249
|
+
// falls of itself (Torsby, whose midsummer night is just over five hours: its sunset still
|
|
250
|
+
// gets later for a few days after the solstice, and the table holds midsummer's Maghrib)
|
|
251
|
+
let held;
|
|
252
|
+
if (this.midsummerFloors(day)) {
|
|
253
|
+
const mid = midsummerOf(day);
|
|
254
|
+
if (day === mid)
|
|
255
|
+
held = true;
|
|
256
|
+
else if (day > mid) {
|
|
257
|
+
const prev = this.riseSet(day - 1);
|
|
258
|
+
if (prev.held && ss > prev.ss) {
|
|
259
|
+
ss = prev.ss;
|
|
260
|
+
held = true;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const rs = { sr, ss, held };
|
|
265
|
+
this.riseSets.set(day, rs);
|
|
266
|
+
return rs;
|
|
267
|
+
}
|
|
268
|
+
dhuhrOf(day) {
|
|
269
|
+
return this.solar(day).transit + TEMKIN.dhuhr;
|
|
270
|
+
}
|
|
271
|
+
/** Does the day's Maghrib fall on the night's floor (or the sun not set at all)? */
|
|
272
|
+
maghribFloored(day) {
|
|
273
|
+
const s = this.solar(day);
|
|
274
|
+
const st = s.setting(RISE_SET);
|
|
275
|
+
return st === null || st + TEMKIN.maghrib > s.transit + TEMKIN.dhuhr + 720 - FLOOR / 2;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* The Dhuhrs the anchored night floors go by: [latest, earliest]. Before
|
|
279
|
+
* midsummer, sunrise is held against midsummer's Dhuhr and a floored
|
|
280
|
+
* Maghrib against the latest Dhuhr since its floor began; after it, every
|
|
281
|
+
* Dhuhr from midsummer on — so the floored times never step back.
|
|
282
|
+
*/
|
|
283
|
+
dhuhrExtremes(day) {
|
|
284
|
+
const cached = this.extremes.get(day);
|
|
285
|
+
if (cached)
|
|
286
|
+
return cached;
|
|
287
|
+
const mid = midsummerOf(day);
|
|
288
|
+
let out;
|
|
289
|
+
if (day <= mid) {
|
|
290
|
+
let maxRun = this.dhuhrOf(day);
|
|
291
|
+
if (this.maghribFloored(day)) {
|
|
292
|
+
for (let d = day - 1; d > day - 120 && this.maghribFloored(d); d -= 1)
|
|
293
|
+
maxRun = Math.max(maxRun, this.dhuhrOf(d));
|
|
294
|
+
}
|
|
295
|
+
out = [Math.max(this.dhuhrOf(day), this.dhuhrOf(mid)), Math.min(maxRun, this.dhuhrOf(mid))];
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
let hi = -Infinity;
|
|
299
|
+
let lo = Infinity;
|
|
300
|
+
for (let d = mid; d <= day; d += 1) {
|
|
301
|
+
const v = this.dhuhrOf(d);
|
|
302
|
+
hi = Math.max(hi, v);
|
|
303
|
+
lo = Math.min(lo, v);
|
|
304
|
+
}
|
|
305
|
+
out = [hi, lo];
|
|
306
|
+
}
|
|
307
|
+
this.extremes.set(day, out);
|
|
308
|
+
return out;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Is midsummer's night floored at both ends — the day's own floors
|
|
312
|
+
* leaving it five hours, or within a minute of five (Torsby's 300.5 is
|
|
313
|
+
* anchored, Fagersta's 302 is not)? Then that night anchors the season.
|
|
314
|
+
*/
|
|
315
|
+
midsummerFloors(day) {
|
|
316
|
+
if (this.floors === undefined) {
|
|
317
|
+
const s = this.solar(midsummerOf(day));
|
|
318
|
+
const sr = s.rising(RISE_SET);
|
|
319
|
+
const ss = s.setting(RISE_SET);
|
|
320
|
+
const dhuhr = s.transit + TEMKIN.dhuhr;
|
|
321
|
+
const half = FLOOR / 2;
|
|
322
|
+
if (sr === null || ss === null)
|
|
323
|
+
this.floors = true;
|
|
324
|
+
else {
|
|
325
|
+
const psr = Math.max(sr + TEMKIN.sunrise, dhuhr - 720 + half);
|
|
326
|
+
const pss = Math.min(ss + TEMKIN.maghrib, dhuhr + 720 - half);
|
|
327
|
+
this.floors = 1440 - (pss - psr) <= FLOOR + ANCHOR_SLACK;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return this.floors;
|
|
331
|
+
}
|
|
332
|
+
/** The day's night: 24 h less the printed day. */
|
|
333
|
+
night(day) {
|
|
334
|
+
const { sr, ss } = this.riseSet(day);
|
|
335
|
+
return 1440 - (ss - sr);
|
|
336
|
+
}
|
|
337
|
+
fajr18(day) {
|
|
338
|
+
return this.solar(day).rising(FAJR_ANGLE);
|
|
339
|
+
}
|
|
340
|
+
isha16(day) {
|
|
341
|
+
return this.solar(day).setting(this.ishaAngle);
|
|
342
|
+
}
|
|
343
|
+
trueTime(key, day) {
|
|
344
|
+
return key === 'fajr' ? this.fajr18(day) : this.isha16(day);
|
|
345
|
+
}
|
|
346
|
+
/** First and last day on which the 18° dawn does not form, or null when it forms all year. */
|
|
347
|
+
gapDays() {
|
|
348
|
+
if (this.gap !== undefined)
|
|
349
|
+
return this.gap;
|
|
350
|
+
const mid = dayKeyOf(this.year, 5, 21);
|
|
351
|
+
if (this.fajr18(mid) !== null) {
|
|
352
|
+
// The dawn forms all summer, but where midsummer's true Isha falls
|
|
353
|
+
// later than the share carried from that night would put it, Diyanet
|
|
354
|
+
// takes midsummer as the takdir's day and ramps to it as at a gap's
|
|
355
|
+
// edge (Austria, central France, northern Bosnia — from about 44.4°).
|
|
356
|
+
// The rule is the northern summer's; south of the equator the true
|
|
357
|
+
// times stand.
|
|
358
|
+
// (at the Congress's 16°, whatever Isha's printed angle)
|
|
359
|
+
const isha = this.solar(mid).setting(-exports.CONGRESS_ISHA_DEG);
|
|
360
|
+
this.gap = this.lat > 0 && isha !== null && this.carriedRaw(mid)[1] < isha ? [mid, mid] : null;
|
|
361
|
+
return this.gap;
|
|
362
|
+
}
|
|
363
|
+
let a = mid;
|
|
364
|
+
while (this.fajr18(a - 1) === null && mid - a < SEARCH_DAYS)
|
|
365
|
+
a -= 1;
|
|
366
|
+
let b = mid;
|
|
367
|
+
while (this.fajr18(b + 1) === null && b - mid < SEARCH_DAYS)
|
|
368
|
+
b += 1;
|
|
369
|
+
this.gap = [a, b];
|
|
370
|
+
return this.gap;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* The carried ratio: a third of the sharia night (this day's Maghrib to
|
|
374
|
+
* the next dawn — the last one, a day on) over the day's night, on the
|
|
375
|
+
* last day before midsummer on which the 18° dawn forms.
|
|
376
|
+
*/
|
|
377
|
+
ratio() {
|
|
378
|
+
if (this.ratioValue !== undefined)
|
|
379
|
+
return this.ratioValue;
|
|
380
|
+
let d = dayKeyOf(this.year, 5, 21);
|
|
381
|
+
let f = this.fajr18(d);
|
|
382
|
+
let steps = 0;
|
|
383
|
+
while (f === null && steps < SEARCH_DAYS) {
|
|
384
|
+
d -= 1;
|
|
385
|
+
f = this.fajr18(d);
|
|
386
|
+
steps += 1;
|
|
387
|
+
}
|
|
388
|
+
if (f === null) {
|
|
389
|
+
this.ratioValue = null;
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
const { ss } = this.riseSet(d);
|
|
393
|
+
const S = f + 1440 - ss;
|
|
394
|
+
this.ratioValue = S / 3 / this.night(d);
|
|
395
|
+
return this.ratioValue;
|
|
396
|
+
}
|
|
397
|
+
/** Fajr and Isha from the carried ratio, with midsummer's as the bound where its floors are in force. */
|
|
398
|
+
/** Fajr and Isha from the carried share, before any season rule. */
|
|
399
|
+
carriedRaw(day) {
|
|
400
|
+
const r = this.ratio() ?? 0;
|
|
401
|
+
const { sr, ss } = this.riseSet(day);
|
|
402
|
+
const n = this.night(day);
|
|
403
|
+
return [sr - r * (FAJR_ANGLE / -exports.CONGRESS_ISHA_DEG) * n, ss + r * n];
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Fajr and Isha from the carried share. Where midsummer's night anchors
|
|
407
|
+
* the season: before midsummer never an earlier Fajr nor a later Isha than
|
|
408
|
+
* midsummer's; after it, than on any day since — as the floored sunrise.
|
|
409
|
+
*/
|
|
410
|
+
carried(day) {
|
|
411
|
+
const cached = this.carriedCache.get(day);
|
|
412
|
+
if (cached)
|
|
413
|
+
return cached;
|
|
414
|
+
const mid = midsummerOf(day);
|
|
415
|
+
let out;
|
|
416
|
+
if (!this.midsummerFloors(day) || day === mid)
|
|
417
|
+
out = this.carriedRaw(day);
|
|
418
|
+
else if (day < mid) {
|
|
419
|
+
const [f, i] = this.carriedRaw(day);
|
|
420
|
+
const [mf, mi] = this.carried(mid);
|
|
421
|
+
out = [Math.max(f, mf), Math.min(i, mi)];
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
// walk forward from midsummer so the running bound needs no deep recursion
|
|
425
|
+
let prev = this.carried(mid);
|
|
426
|
+
for (let d = mid + 1; d < day; d += 1) {
|
|
427
|
+
let c = this.carriedCache.get(d);
|
|
428
|
+
if (!c) {
|
|
429
|
+
const [f, i] = this.carriedRaw(d);
|
|
430
|
+
c = [Math.max(f, prev[0]), Math.min(i, prev[1])];
|
|
431
|
+
this.carriedCache.set(d, c);
|
|
432
|
+
}
|
|
433
|
+
prev = c;
|
|
434
|
+
}
|
|
435
|
+
const [f, i] = this.carriedRaw(day);
|
|
436
|
+
out = [Math.max(f, prev[0]), Math.min(i, prev[1])];
|
|
437
|
+
}
|
|
438
|
+
this.carriedCache.set(day, out);
|
|
439
|
+
return out;
|
|
440
|
+
}
|
|
441
|
+
/** The gradual transition between the true time and the takdir. */
|
|
442
|
+
ramp(day, side, key) {
|
|
443
|
+
const gap = this.gapDays();
|
|
444
|
+
if (!gap)
|
|
445
|
+
return this.trueTime(key, day);
|
|
446
|
+
const [d1, d2] = gap;
|
|
447
|
+
const idx = key === 'fajr' ? 0 : 1;
|
|
448
|
+
const cacheKey = side + key;
|
|
449
|
+
let ramp = this.ramps.get(cacheKey);
|
|
450
|
+
if (!ramp) {
|
|
451
|
+
const edge = side === 'in' ? d1 : d2;
|
|
452
|
+
const T = this.carried(edge)[idx];
|
|
453
|
+
const step = side === 'in' ? -1 : 1;
|
|
454
|
+
let far = null;
|
|
455
|
+
// On the table's clock, a true time just after the gap that lands on the
|
|
456
|
+
// other side of local midnight from the takdir is already past the band
|
|
457
|
+
// (Fajr after the gap only — before it, and for Isha, the transition is walked as ever):
|
|
458
|
+
// there is no transition, the gap's last day is printed the band away
|
|
459
|
+
// from the takdir, and the true times follow (Diyanet's tables at Aihui).
|
|
460
|
+
const first = this.trueTime(key, edge + step);
|
|
461
|
+
const localDay = (m) => Math.floor((m + (this.clockOffset ?? 0)) / 1440);
|
|
462
|
+
const wrapped = side === 'out' && key === 'fajr' && this.clockOffset !== undefined && first !== null && localDay(first) !== localDay(T);
|
|
463
|
+
// walking away from the gap the true time starts far beyond T, enters the
|
|
464
|
+
// band and leaves it again; the far end is the last day of that run
|
|
465
|
+
for (let d = edge + step; !wrapped && Math.abs(d - edge) < SEARCH_DAYS; d += step) {
|
|
466
|
+
const t = this.trueTime(key, d);
|
|
467
|
+
if (t !== null && Math.abs(t - T) <= BAND)
|
|
468
|
+
far = d;
|
|
469
|
+
else if (far !== null)
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
ramp = { edge, T, far, bump: wrapped };
|
|
473
|
+
this.ramps.set(cacheKey, ramp);
|
|
474
|
+
}
|
|
475
|
+
const { edge, T, far } = ramp;
|
|
476
|
+
if (far === null)
|
|
477
|
+
return this.trueTime(key, day);
|
|
478
|
+
const inside = side === 'in' ? far <= day && day < edge : edge < day && day <= far;
|
|
479
|
+
if (!inside)
|
|
480
|
+
return this.trueTime(key, day);
|
|
481
|
+
const sign = key === 'fajr' ? 1 : -1; // Fajr sits later than the takdir, Isha earlier
|
|
482
|
+
return T + (sign * BAND * Math.abs(day - edge)) / Math.abs(far - edge);
|
|
483
|
+
}
|
|
484
|
+
/** The day's six times, minutes past its 0h UT. */
|
|
485
|
+
times(day, asrShadow) {
|
|
486
|
+
const s = this.solar(day);
|
|
487
|
+
const { sr, ss } = this.riseSet(day);
|
|
488
|
+
const dhuhr = s.transit + TEMKIN.dhuhr;
|
|
489
|
+
const rawAsr = s.asr(asrShadow);
|
|
490
|
+
// an Asr that never forms is printed at Dhuhr's time (the published rule)
|
|
491
|
+
let asr = rawAsr === null ? dhuhr : rawAsr + TEMKIN.asr;
|
|
492
|
+
asr = Math.max(dhuhr, Math.min(asr, ss));
|
|
493
|
+
let fajr = this.fajr18(day);
|
|
494
|
+
let isha = this.isha16(day);
|
|
495
|
+
const gap = this.gapDays();
|
|
496
|
+
if (gap) {
|
|
497
|
+
const [d1, d2] = gap;
|
|
498
|
+
if (d1 <= day && day <= d2) {
|
|
499
|
+
[fajr, isha] = this.carried(day);
|
|
500
|
+
// the gap's edge where the transition is skipped (`ramp`): the band away
|
|
501
|
+
if (day === d1 || day === d2) {
|
|
502
|
+
const side = day === d1 ? 'in' : 'out';
|
|
503
|
+
this.ramp(day, side, 'fajr');
|
|
504
|
+
this.ramp(day, side, 'isha');
|
|
505
|
+
if (this.ramps.get(side + 'fajr')?.bump && fajr !== null)
|
|
506
|
+
fajr += BAND;
|
|
507
|
+
if (this.ramps.get(side + 'isha')?.bump && isha !== null)
|
|
508
|
+
isha -= BAND;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
else if (day < d1) {
|
|
512
|
+
fajr = this.ramp(day, 'in', 'fajr');
|
|
513
|
+
isha = this.ramp(day, 'in', 'isha');
|
|
514
|
+
}
|
|
515
|
+
else {
|
|
516
|
+
fajr = this.ramp(day, 'out', 'fajr');
|
|
517
|
+
isha = this.ramp(day, 'out', 'isha');
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
fajr: fajr ?? sr - 60,
|
|
522
|
+
sunrise: sr,
|
|
523
|
+
dhuhr,
|
|
524
|
+
asr,
|
|
525
|
+
maghrib: ss,
|
|
526
|
+
isha: isha ?? ss + 60,
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
const years = new Map();
|
|
531
|
+
const MAX_CACHED_YEARS = 12;
|
|
532
|
+
function yearFor(lat, lon, year, ishaDeg = exports.CONGRESS_ISHA_DEG, clockOffset) {
|
|
533
|
+
const key = `${lat.toFixed(5)},${lon.toFixed(5)},${year},${ishaDeg},${clockOffset ?? ''}`;
|
|
534
|
+
let cy = years.get(key);
|
|
535
|
+
if (!cy) {
|
|
536
|
+
if (years.size >= MAX_CACHED_YEARS)
|
|
537
|
+
years.delete(years.keys().next().value);
|
|
538
|
+
cy = new CongressYear(lat, lon, year, ishaDeg, clockOffset);
|
|
539
|
+
years.set(key, cy);
|
|
540
|
+
}
|
|
541
|
+
return cy;
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* The Congress method's times for a calendar date (year, month 0–11, day),
|
|
545
|
+
* as instants, unrounded. `asrShadow` is 1 for the standard Asr, 2 for the
|
|
546
|
+
* Hanafi one; the tables print the standard. `ishaDeg` is Isha's depression:
|
|
547
|
+
* 16° (the Congress's, Diyanet's in Europe and North America) or 17°
|
|
548
|
+
* (Diyanet's everywhere else). `clockOffset` is the table's clock, minutes
|
|
549
|
+
* east of UTC (its standard time), where known — see CongressYear.
|
|
550
|
+
*/
|
|
551
|
+
function congressTimes(latitude, longitude, year, month, day, asrShadow = 1, ishaDeg = exports.CONGRESS_ISHA_DEG, clockOffset) {
|
|
552
|
+
const key = dayKeyOf(year, month, day);
|
|
553
|
+
const t = yearFor(latitude, longitude, year, ishaDeg, clockOffset).times(key, asrShadow);
|
|
554
|
+
const start = key * DAY_MS;
|
|
555
|
+
const at = (m) => new Date(start + m * 60_000);
|
|
556
|
+
return { fajr: at(t.fajr), sunrise: at(t.sunrise), dhuhr: at(t.dhuhr), asr: at(t.asr), maghrib: at(t.maghrib), isha: at(t.isha) };
|
|
557
|
+
}
|
|
558
|
+
/** For tests and the verification tool: the year's structure as the method sees it. */
|
|
559
|
+
function congressYearInfo(latitude, longitude, year) {
|
|
560
|
+
const cy = yearFor(latitude, longitude, year);
|
|
561
|
+
const iso = (k) => new Date(k * DAY_MS).toISOString().slice(0, 10);
|
|
562
|
+
const gap = cy.gapDays();
|
|
563
|
+
return {
|
|
564
|
+
gap: gap ? [iso(gap[0]), iso(gap[1])] : null,
|
|
565
|
+
ratio: cy.ratio(),
|
|
566
|
+
midsummerFloors: cy.midsummerFloors(dayKeyOf(year, 5, 21)),
|
|
567
|
+
};
|
|
568
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.places = void 0;
|
|
18
|
+
/** mihrab-methods/morocco — the morocco method with its places and correction list, and nothing else's. */
|
|
19
|
+
require("./authorities/morocco.js");
|
|
20
|
+
__exportStar(require("./core/index.js"), exports);
|
|
21
|
+
var morocco_js_1 = require("./authorities/morocco.js");
|
|
22
|
+
Object.defineProperty(exports, "places", { enumerable: true, get: function () { return morocco_js_1.places; } });
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A precise apparent Sun: the Earth's VSOP87 series (truncated), IAU 2006
|
|
3
|
+
* precession, IAU 2000B nutation and light time, after Don Cross's
|
|
4
|
+
* Astronomy Engine (MIT licence). It agrees with JPL DE421 to about 0.05 s
|
|
5
|
+
* in the equation of time and 0.5″ in declination, where Meeus's short
|
|
6
|
+
* series (`meeusApparentSun`) drifts by about a second over the year —
|
|
7
|
+
* enough to move a published minute.
|
|
8
|
+
*/
|
|
9
|
+
/** ΔT (s), Espenak & Meeus, for UT days from J2000 — held at its 2017 value onward (about 69 s, as observed), as JPL Horizons does. */
|
|
10
|
+
export declare function deltaT(ut: number): number;
|
|
11
|
+
/**
|
|
12
|
+
* The apparent Sun at `d` days from J2000.0 (UT): declination (rad) and
|
|
13
|
+
* equation of time (minutes), such that the transit at longitude λ (east) is
|
|
14
|
+
* 720 − 4λ − eot minutes UT. Same contract as `meeusApparentSun`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function preciseApparentSun(d: number): {
|
|
17
|
+
dec: number;
|
|
18
|
+
eot: number;
|
|
19
|
+
};
|