mihrab-methods 1.2.0 → 1.3.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/README.md +5 -3
- package/certification.json +30 -7
- package/data/corrections/diyanet.json +455 -0
- package/data/corrections/turkiyetakvimi.json +120 -0
- package/dist/cjs/authorities/turkiyeTakvimi.d.ts +3 -0
- package/dist/cjs/authorities/turkiyeTakvimi.js +59 -0
- package/dist/cjs/core/compute.js +6 -2
- package/dist/cjs/core/types.d.ts +3 -1
- package/dist/cjs/core/types.js +1 -1
- package/dist/cjs/data/generated/diyanetCertification.js +1 -1
- package/dist/cjs/data/generated/diyanetCorrections.js +1 -1
- package/dist/cjs/data/generated/diyanetWorldPoints.js +1 -1
- package/dist/cjs/data/generated/turkiyeTakvimiCities.d.ts +8 -0
- package/dist/cjs/data/generated/turkiyeTakvimiCities.js +5 -0
- package/dist/cjs/data/generated/turkiyetakvimiCertification.d.ts +3 -0
- package/dist/cjs/data/generated/turkiyetakvimiCertification.js +4 -0
- package/dist/cjs/data/generated/turkiyetakvimiCorrections.d.ts +3 -0
- package/dist/cjs/data/generated/turkiyetakvimiCorrections.js +4 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/methods/revisions.d.ts +1 -0
- package/dist/cjs/methods/revisions.js +1 -0
- package/dist/cjs/methods/turkiyeTakvimi.d.ts +42 -0
- package/dist/cjs/methods/turkiyeTakvimi.js +166 -0
- package/dist/cjs/turkiyetakvimi.d.ts +4 -0
- package/dist/cjs/turkiyetakvimi.js +22 -0
- package/dist/esm/authorities/turkiyeTakvimi.d.ts +3 -0
- package/dist/esm/authorities/turkiyeTakvimi.js +53 -0
- package/dist/esm/core/compute.js +6 -2
- package/dist/esm/core/types.d.ts +3 -1
- package/dist/esm/core/types.js +1 -1
- package/dist/esm/data/generated/diyanetCertification.js +1 -1
- package/dist/esm/data/generated/diyanetCorrections.js +1 -1
- package/dist/esm/data/generated/diyanetWorldPoints.js +1 -1
- package/dist/esm/data/generated/turkiyeTakvimiCities.d.ts +8 -0
- package/dist/esm/data/generated/turkiyeTakvimiCities.js +3 -0
- package/dist/esm/data/generated/turkiyetakvimiCertification.d.ts +3 -0
- package/dist/esm/data/generated/turkiyetakvimiCertification.js +2 -0
- package/dist/esm/data/generated/turkiyetakvimiCorrections.d.ts +3 -0
- package/dist/esm/data/generated/turkiyetakvimiCorrections.js +2 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/methods/revisions.d.ts +1 -0
- package/dist/esm/methods/revisions.js +1 -0
- package/dist/esm/methods/turkiyeTakvimi.d.ts +42 -0
- package/dist/esm/methods/turkiyeTakvimi.js +159 -0
- package/dist/esm/turkiyetakvimi.d.ts +4 -0
- package/dist/esm/turkiyetakvimi.js +4 -0
- package/docs/methods.md +39 -0
- package/package.json +18 -2
- package/schemas/certification.schema.json +2 -1
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Generated by scripts/embed.mjs — do not edit; edit the JSON under data/ instead.
|
|
2
|
+
const data = [{ "id": 16702, "name": "Adana", "lat": 36.9995, "lon": 35.316075, "temkin": 10.0151 }, { "id": 16703, "name": "Adapazarı", "lat": 40.7833, "lon": 30.399875, "temkin": 10.7698 }, { "id": 16704, "name": "Adıyaman", "lat": 37.7667, "lon": 38.2828, "temkin": 10.1563 }, { "id": 16705, "name": "Afyonkarahisar", "lat": 38.750167, "lon": 30.549625, "temkin": 10.3374 }, { "id": 16706, "name": "Ağrı", "lat": 39.7162, "lon": 43.0495, "temkin": 10.5387 }, { "id": 16707, "name": "Aksaray", "lat": 38.3667, "lon": 34.0328, "temkin": 10.2665 }, { "id": 16708, "name": "Amasya", "lat": 40.65, "lon": 35.8333, "temkin": 10.7413 }, { "id": 16709, "name": "Ankara", "lat": 39.9333, "lon": 32.849063, "temkin": 10.5818 }, { "id": 16710, "name": "Antakya", "lat": 36.1833, "lon": 36.166263, "temkin": 9.8655 }, { "id": 16711, "name": "Antalya", "lat": 36.8838, "lon": 30.6995, "temkin": 9.9937 }, { "id": 16712, "name": "Ardahan", "lat": 41.1167, "lon": 42.7, "temkin": 10.8344 }, { "id": 16713, "name": "Artvin", "lat": 41.1833, "lon": 41.816575, "temkin": 10.8446 }, { "id": 16714, "name": "Aydın", "lat": 37.849833, "lon": 27.849625, "temkin": 10.1726 }, { "id": 16715, "name": "Balıkesir", "lat": 39.65, "lon": 27.882362, "temkin": 10.5209 }, { "id": 16716, "name": "Bartın", "lat": 41.633133, "lon": 32.333175, "temkin": 10.9118 }, { "id": 16717, "name": "Batman", "lat": 37.8662, "lon": 41.116325, "temkin": 10.1742 }, { "id": 16718, "name": "Bayburt", "lat": 40.2505, "lon": 40.232175, "temkin": 10.6513 }, { "id": 16719, "name": "Bilecik", "lat": 40.149833, "lon": 29.9828, "temkin": 10.6312 }, { "id": 16720, "name": "Bingöl", "lat": 38.883133, "lon": 40.48305, "temkin": 10.3613 }, { "id": 16721, "name": "Bitlis", "lat": 38.3828, "lon": 42.099375, "temkin": 10.2697 }, { "id": 16722, "name": "Bolu", "lat": 40.733133, "lon": 31.61645, "temkin": 10.7573 }, { "id": 16723, "name": "Burdur", "lat": 37.7162, "lon": 30.283425, "temkin": 10.149 }, { "id": 16724, "name": "Bursa", "lat": 40.200333, "lon": 29.066325, "temkin": 10.6428 }, { "id": 16725, "name": "Çanakkale", "lat": 40.15, "lon": 26.416012, "temkin": 10.6307 }, { "id": 16726, "name": "Çankırı", "lat": 40.6, "lon": 33.6167, "temkin": 10.7299 }, { "id": 16727, "name": "Çorum", "lat": 40.55, "lon": 34.949625, "temkin": 10.7186 }, { "id": 16728, "name": "Denizli", "lat": 37.7833, "lon": 29.083175, "temkin": 10.1605 }, { "id": 16729, "name": "Diyarbakır", "lat": 37.9167, "lon": 40.232675, "temkin": 10.1822 }, { "id": 16730, "name": "Edirne", "lat": 41.666367, "lon": 26.566575, "temkin": 10.9169 }, { "id": 16731, "name": "Elazığ", "lat": 38.683467, "lon": 39.23305, "temkin": 10.3245 }, { "id": 16732, "name": "Erzincan", "lat": 39.75, "lon": 39.499875, "temkin": 10.5473 }, { "id": 16733, "name": "Erzurum", "lat": 39.916533, "lon": 41.266325, "temkin": 10.5817 }, { "id": 16734, "name": "Eskişehir", "lat": 39.782133, "lon": 30.51595, "temkin": 10.553 }, { "id": 16735, "name": "Gaziantep", "lat": 37.066367, "lon": 37.38305, "temkin": 10.0276 }, { "id": 16736, "name": "Giresun", "lat": 40.916367, "lon": 38.399875, "temkin": 10.7996 }, { "id": 16737, "name": "Gümüşhane", "lat": 40.449, "lon": 39.482925, "temkin": 10.696 }, { "id": 16738, "name": "Hakkâri", "lat": 37.5833, "lon": 43.733238, "temkin": 10.1245 }, { "id": 16739, "name": "Iğdır", "lat": 39.916533, "lon": 44.032987, "temkin": 10.5817 }, { "id": 16740, "name": "Isparta", "lat": 37.767033, "lon": 30.549625, "temkin": 10.1573 }, { "id": 16741, "name": "İstanbul", "lat": 41.000167, "lon": 28.999625, "temkin": 10.815 }, { "id": 16742, "name": "İzmir", "lat": 38.416367, "lon": 27.132987, "temkin": 10.2768 }, { "id": 16743, "name": "Kahramanmaraş", "lat": 37.5833, "lon": 36.932925, "temkin": 10.1225 }, { "id": 16744, "name": "Karabük", "lat": 41.199833, "lon": 32.632425, "temkin": 10.8451 }, { "id": 16745, "name": "Karaman", "lat": 37.183633, "lon": 33.21595, "temkin": 10.0491 }, { "id": 16746, "name": "Kars", "lat": 40.5995, "lon": 43.083175, "temkin": 10.7284 }, { "id": 16747, "name": "Kastamonu", "lat": 41.366533, "lon": 33.78305, "temkin": 10.8723 }, { "id": 16748, "name": "Kayseri", "lat": 38.732967, "lon": 35.48305, "temkin": 10.3331 }, { "id": 16749, "name": "Kilis", "lat": 36.716867, "lon": 37.116325, "temkin": 9.9638 }, { "id": 16750, "name": "Kırıkkale", "lat": 39.8495, "lon": 33.499625, "temkin": 10.5663 }, { "id": 16751, "name": "Kırklareli", "lat": 41.733467, "lon": 27.216575, "temkin": 10.9278 }, { "id": 16752, "name": "Kırşehir", "lat": 39.149167, "lon": 34.166075, "temkin": 10.4142 }, { "id": 16753, "name": "Konya", "lat": 37.866033, "lon": 32.48305, "temkin": 10.1762 }, { "id": 16754, "name": "Kütahya", "lat": 39.4167, "lon": 29.982675, "temkin": 10.4721 }, { "id": 16755, "name": "Malatya", "lat": 38.349667, "lon": 38.315575, "temkin": 10.2622 }, { "id": 16756, "name": "Manisa", "lat": 38.599833, "lon": 27.4328, "temkin": 10.3105 }, { "id": 16757, "name": "Mardin", "lat": 37.3, "lon": 40.7333, "temkin": 10.0723 }, { "id": 16758, "name": "Mersin", "lat": 36.800167, "lon": 34.633237, "temkin": 9.9795 }, { "id": 16759, "name": "Muğla", "lat": 37.2167, "lon": 28.36645, "temkin": 10.0572 }, { "id": 16760, "name": "Muş", "lat": 38.733633, "lon": 41.4995, "temkin": 10.3326 }, { "id": 16761, "name": "Nevşehir", "lat": 38.632967, "lon": 34.716575, "temkin": 10.3156 }, { "id": 16762, "name": "Niğde", "lat": 37.9667, "lon": 34.6828, "temkin": 10.1917 }, { "id": 16763, "name": "Ordu", "lat": 40.982967, "lon": 37.8828, "temkin": 10.8126 }, { "id": 16764, "name": "Osmaniye", "lat": 37.066033, "lon": 36.249375, "temkin": 10.0281 }, { "id": 16765, "name": "Rize", "lat": 41.032967, "lon": 40.516575, "temkin": 10.8218 }, { "id": 16766, "name": "Samsun", "lat": 41.2833, "lon": 36.33305, "temkin": 10.8589 }, { "id": 16767, "name": "Siirt", "lat": 37.9328, "lon": 41.94975, "temkin": 10.1869 }, { "id": 16768, "name": "Sinop", "lat": 42.033133, "lon": 35.14975, "temkin": 10.9773 }, { "id": 16769, "name": "Sivas", "lat": 39.7495, "lon": 37.01645, "temkin": 10.5443 }, { "id": 16770, "name": "Şanlıurfa", "lat": 37.1505, "lon": 38.7995, "temkin": 10.0431 }, { "id": 16771, "name": "Şırnak", "lat": 37.5167, "lon": 42.466825, "temkin": 10.1122 }, { "id": 16772, "name": "Tekirdağ", "lat": 40.9833, "lon": 27.51645, "temkin": 10.8131 }, { "id": 16773, "name": "Tokat", "lat": 40.316367, "lon": 36.549625, "temkin": 10.6687 }, { "id": 16774, "name": "Trabzon", "lat": 41, "lon": 39.7162, "temkin": 10.815 }, { "id": 16775, "name": "Tunceli", "lat": 39.116533, "lon": 39.532925, "temkin": 10.4079 }, { "id": 18138, "name": "Uşak", "lat": 38.682467, "lon": 29.399875, "temkin": 10.3235 }, { "id": 18159, "name": "Van", "lat": 38.498833, "lon": 43.3828, "temkin": 10.2907 }, { "id": 18161, "name": "Yalova", "lat": 40.65, "lon": 29.266075, "temkin": 10.7413 }, { "id": 18180, "name": "Yozgat", "lat": 39.816867, "lon": 34.7995, "temkin": 10.5606 }, { "id": 18196, "name": "Zonguldak", "lat": 41.450167, "lon": 31.799563, "temkin": 10.8828 }, { "id": 18197, "name": "Düzce", "lat": 40.849667, "lon": 31.149875, "temkin": 10.7827 }, { "id": 62353, "name": "İzmit", "lat": 40.766533, "lon": 29.949625, "temkin": 10.766 }];
|
|
3
|
+
export default data;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const data = { "certified": true, "checkedAt": "2026-11-11", "places": 81, "checks": [{ "tables": "Türkiye Takvimi — its cities’ years", "places": 81, "times": 178848, "off": 0, "offWithoutCorrections": 52, "from": "2025-12-31", "to": "2027-01-02" }], "corrections": { "from": "2025-12-31", "to": "2027-01-02", "entries": 52, "sha256": "a3059fd5aae0b0f8ddee10a2aaaf93e982ded12e652f6aa21d0a3d347a082b41" }, "revision": 1 };
|
|
2
|
+
export default data;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const data = { "from": "2025-12-31", "to": "2027-01-02", "points": { "36.999,35.316": ["2026-01-07 fajr -1"], "37.184,33.216": ["2026-01-20 fajr -1", "2026-01-27 fajr -1"], "37.217,28.366": ["2026-11-18 sunrise +1"], "37.767,30.550": ["2026-05-26 isha -1"], "37.850,27.850": ["2026-03-06 dhuhr -1"], "37.866,32.483": ["2026-06-08 maghrib +1"], "37.917,40.233": ["2026-11-16 dhuhr +1"], "38.367,34.033": ["2026-04-16 isha -1"], "38.383,42.099": ["2026-03-26 maghrib -1"], "38.633,34.717": ["2026-05-31 asr +1", "2026-07-02 asr +1"], "38.733,35.483": ["2026-05-04 isha +1"], "38.883,40.483": ["2026-03-25 sunrise -1"], "39.716,43.050": ["2026-02-01 isha -1", "2026-02-20 fajr -1", "2026-03-04 maghrib -1"], "39.750,39.500": ["2026-01-17 isha -1", "2026-02-22 dhuhr -1"], "39.933,32.849": ["2026-02-22 isha -1"], "40.316,36.550": ["2026-02-01 dhuhr -1"], "40.599,43.083": ["2026-05-06 dhuhr +1"], "40.650,29.266": ["2026-01-26 asr -1"], "40.650,35.833": ["2026-10-03 fajr +1"], "40.733,31.616": ["2026-03-24 maghrib +1", "2026-09-08 dhuhr +1"], "40.767,29.950": ["2026-03-05 maghrib -1", "2026-04-14 sunrise -1"], "40.850,31.150": ["2026-07-19 sunrise -1"], "40.983,27.516": ["2026-07-03 dhuhr +1", "2026-11-26 dhuhr +1", "2026-12-23 asr +1"], "41.000,29.000": ["2026-03-31 sunrise -1", "2026-12-15 maghrib -1", "2026-12-16 maghrib -1", "2026-12-17 maghrib -1", "2026-12-17 sunrise -1", "2026-12-18 maghrib -1", "2026-12-21 maghrib -1", "2026-12-24 sunrise -1", "2026-12-27 sunrise -1", "2026-12-31 sunrise -1"], "41.033,40.517": ["2026-04-19 maghrib +1"], "41.200,32.632": ["2026-02-20 dhuhr -1", "2026-03-21 fajr -1"], "41.367,33.783": ["2026-04-05 asr -1"], "41.450,31.800": ["2026-05-22 sunrise -1", "2026-08-09 asr +1"], "41.666,26.567": ["2026-04-23 isha +1"], "41.733,27.217": ["2026-06-28 fajr +1", "2026-09-19 isha -1"], "42.033,35.150": ["2026-10-11 maghrib +1"] } };
|
|
2
|
+
export default data;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -15,5 +15,6 @@ import './authorities/diyanet.js';
|
|
|
15
15
|
import './authorities/morocco.js';
|
|
16
16
|
import './authorities/algeria.js';
|
|
17
17
|
import './authorities/indonesia.js';
|
|
18
|
+
import './authorities/turkiyeTakvimi.js';
|
|
18
19
|
export * from './core/index.js';
|
|
19
20
|
export { diyanetCountry } from './authorities/diyanet.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -15,5 +15,6 @@ import './authorities/diyanet.js';
|
|
|
15
15
|
import './authorities/morocco.js';
|
|
16
16
|
import './authorities/algeria.js';
|
|
17
17
|
import './authorities/indonesia.js';
|
|
18
|
+
import './authorities/turkiyeTakvimi.js';
|
|
18
19
|
export * from './core/index.js';
|
|
19
20
|
export { diyanetCountry } from './authorities/diyanet.js';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type TakvimInstants = {
|
|
2
|
+
fajr: Date;
|
|
3
|
+
sunrise: Date;
|
|
4
|
+
dhuhr: Date;
|
|
5
|
+
asr: Date;
|
|
6
|
+
maghrib: Date;
|
|
7
|
+
isha: Date;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The calendar's temkin by its formula, minutes: the time the sun takes on
|
|
11
|
+
* the summer solstice at this latitude to go from the level horizon to the
|
|
12
|
+
* city's own. A listed place carries its own (`Place.temkin`), which strays
|
|
13
|
+
* from this by a few hundredths of a minute.
|
|
14
|
+
*/
|
|
15
|
+
export declare function takvimTemkin(latitude: number, heightM?: number): number;
|
|
16
|
+
/** The day whose night times stand for this one: itself, or the last before it whose night reached 19°. */
|
|
17
|
+
export declare function heldNight(latitude: number, longitude: number, key: number): number;
|
|
18
|
+
/**
|
|
19
|
+
* The calendar's times before rounding, minutes past 00:00 UT of the date
|
|
20
|
+
* (month 0-based): the six the library gives, and İmsâk. A held night's
|
|
21
|
+
* times are that night's time of day, on this date.
|
|
22
|
+
*/
|
|
23
|
+
export declare function takvimRawMinutes(latitude: number, longitude: number, year: number, month: number, day: number, temkin?: number, asrShadow?: number): {
|
|
24
|
+
imsak: number;
|
|
25
|
+
fajr: number;
|
|
26
|
+
sunrise: number;
|
|
27
|
+
dhuhr: number;
|
|
28
|
+
asr: number;
|
|
29
|
+
maghrib: number;
|
|
30
|
+
isha: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The calendar's İmsâk for the date, on the minute (rounded down), or null
|
|
34
|
+
* where it does not form. Not one of the six times the library certifies.
|
|
35
|
+
*/
|
|
36
|
+
export declare function takvimImsak(latitude: number, longitude: number, year: number, month: number, day: number, temkin?: number): Date | null;
|
|
37
|
+
/**
|
|
38
|
+
* Türkiye Takvimi's times for the civil date (month 0-based) at the point,
|
|
39
|
+
* each on the minute the calendar prints; Fajr is its Sabâh. Null where a
|
|
40
|
+
* time does not form.
|
|
41
|
+
*/
|
|
42
|
+
export declare function takvimTimes(latitude: number, longitude: number, year: number, month: number, day: number, temkin?: number, asrShadow?: number): TakvimInstants | null;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Türkiye Takvimi — the calendar's method, as the year it publishes for a
|
|
3
|
+
* city is computed (namazvakti.com).
|
|
4
|
+
*
|
|
5
|
+
* Read off the calendar's own years (cities from 42°S to 60°N):
|
|
6
|
+
*
|
|
7
|
+
* • the precise apparent sun, taken at each event's own moment (iterated);
|
|
8
|
+
* • a temkin T per city, in minutes with its fraction: the time the sun
|
|
9
|
+
* takes on the summer solstice (declination 23.38°) to go from the
|
|
10
|
+
* level horizon down to the city's own, which depends on the height the
|
|
11
|
+
* calendar gives the city (250 m or 500 m). A place carries the T its
|
|
12
|
+
* table shows (`Place.temkin`); `takvimTemkin` is the formula;
|
|
13
|
+
* • İmsâk the sun 19° below the horizon, less T, rounded DOWN;
|
|
14
|
+
* • Sabâh — the time the calendar prints for the Fajr prayer — the sun at
|
|
15
|
+
* 18°, with no temkin;
|
|
16
|
+
* • sunrise the sun's centre on the level horizon (0°, no refraction),
|
|
17
|
+
* less T and two minutes;
|
|
18
|
+
* • Dhuhr the transit plus T; Asr and Isha (17°) plus T;
|
|
19
|
+
* • Asr's shadow the object's length plus the noon shadow at the
|
|
20
|
+
* declination of local noon, the hour angle from the sun at Asr itself;
|
|
21
|
+
* • Maghrib the sun's centre on the level horizon, plus T and two minutes;
|
|
22
|
+
* • everything but İmsâk rounded UP to the minute.
|
|
23
|
+
*
|
|
24
|
+
* Where the sun no longer gets 19° below the horizon (north of about 47.5°
|
|
25
|
+
* in summer) the calendar holds İmsâk, Sabâh and Isha at the times of the
|
|
26
|
+
* last night it did; `heldNight` is that rule. No place of the certified
|
|
27
|
+
* list is that far north, so the list does not hold the rule to a table.
|
|
28
|
+
*
|
|
29
|
+
* The calendar's files give a city's point to the whole arc-minute and the
|
|
30
|
+
* calendar computes at a finer one; each place is at the point its year
|
|
31
|
+
* shows (data/places/turkiyeTakvimiCities.json).
|
|
32
|
+
*/
|
|
33
|
+
import { preciseApparentSun } from '../sun/preciseSun.js';
|
|
34
|
+
const RAD = Math.PI / 180;
|
|
35
|
+
const DAY_MS = 86_400_000;
|
|
36
|
+
/** The declination the temkin's solstice is taken at, degrees. */
|
|
37
|
+
const SOLSTICE_DECLINATION = 23.38;
|
|
38
|
+
/** Minutes on sunrise and Maghrib beyond the temkin. */
|
|
39
|
+
const HORIZON_MARGIN = 2;
|
|
40
|
+
/** Days to look back for a night that reached 19°. */
|
|
41
|
+
const HOLD_SEARCH_DAYS = 200;
|
|
42
|
+
/** The depression of a city's horizon below the level one, degrees, for the calendar's height of the city. */
|
|
43
|
+
function horizonDepth(heightM) {
|
|
44
|
+
return 0.8416 + 0.03924 * Math.sqrt(Math.max(0, heightM));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The calendar's temkin by its formula, minutes: the time the sun takes on
|
|
48
|
+
* the summer solstice at this latitude to go from the level horizon to the
|
|
49
|
+
* city's own. A listed place carries its own (`Place.temkin`), which strays
|
|
50
|
+
* from this by a few hundredths of a minute.
|
|
51
|
+
*/
|
|
52
|
+
export function takvimTemkin(latitude, heightM = 250) {
|
|
53
|
+
const phi = Math.min(Math.abs(latitude), 62) * RAD;
|
|
54
|
+
const dec = SOLSTICE_DECLINATION * RAD;
|
|
55
|
+
const hourAngle = (alt) => Math.acos(Math.max(-1, Math.min(1, (Math.sin(alt * RAD) - Math.sin(phi) * Math.sin(dec)) / (Math.cos(phi) * Math.cos(dec)))));
|
|
56
|
+
return ((hourAngle(-horizonDepth(heightM)) - hourAngle(0)) / RAD) * 4;
|
|
57
|
+
}
|
|
58
|
+
/** Whole days since 1970-01-01 of a civil date (month 0-based). */
|
|
59
|
+
const dayKeyOf = (year, month, day) => Math.round(Date.UTC(year, month, day) / DAY_MS);
|
|
60
|
+
/** Days from J2000.0 (noon) of a day's 00:00 UT. */
|
|
61
|
+
const d0Of = (key) => key - 10957 - 0.5;
|
|
62
|
+
/** The sun's events of a day at a point, minutes past the day's 00:00 UT; NaN where one does not happen. */
|
|
63
|
+
function events(latitude, longitude, key) {
|
|
64
|
+
const d0 = d0Of(key);
|
|
65
|
+
const at = (t) => preciseApparentSun(d0 + t / 1440);
|
|
66
|
+
let noon = 720 - 4 * longitude;
|
|
67
|
+
for (let i = 0; i < 3; i++)
|
|
68
|
+
noon = 720 - 4 * longitude - at(noon).eot;
|
|
69
|
+
const noonDec = at(noon).dec;
|
|
70
|
+
const sp = Math.sin(latitude * RAD);
|
|
71
|
+
const cp = Math.cos(latitude * RAD);
|
|
72
|
+
const event = (alt, sign, start) => {
|
|
73
|
+
let t = start;
|
|
74
|
+
for (let i = 0; i < 3; i++) {
|
|
75
|
+
const { dec, eot } = at(t);
|
|
76
|
+
const c = (Math.sin(alt * RAD) - sp * Math.sin(dec)) / (cp * Math.cos(dec));
|
|
77
|
+
if (!(Math.abs(c) <= 1))
|
|
78
|
+
return NaN;
|
|
79
|
+
t = 720 - 4 * longitude - eot + (sign * 4 * Math.acos(c)) / RAD;
|
|
80
|
+
}
|
|
81
|
+
return t;
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
noon,
|
|
85
|
+
at19: () => event(-19, -1, noon - 420),
|
|
86
|
+
at18: () => event(-18, -1, noon - 420),
|
|
87
|
+
sunrise: () => event(0, -1, noon - 360),
|
|
88
|
+
asr: (shadow) => event(Math.atan(1 / (shadow + Math.tan(Math.abs(latitude * RAD - noonDec)))) / RAD, 1, noon + 200),
|
|
89
|
+
sunset: () => event(0, 1, noon + 360),
|
|
90
|
+
at17: () => event(-17, 1, noon + 420),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Does the sun get 19° below the horizon in the night that ends on the
|
|
95
|
+
* morning of the day? The calendar counts it as reaching when its lowest
|
|
96
|
+
* point does at the declination of either of two moments: the local solar
|
|
97
|
+
* midnight that begins the day, or 12:00 UT of the day.
|
|
98
|
+
*/
|
|
99
|
+
function reaches19(latitude, longitude, key) {
|
|
100
|
+
const d0 = d0Of(key);
|
|
101
|
+
const lowest = (d) => Math.abs(latitude + preciseApparentSun(d).dec / RAD) - 90;
|
|
102
|
+
return Math.min(lowest(d0 - longitude / 360), lowest(d0 + 0.5)) <= -19;
|
|
103
|
+
}
|
|
104
|
+
/** The day whose night times stand for this one: itself, or the last before it whose night reached 19°. */
|
|
105
|
+
export function heldNight(latitude, longitude, key) {
|
|
106
|
+
for (let i = 0; i <= HOLD_SEARCH_DAYS; i++)
|
|
107
|
+
if (reaches19(latitude, longitude, key - i))
|
|
108
|
+
return key - i;
|
|
109
|
+
return key;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The calendar's times before rounding, minutes past 00:00 UT of the date
|
|
113
|
+
* (month 0-based): the six the library gives, and İmsâk. A held night's
|
|
114
|
+
* times are that night's time of day, on this date.
|
|
115
|
+
*/
|
|
116
|
+
export function takvimRawMinutes(latitude, longitude, year, month, day, temkin = takvimTemkin(latitude), asrShadow = 1) {
|
|
117
|
+
const key = dayKeyOf(year, month, day);
|
|
118
|
+
const today = events(latitude, longitude, key);
|
|
119
|
+
const night = heldNight(latitude, longitude, key);
|
|
120
|
+
const nightSun = night === key ? today : events(latitude, longitude, night);
|
|
121
|
+
// Isha belongs to the night that begins this evening: it is tomorrow's night that decides,
|
|
122
|
+
// and a held Isha is that of the evening before the last night that reached 19°.
|
|
123
|
+
const ishaNight = heldNight(latitude, longitude, key + 1);
|
|
124
|
+
const ishaDay = ishaNight === key + 1 ? key : ishaNight - 1;
|
|
125
|
+
const ishaSun = ishaDay === key ? today : events(latitude, longitude, ishaDay);
|
|
126
|
+
return {
|
|
127
|
+
imsak: nightSun.at19() - temkin,
|
|
128
|
+
fajr: nightSun.at18(),
|
|
129
|
+
sunrise: today.sunrise() - temkin - HORIZON_MARGIN,
|
|
130
|
+
dhuhr: today.noon + temkin,
|
|
131
|
+
asr: today.asr(asrShadow) + temkin,
|
|
132
|
+
maghrib: today.sunset() + temkin + HORIZON_MARGIN,
|
|
133
|
+
isha: ishaSun.at17() + temkin,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/** Up to the minute, as the calendar rounds everything but İmsâk. */
|
|
137
|
+
const up = (m) => Math.ceil(m - 1e-9);
|
|
138
|
+
/**
|
|
139
|
+
* The calendar's İmsâk for the date, on the minute (rounded down), or null
|
|
140
|
+
* where it does not form. Not one of the six times the library certifies.
|
|
141
|
+
*/
|
|
142
|
+
export function takvimImsak(latitude, longitude, year, month, day, temkin) {
|
|
143
|
+
const m = takvimRawMinutes(latitude, longitude, year, month, day, temkin).imsak;
|
|
144
|
+
return Number.isFinite(m) ? new Date(Date.UTC(year, month, day) + Math.floor(m + 1e-9) * 60_000) : null;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Türkiye Takvimi's times for the civil date (month 0-based) at the point,
|
|
148
|
+
* each on the minute the calendar prints; Fajr is its Sabâh. Null where a
|
|
149
|
+
* time does not form.
|
|
150
|
+
*/
|
|
151
|
+
export function takvimTimes(latitude, longitude, year, month, day, temkin, asrShadow = 1) {
|
|
152
|
+
const r = takvimRawMinutes(latitude, longitude, year, month, day, temkin, asrShadow);
|
|
153
|
+
const all = [r.fajr, r.sunrise, r.dhuhr, r.asr, r.maghrib, r.isha];
|
|
154
|
+
if (!all.every(Number.isFinite))
|
|
155
|
+
return null;
|
|
156
|
+
const start = Date.UTC(year, month, day);
|
|
157
|
+
const at = (m) => new Date(start + up(m) * 60_000);
|
|
158
|
+
return { fajr: at(r.fajr), sunrise: at(r.sunrise), dhuhr: at(r.dhuhr), asr: at(r.asr), maghrib: at(r.maghrib), isha: at(r.isha) };
|
|
159
|
+
}
|
package/docs/methods.md
CHANGED
|
@@ -201,6 +201,45 @@ cities.
|
|
|
201
201
|
its table is computed.
|
|
202
202
|
- Each regency is printed in its province's zone (WIB, WITA or WIT).
|
|
203
203
|
|
|
204
|
+
## Türkiye Takvimi
|
|
205
|
+
|
|
206
|
+
`src/methods/turkiyeTakvimi.ts`. The calendar's own years for its cities
|
|
207
|
+
(namazvakti.com), read off cities from 42°S to 60°N.
|
|
208
|
+
|
|
209
|
+
- The **precise apparent sun** of Indonesia's method — here with ΔT added
|
|
210
|
+
to Universal Time, as the ephemeris asks — taken at each event's own
|
|
211
|
+
moment: three iterations from the transit, itself iterated
|
|
212
|
+
three times.
|
|
213
|
+
- A **temkin `T`** per city, in minutes with its fraction: the time the sun
|
|
214
|
+
takes on the summer solstice (declination 23.38°) at the city's latitude
|
|
215
|
+
`φ` to go from the level horizon to the city's own, `d` below it,
|
|
216
|
+
`T = 4 [ H(−d) − H(0) ]` with `cos H(a) = (sin a − sin φ sin 23.38°) / (cos φ cos 23.38°)`
|
|
217
|
+
and `d = 0.8416° + 0.03924° √h` for the height `h` the calendar gives the
|
|
218
|
+
city (250 m: 1.462°; 500 m: 1.719°). A listed place carries the `T` its
|
|
219
|
+
table shows (`Place.temkin`), which strays from the formula by a few
|
|
220
|
+
hundredths of a minute.
|
|
221
|
+
- **Fajr** is the calendar's Sabâh: the sun 18° below the horizon, with no
|
|
222
|
+
temkin. (Its İmsâk, which the library does not give among the six, is the
|
|
223
|
+
sun at 19° less `T`, rounded down.)
|
|
224
|
+
- **Sunrise**: the sun's centre on the level horizon (altitude 0°, no
|
|
225
|
+
refraction), less `T` and two minutes.
|
|
226
|
+
- **Dhuhr**: the transit plus `T`.
|
|
227
|
+
- **Asr**: the altitude `arccot(s + tan|φ − δ|)` with `δ` the declination
|
|
228
|
+
of local noon (the hour angle from the sun at Asr itself), plus `T`.
|
|
229
|
+
- **Maghrib**: the sun's centre on the level horizon, plus `T` and two
|
|
230
|
+
minutes.
|
|
231
|
+
- **Isha**: the sun 17° below the horizon, plus `T`.
|
|
232
|
+
- Every time rounded **up** to the minute.
|
|
233
|
+
- **Where the sun does not get 19° below the horizon** (north of about
|
|
234
|
+
47.5° in summer), İmsâk, Fajr and Isha are held at the times of the last
|
|
235
|
+
night it did. A night counts as reaching 19° when the sun's lowest point,
|
|
236
|
+
`|φ + δ| − 90°`, does at the declination of either the local solar
|
|
237
|
+
midnight that begins the day or 12:00 UT of the day. The certified list
|
|
238
|
+
has no place that far north; the rule is as the calendar's northern
|
|
239
|
+
cities show it, and no table here holds it.
|
|
240
|
+
- The calendar's files give a city's point to the whole arc-minute and it
|
|
241
|
+
computes at a finer one; each place is at the point its year shows.
|
|
242
|
+
|
|
204
243
|
## Checking a port
|
|
205
244
|
|
|
206
245
|
1. Take `test/vectors.json`. For each case, compute the six times at the
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mihrab-methods",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "The prayer-time authorities' own calculation methods, each reproducing its published timetable to the minute: Sweden (Diyanet, as Islamiska Förbundet prints it), Diyanet worldwide, Morocco (Habous), Algeria (Ministry of Religious Affairs), Indonesia (Kemenag).",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "The prayer-time authorities' own calculation methods, each reproducing its published timetable to the minute: Sweden (Diyanet, as Islamiska Förbundet prints it), Diyanet worldwide, Morocco (Habous), Algeria (Ministry of Religious Affairs), Indonesia (Kemenag), Türkiye Takvimi.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"author": "Hassan El Ghamri",
|
|
7
7
|
"repository": {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"./dist/*/morocco.js",
|
|
29
29
|
"./dist/*/algeria.js",
|
|
30
30
|
"./dist/*/indonesia.js",
|
|
31
|
+
"./dist/*/turkiyetakvimi.js",
|
|
31
32
|
"./dist/*/authorities/*.js",
|
|
32
33
|
"./src/index.ts",
|
|
33
34
|
"./src/sweden.ts",
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
"./src/morocco.ts",
|
|
36
37
|
"./src/algeria.ts",
|
|
37
38
|
"./src/indonesia.ts",
|
|
39
|
+
"./src/turkiyetakvimi.ts",
|
|
38
40
|
"./src/authorities/*.ts"
|
|
39
41
|
],
|
|
40
42
|
"engines": {
|
|
@@ -121,6 +123,16 @@
|
|
|
121
123
|
"default": "./dist/cjs/indonesia.js"
|
|
122
124
|
}
|
|
123
125
|
},
|
|
126
|
+
"./turkiyetakvimi": {
|
|
127
|
+
"import": {
|
|
128
|
+
"types": "./dist/esm/turkiyetakvimi.d.ts",
|
|
129
|
+
"default": "./dist/esm/turkiyetakvimi.js"
|
|
130
|
+
},
|
|
131
|
+
"require": {
|
|
132
|
+
"types": "./dist/cjs/turkiyetakvimi.d.ts",
|
|
133
|
+
"default": "./dist/cjs/turkiyetakvimi.js"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
124
136
|
"./locate": {
|
|
125
137
|
"import": {
|
|
126
138
|
"types": "./dist/esm/locate.d.ts",
|
|
@@ -156,6 +168,9 @@
|
|
|
156
168
|
"indonesia": [
|
|
157
169
|
"./dist/cjs/indonesia.d.ts"
|
|
158
170
|
],
|
|
171
|
+
"turkiyetakvimi": [
|
|
172
|
+
"./dist/cjs/turkiyetakvimi.d.ts"
|
|
173
|
+
],
|
|
159
174
|
"locate": [
|
|
160
175
|
"./dist/cjs/locate.d.ts"
|
|
161
176
|
]
|
|
@@ -176,6 +191,7 @@
|
|
|
176
191
|
"precertify": "npm run embed",
|
|
177
192
|
"certify": "tsx tools/certify.ts",
|
|
178
193
|
"vectors": "npm run embed && tsx tools/vectors.ts",
|
|
194
|
+
"port-sample": "npm run embed && tsx tools/port-sample.ts",
|
|
179
195
|
"prefeed-check": "npm run embed",
|
|
180
196
|
"feed-check": "tsx tools/feed-check.ts",
|
|
181
197
|
"readme": "node scripts/readme.mjs",
|