mihrab-methods 1.3.2 → 1.5.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.
Files changed (51) hide show
  1. package/README.md +4 -3
  2. package/certification.json +27 -4
  3. package/data/corrections/diyanet.json +48 -316
  4. package/data/corrections/kazakhstan.json +5 -0
  5. package/dist/cjs/authorities/kazakhstan.d.ts +3 -0
  6. package/dist/cjs/authorities/kazakhstan.js +49 -0
  7. package/dist/cjs/core/compute.js +8 -4
  8. package/dist/cjs/core/types.d.ts +1 -1
  9. package/dist/cjs/core/types.js +1 -1
  10. package/dist/cjs/data/generated/diyanetCertification.js +1 -1
  11. package/dist/cjs/data/generated/diyanetCorrections.js +1 -1
  12. package/dist/cjs/data/generated/diyanetWorldPoints.js +1 -1
  13. package/dist/cjs/data/generated/kazakhstanCertification.d.ts +3 -0
  14. package/dist/cjs/data/generated/kazakhstanCertification.js +4 -0
  15. package/dist/cjs/data/generated/kazakhstanCities.d.ts +7 -0
  16. package/dist/cjs/data/generated/kazakhstanCities.js +5 -0
  17. package/dist/cjs/data/generated/kazakhstanCorrections.d.ts +3 -0
  18. package/dist/cjs/data/generated/kazakhstanCorrections.js +4 -0
  19. package/dist/cjs/index.d.ts +1 -0
  20. package/dist/cjs/index.js +1 -0
  21. package/dist/cjs/kazakhstan.d.ts +4 -0
  22. package/dist/cjs/kazakhstan.js +22 -0
  23. package/dist/cjs/methods/kazakhstan.d.ts +58 -0
  24. package/dist/cjs/methods/kazakhstan.js +129 -0
  25. package/dist/cjs/methods/revisions.d.ts +2 -1
  26. package/dist/cjs/methods/revisions.js +2 -1
  27. package/dist/esm/authorities/kazakhstan.d.ts +3 -0
  28. package/dist/esm/authorities/kazakhstan.js +43 -0
  29. package/dist/esm/core/compute.js +8 -4
  30. package/dist/esm/core/types.d.ts +1 -1
  31. package/dist/esm/core/types.js +1 -1
  32. package/dist/esm/data/generated/diyanetCertification.js +1 -1
  33. package/dist/esm/data/generated/diyanetCorrections.js +1 -1
  34. package/dist/esm/data/generated/diyanetWorldPoints.js +1 -1
  35. package/dist/esm/data/generated/kazakhstanCertification.d.ts +3 -0
  36. package/dist/esm/data/generated/kazakhstanCertification.js +2 -0
  37. package/dist/esm/data/generated/kazakhstanCities.d.ts +7 -0
  38. package/dist/esm/data/generated/kazakhstanCities.js +3 -0
  39. package/dist/esm/data/generated/kazakhstanCorrections.d.ts +3 -0
  40. package/dist/esm/data/generated/kazakhstanCorrections.js +2 -0
  41. package/dist/esm/index.d.ts +1 -0
  42. package/dist/esm/index.js +1 -0
  43. package/dist/esm/kazakhstan.d.ts +4 -0
  44. package/dist/esm/kazakhstan.js +4 -0
  45. package/dist/esm/methods/kazakhstan.d.ts +58 -0
  46. package/dist/esm/methods/kazakhstan.js +124 -0
  47. package/dist/esm/methods/revisions.d.ts +2 -1
  48. package/dist/esm/methods/revisions.js +2 -1
  49. package/docs/methods.md +29 -0
  50. package/package.json +17 -2
  51. package/schemas/certification.schema.json +2 -1
@@ -0,0 +1,3 @@
1
+ import type { Certification } from '../../core/types.js';
2
+ declare const data: Certification | null;
3
+ export default data;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const data = { "certified": true, "checkedAt": "2026-11-11", "places": 84, "checks": [{ "tables": "Kazakhstan — the Spiritual Administration’s times", "places": 84, "times": 551880, "off": 0, "offWithoutCorrections": 0, "from": "2025-01-01", "to": "2027-12-31" }], "corrections": { "from": "2025-01-01", "to": "2027-12-31", "entries": 0, "sha256": "e3d60e566ca082f74ce9904886087b29e65d2871c5bcc02f46349d82c8994d88" }, "revision": 1 };
4
+ exports.default = data;
@@ -0,0 +1,7 @@
1
+ declare const data: {
2
+ id: number;
3
+ name: string;
4
+ lat: number;
5
+ lon: number;
6
+ }[];
7
+ export default data;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Generated by scripts/embed.mjs — do not edit; edit the JSON under data/ instead.
4
+ const data = [{ "id": 2, "name": "Қонаев", "lat": 43.883333, "lon": 77.083333 }, { "id": 3, "name": "Астана", "lat": 51.133333, "lon": 71.433333 }, { "id": 7, "name": "Орал", "lat": 51.204019, "lon": 51.370537 }, { "id": 17, "name": "Көкшетау", "lat": 53.291667, "lon": 69.391667 }, { "id": 18, "name": "Атырау", "lat": 47.116667, "lon": 51.883333 }, { "id": 20, "name": "Ақтөбе", "lat": 50.300377, "lon": 57.154555 }, { "id": 21, "name": "Степногорск", "lat": 52.346944, "lon": 71.881667 }, { "id": 22, "name": "Үшарал", "lat": 46.169722, "lon": 80.939444 }, { "id": 23, "name": "Атбасар", "lat": 51.815761, "lon": 68.358335 }, { "id": 24, "name": "Қандыағаш", "lat": 49.474444, "lon": 57.423333 }, { "id": 25, "name": "Хромтау", "lat": 50.250278, "lon": 58.434722 }, { "id": 26, "name": "Шалқар", "lat": 47.831392, "lon": 59.61929 }, { "id": 27, "name": "Құлсары", "lat": 46.983333, "lon": 54.016667 }, { "id": 29, "name": "Аягөз", "lat": 47.966667, "lon": 80.433333 }, { "id": 30, "name": "Өскемен", "lat": 49.948325, "lon": 82.627848 }, { "id": 31, "name": "Риддер", "lat": 50.33886, "lon": 83.506329 }, { "id": 32, "name": "Семей", "lat": 50.404976, "lon": 80.249235 }, { "id": 33, "name": "Жаңатас", "lat": 43.55465, "lon": 69.722525 }, { "id": 34, "name": "Қаратау", "lat": 43.166667, "lon": 70.466667 }, { "id": 35, "name": "Тараз", "lat": 42.883333, "lon": 71.366667 }, { "id": 36, "name": "Балқаш", "lat": 46.843721, "lon": 74.977301 }, { "id": 38, "name": "Жезқазған", "lat": 47.799711, "lon": 67.71409 }, { "id": 39, "name": "Қарағанды", "lat": 49.806406, "lon": 73.085485 }, { "id": 40, "name": "Сәтпаев", "lat": 47.907455, "lon": 67.528112 }, { "id": 41, "name": "Арқалық", "lat": 50.248611, "lon": 66.911389 }, { "id": 42, "name": "Қостанай", "lat": 53.219333, "lon": 63.634194 }, { "id": 43, "name": "Рудный", "lat": 52.966667, "lon": 63.116667 }, { "id": 46, "name": "Қызылорда", "lat": 44.842544, "lon": 65.502563 }, { "id": 47, "name": "Ақтау", "lat": 43.635379, "lon": 51.169135 }, { "id": 49, "name": "Форт-Шевченко", "lat": 44.507463, "lon": 50.262833 }, { "id": 50, "name": "Жаңаөзен", "lat": 43.343266, "lon": 52.865792 }, { "id": 51, "name": "Петропавл", "lat": 54.862222, "lon": 69.140833 }, { "id": 52, "name": "Екібастұз", "lat": 51.729778, "lon": 75.326583 }, { "id": 53, "name": "Павлодар", "lat": 52.315556, "lon": 76.956389 }, { "id": 54, "name": "Жетісай", "lat": 40.775278, "lon": 68.327222 }, { "id": 55, "name": "Сарыағаш", "lat": 41.466667, "lon": 69.166667 }, { "id": 56, "name": "Шардара", "lat": 41.254722, "lon": 67.969167 }, { "id": 57, "name": "Шымкент", "lat": 42.368009, "lon": 69.612769 }, { "id": 58, "name": "Түркістан", "lat": 43.302025, "lon": 68.268979 }, { "id": 59, "name": "Ақсай", "lat": 51.164945, "lon": 53.020868 }, { "id": 69, "name": "Лисаков", "lat": 52.544079, "lon": 62.492641 }, { "id": 70, "name": "Жаркент", "lat": 44.169365, "lon": 80.003842 }, { "id": 71, "name": "Арал", "lat": 46.797738, "lon": 61.660792 }, { "id": 72, "name": "Алматы", "lat": 43.238293, "lon": 76.945465 }, { "id": 73, "name": "Талғар", "lat": 43.302813, "lon": 77.23969 }, { "id": 75, "name": "Қаскелең", "lat": 43.202449, "lon": 76.622278 }, { "id": 77, "name": "Шу", "lat": 43.611782, "lon": 73.760237 }, { "id": 79, "name": "Қаражал", "lat": 48.001042, "lon": 70.785762 }, { "id": 82, "name": "Ленгер", "lat": 42.182051, "lon": 69.88212 }, { "id": 93, "name": "Ембі", "lat": 48.823344, "lon": 58.148397 }, { "id": 95, "name": "Зайсан", "lat": 47.453008, "lon": 84.969846 }, { "id": 100, "name": "Кентау", "lat": 43.518131, "lon": 68.504652 }, { "id": 103, "name": "Тайынша", "lat": 53.852738, "lon": 69.782631 }, { "id": 109, "name": "Теміртау", "lat": 50.058756, "lon": 72.953424 }, { "id": 112, "name": "Алға", "lat": 49.89673, "lon": 57.328586 }, { "id": 113, "name": "Ақсу", "lat": 52.03789, "lon": 76.920582 }, { "id": 128, "name": "Курчатов", "lat": 50.7549, "lon": 78.544826 }, { "id": 134, "name": "Арыс", "lat": 42.432744, "lon": 68.813798 }, { "id": 137, "name": "Қосшы", "lat": 50.970262, "lon": 71.355366 }, { "id": 143, "name": "Текелі", "lat": 44.863094, "lon": 78.764266 }, { "id": 146, "name": "Қарқаралы", "lat": 49.41224, "lon": 75.470095 }, { "id": 149, "name": "Шар", "lat": 49.584964, "lon": 81.047173 }, { "id": 150, "name": "Ақкөл", "lat": 51.995855, "lon": 70.952948 }, { "id": 151, "name": "Державинск", "lat": 51.098685, "lon": 66.314712 }, { "id": 152, "name": "Ерейментау", "lat": 51.619626, "lon": 73.102598 }, { "id": 153, "name": "Есіл", "lat": 51.958004, "lon": 66.406215 }, { "id": 154, "name": "Макинск", "lat": 52.63281, "lon": 70.417677 }, { "id": 155, "name": "Степняк", "lat": 52.832, "lon": 70.783427 }, { "id": 157, "name": "Жем", "lat": 48.774532, "lon": 58.072436 }, { "id": 158, "name": "Темір", "lat": 49.143142, "lon": 57.12633 }, { "id": 159, "name": "Алатау", "lat": 43.681261, "lon": 77.116046 }, { "id": 161, "name": "Сарқан", "lat": 45.413666, "lon": 79.916894 }, { "id": 162, "name": "Талдықорған", "lat": 45.017837, "lon": 78.382123 }, { "id": 163, "name": "Үштөбе", "lat": 45.251221, "lon": 77.980827 }, { "id": 165, "name": "Приозёрск", "lat": 46.028969, "lon": 73.708027 }, { "id": 166, "name": "Саран", "lat": 49.801993, "lon": 72.828387 }, { "id": 167, "name": "Шахтинск", "lat": 49.705868, "lon": 72.594637 }, { "id": 170, "name": "Қазалы", "lat": 45.760633, "lon": 62.105836 }, { "id": 171, "name": "Булаев", "lat": 54.896056, "lon": 70.448157 }, { "id": 172, "name": "Мамлют", "lat": 54.94112, "lon": 68.546199 }, { "id": 173, "name": "Сергеев", "lat": 53.888542, "lon": 67.416271 }, { "id": 174, "name": "Алтай", "lat": 49.725218, "lon": 84.273562 }, { "id": 175, "name": "Серебрянск", "lat": 49.679277, "lon": 83.300651 }, { "id": 176, "name": "Шемонаиха", "lat": 50.627624, "lon": 81.916697 }];
5
+ exports.default = data;
@@ -0,0 +1,3 @@
1
+ import type { CorrectionsFile } from '../../core/types.js';
2
+ declare const data: CorrectionsFile;
3
+ export default data;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const data = { "from": "2025-01-01", "to": "2027-12-31", "points": {} };
4
+ exports.default = data;
@@ -16,5 +16,6 @@ import './authorities/morocco.js';
16
16
  import './authorities/algeria.js';
17
17
  import './authorities/indonesia.js';
18
18
  import './authorities/turkiyeTakvimi.js';
19
+ import './authorities/kazakhstan.js';
19
20
  export * from './core/index.js';
20
21
  export { diyanetCountry } from './authorities/diyanet.js';
package/dist/cjs/index.js CHANGED
@@ -33,6 +33,7 @@ require("./authorities/morocco.js");
33
33
  require("./authorities/algeria.js");
34
34
  require("./authorities/indonesia.js");
35
35
  require("./authorities/turkiyeTakvimi.js");
36
+ require("./authorities/kazakhstan.js");
36
37
  __exportStar(require("./core/index.js"), exports);
37
38
  var diyanet_js_1 = require("./authorities/diyanet.js");
38
39
  Object.defineProperty(exports, "diyanetCountry", { enumerable: true, get: function () { return diyanet_js_1.diyanetCountry; } });
@@ -0,0 +1,4 @@
1
+ /** mihrab-methods/kazakhstan — the Kazakhstan method with its places and correction list, and nothing else's. */
2
+ import './authorities/kazakhstan.js';
3
+ export * from './core/index.js';
4
+ export { places } from './authorities/kazakhstan.js';
@@ -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/kazakhstan — the Kazakhstan method with its places and correction list, and nothing else's. */
19
+ require("./authorities/kazakhstan.js");
20
+ __exportStar(require("./core/index.js"), exports);
21
+ var kazakhstan_js_1 = require("./authorities/kazakhstan.js");
22
+ Object.defineProperty(exports, "places", { enumerable: true, get: function () { return kazakhstan_js_1.places; } });
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Kazakhstan — the Spiritual Administration of Muslims of Kazakhstan's
3
+ * method, as the times it publishes for a place are computed.
4
+ *
5
+ * Read off its published year for places from 40.8° to 54.9° N:
6
+ *
7
+ * • a short series for the sun: mean anomaly g and mean longitude q linear
8
+ * in the days D from J2000.0, the ecliptic longitude
9
+ * L = q + 1.915° sin g + 0.020° sin 2g, the obliquity 23.439° − 0.00000036° D,
10
+ * and from them the declination and the equation of time;
11
+ * • the day counted from 0h of the civil date at the place's own meridian
12
+ * (the Julian day of the date less longitude/360);
13
+ * • each time computed once, with the sun taken at a fixed first guess of
14
+ * its hour (Fajr 5h, sunrise 6h, Dhuhr 12h, Asr 13h, sunset and Isha
15
+ * 18h), not iterated;
16
+ * • Fajr and Isha at 15°; sunrise and sunset at −0.833°; Asr at two shadow
17
+ * lengths beyond the noon shadow (Hanafi);
18
+ * • where Fajr would fall more than a quarter of the night before sunrise,
19
+ * or Isha more than a quarter of the night after sunset — or the sun does
20
+ * not reach 15° — the quarter of the night is taken (the night from
21
+ * sunset to sunrise);
22
+ * • a margin of 3 minutes, 5 minutes from 48° N: sunrise that much
23
+ * earlier, Dhuhr and Asr that much later, Maghrib that much after
24
+ * sunset; none on Fajr or Isha;
25
+ * • every time rounded to the nearest minute.
26
+ *
27
+ * With that the method gives every published time of the places read, with
28
+ * no correction list.
29
+ */
30
+ export type KazakhstanInstants = {
31
+ fajr: Date;
32
+ sunrise: Date;
33
+ dhuhr: Date;
34
+ asr: Date;
35
+ maghrib: Date;
36
+ isha: Date;
37
+ };
38
+ /** The margin at a latitude, minutes. */
39
+ export declare function kazakhstanMargin(latitude: number): number;
40
+ /**
41
+ * The times before rounding, minutes past 00:00 UT of the civil date (month
42
+ * 0-based), and the sunset the method prints beside Maghrib.
43
+ */
44
+ export declare function kazakhstanRawMinutes(latitude: number, longitude: number, year: number, month: number, day: number): {
45
+ fajr: number;
46
+ sunrise: number;
47
+ dhuhr: number;
48
+ asr: number;
49
+ sunset: number;
50
+ maghrib: number;
51
+ isha: number;
52
+ };
53
+ /**
54
+ * The Administration's times for the civil date (month 0-based) at the
55
+ * point, each on the minute it prints (rounded to the nearest); Asr is the
56
+ * Hanafi one its table carries. Null where a time does not form.
57
+ */
58
+ export declare function kazakhstanTimes(latitude: number, longitude: number, year: number, month: number, day: number): KazakhstanInstants | null;
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ /**
3
+ * Kazakhstan — the Spiritual Administration of Muslims of Kazakhstan's
4
+ * method, as the times it publishes for a place are computed.
5
+ *
6
+ * Read off its published year for places from 40.8° to 54.9° N:
7
+ *
8
+ * • a short series for the sun: mean anomaly g and mean longitude q linear
9
+ * in the days D from J2000.0, the ecliptic longitude
10
+ * L = q + 1.915° sin g + 0.020° sin 2g, the obliquity 23.439° − 0.00000036° D,
11
+ * and from them the declination and the equation of time;
12
+ * • the day counted from 0h of the civil date at the place's own meridian
13
+ * (the Julian day of the date less longitude/360);
14
+ * • each time computed once, with the sun taken at a fixed first guess of
15
+ * its hour (Fajr 5h, sunrise 6h, Dhuhr 12h, Asr 13h, sunset and Isha
16
+ * 18h), not iterated;
17
+ * • Fajr and Isha at 15°; sunrise and sunset at −0.833°; Asr at two shadow
18
+ * lengths beyond the noon shadow (Hanafi);
19
+ * • where Fajr would fall more than a quarter of the night before sunrise,
20
+ * or Isha more than a quarter of the night after sunset — or the sun does
21
+ * not reach 15° — the quarter of the night is taken (the night from
22
+ * sunset to sunrise);
23
+ * • a margin of 3 minutes, 5 minutes from 48° N: sunrise that much
24
+ * earlier, Dhuhr and Asr that much later, Maghrib that much after
25
+ * sunset; none on Fajr or Isha;
26
+ * • every time rounded to the nearest minute.
27
+ *
28
+ * With that the method gives every published time of the places read, with
29
+ * no correction list.
30
+ */
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.kazakhstanMargin = kazakhstanMargin;
33
+ exports.kazakhstanRawMinutes = kazakhstanRawMinutes;
34
+ exports.kazakhstanTimes = kazakhstanTimes;
35
+ const RAD = Math.PI / 180;
36
+ const sin = (d) => Math.sin(d * RAD);
37
+ const cos = (d) => Math.cos(d * RAD);
38
+ const tan = (d) => Math.tan(d * RAD);
39
+ /** a − b·⌊a/b⌋: into [0, b). */
40
+ const fix = (a, b) => a - b * Math.floor(a / b);
41
+ /** Fajr's and Isha's depression, degrees. */
42
+ const TWILIGHT = 15;
43
+ const HORIZON = 0.833;
44
+ /** Shadow lengths beyond the noon shadow at Asr. */
45
+ const ASR_SHADOW = 2;
46
+ /** The latitude from which the margin is five minutes, not three. */
47
+ const NORTH = 48;
48
+ /** The first guess of each time's hour, at which its sun is taken. */
49
+ const GUESS = { fajr: 5, sunrise: 6, dhuhr: 12, asr: 13, sunset: 18, isha: 18 };
50
+ /** The Julian day of 0h UT of a civil date (month 1-based). */
51
+ function julian(year, month, day) {
52
+ if (month <= 2) {
53
+ year -= 1;
54
+ month += 12;
55
+ }
56
+ const a = Math.floor(year / 100);
57
+ const b = 2 - a + Math.floor(a / 4);
58
+ return Math.floor(365.25 * (year + 4716)) + Math.floor(30.6001 * (month + 1)) + day + b - 1524.5;
59
+ }
60
+ /** The method's sun at a Julian day: declination (degrees), equation of time (hours). */
61
+ function sunAt(jd) {
62
+ const D = jd - 2451545.0;
63
+ const g = fix(357.529 + 0.98560028 * D, 360);
64
+ const q = fix(280.459 + 0.98564736 * D, 360);
65
+ const L = fix(q + 1.915 * sin(g) + 0.02 * sin(2 * g), 360);
66
+ const e = 23.439 - 0.00000036 * D;
67
+ const ra = Math.atan2(cos(e) * sin(L), cos(L)) / RAD / 15;
68
+ return { decl: Math.asin(sin(e) * sin(L)) / RAD, eqt: q / 15 - fix(ra, 24) };
69
+ }
70
+ /** The margin at a latitude, minutes. */
71
+ function kazakhstanMargin(latitude) {
72
+ return latitude >= NORTH ? 5 : 3;
73
+ }
74
+ /**
75
+ * The times before rounding, minutes past 00:00 UT of the civil date (month
76
+ * 0-based), and the sunset the method prints beside Maghrib.
77
+ */
78
+ function kazakhstanRawMinutes(latitude, longitude, year, month, day) {
79
+ const jd = julian(year, month + 1, day) - longitude / 360;
80
+ const midday = (t) => fix(12 - sunAt(jd + t).eqt, 24);
81
+ /** Hours (local mean time) at which the sun is `angle` degrees below the horizon; NaN where it is not. */
82
+ const at = (angle, t, before) => {
83
+ const { decl } = sunAt(jd + t);
84
+ const x = (-sin(angle) - sin(decl) * sin(latitude)) / (cos(decl) * cos(latitude));
85
+ if (!(Math.abs(x) <= 1))
86
+ return NaN;
87
+ const h = Math.acos(x) / RAD / 15;
88
+ return midday(t) + (before ? -h : h);
89
+ };
90
+ const asrAngle = (t) => -Math.atan(1 / (ASR_SHADOW + tan(Math.abs(latitude - sunAt(jd + t).decl)))) / RAD;
91
+ let fajr = at(TWILIGHT, GUESS.fajr / 24, true);
92
+ const sunrise = at(HORIZON, GUESS.sunrise / 24, true);
93
+ const dhuhr = midday(GUESS.dhuhr / 24);
94
+ const asr = at(asrAngle(GUESS.asr / 24), GUESS.asr / 24, false);
95
+ const sunset = at(HORIZON, GUESS.sunset / 24, false);
96
+ let isha = at(TWILIGHT, GUESS.isha / 24, false);
97
+ // the quarter of the night, where the angle is further than that or is not reached
98
+ const portion = (TWILIGHT / 60) * fix(sunrise - sunset, 24);
99
+ if (!Number.isFinite(fajr) || fix(sunrise - fajr, 24) > portion)
100
+ fajr = sunrise - portion;
101
+ if (!Number.isFinite(isha) || fix(isha - sunset, 24) > portion)
102
+ isha = sunset + portion;
103
+ const margin = kazakhstanMargin(latitude);
104
+ // local mean time (hours) to minutes past 00:00 UT of the date
105
+ const ut = (h) => (h - longitude / 15) * 60;
106
+ return {
107
+ fajr: ut(fajr),
108
+ sunrise: ut(sunrise) - margin,
109
+ dhuhr: ut(dhuhr) + margin,
110
+ asr: ut(asr) + margin,
111
+ sunset: ut(sunset),
112
+ maghrib: ut(sunset) + margin,
113
+ isha: ut(isha),
114
+ };
115
+ }
116
+ /**
117
+ * The Administration's times for the civil date (month 0-based) at the
118
+ * point, each on the minute it prints (rounded to the nearest); Asr is the
119
+ * Hanafi one its table carries. Null where a time does not form.
120
+ */
121
+ function kazakhstanTimes(latitude, longitude, year, month, day) {
122
+ const r = kazakhstanRawMinutes(latitude, longitude, year, month, day);
123
+ const all = [r.fajr, r.sunrise, r.dhuhr, r.asr, r.maghrib, r.isha];
124
+ if (!all.every(Number.isFinite))
125
+ return null;
126
+ const start = Date.UTC(year, month, day);
127
+ const at = (m) => new Date(start + Math.floor(m + 0.5) * 60_000);
128
+ 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) };
129
+ }
@@ -8,9 +8,10 @@
8
8
  */
9
9
  export declare const METHOD_REVISION: {
10
10
  readonly sweden: 1;
11
- readonly diyanet: 1;
11
+ readonly diyanet: 2;
12
12
  readonly morocco: 2;
13
13
  readonly algeria: 1;
14
14
  readonly indonesia: 2;
15
15
  readonly turkiyetakvimi: 1;
16
+ readonly kazakhstan: 1;
16
17
  };
@@ -11,9 +11,10 @@ exports.METHOD_REVISION = void 0;
11
11
  */
12
12
  exports.METHOD_REVISION = {
13
13
  sweden: 1,
14
- diyanet: 1,
14
+ diyanet: 2,
15
15
  morocco: 2,
16
16
  algeria: 1,
17
17
  indonesia: 2,
18
18
  turkiyetakvimi: 1,
19
+ kazakhstan: 1,
19
20
  };
@@ -0,0 +1,3 @@
1
+ import type { Place } from '../core/types.js';
2
+ export declare const kazakhstan: import("../core/registry.js").AuthorityData;
3
+ export declare const places: readonly Place[];
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Kazakhstan — the Spiritual Administration of Muslims of Kazakhstan: its
3
+ * cities, each at the coordinates the Administration computes it at.
4
+ */
5
+ import cities from '../data/generated/kazakhstanCities.js';
6
+ import corrections from '../data/generated/kazakhstanCorrections.js';
7
+ import certification from '../data/generated/kazakhstanCertification.js';
8
+ import { METHOD_REVISION } from '../methods/revisions.js';
9
+ import { registerAuthority } from '../core/registry.js';
10
+ const AUTHORITY = 'kazakhstan';
11
+ /** The whole country keeps UTC+5 (since 1 March 2024), and the Administration prints every place on it. */
12
+ const TZ = 'Asia/Almaty';
13
+ function buildPlaces() {
14
+ return cities.map(c => {
15
+ const key = String(c.id);
16
+ return { authority: AUTHORITY, id: `${AUTHORITY}:${key}`, key, name: c.name, country: 'KZ', lat: c.lat, lon: c.lon, tz: TZ };
17
+ });
18
+ }
19
+ export const kazakhstan = registerAuthority({
20
+ authority: AUTHORITY,
21
+ revision: METHOD_REVISION.kazakhstan,
22
+ places: buildPlaces(),
23
+ corrections,
24
+ certification,
25
+ description: {
26
+ name: 'Kazakhstan — Spiritual Administration of Muslims of Kazakhstan',
27
+ method: 'A short series for the sun, each time computed once from a fixed first guess of its hour; Fajr and Isha at 15°, capped at a quarter of the night from sunrise and sunset; sunrise and sunset at −0.833°; Asr at two shadow lengths (Hanafi); a margin of 3 minutes (5 from 48° N) before sunrise, after the transit, on Asr and on Maghrib after sunset; every time rounded to the nearest minute.',
28
+ countries: ['KZ'],
29
+ parameters: {
30
+ fajrAngle: 15,
31
+ ishaAngle: 15,
32
+ sunriseAltitude: -0.833,
33
+ asrShadow: 2,
34
+ highLatitude: 'a quarter of the night, where the angle is further or not reached',
35
+ marginMinutes: '3; 5 from 48° N — sunrise earlier, Dhuhr, Asr and Maghrib later',
36
+ rounding: 'to the nearest minute',
37
+ sun: 'low-precision series (mean elements linear in time, two terms of the equation of the centre), not iterated',
38
+ },
39
+ sources: [{ title: 'Spiritual Administration of Muslims of Kazakhstan — намаз уақыттары', url: 'https://namaz.muftyat.kz/' }],
40
+ spec: 'docs/methods.md#kazakhstan',
41
+ },
42
+ });
43
+ export const places = kazakhstan.places;
@@ -9,6 +9,7 @@ import { moroccoTimes } from '../methods/morocco.js';
9
9
  import { algeriaTimes } from '../methods/algeria.js';
10
10
  import { kemenagTimes } from '../methods/indonesia.js';
11
11
  import { takvimTimes } from '../methods/turkiyeTakvimi.js';
12
+ import { kazakhstanTimes } from '../methods/kazakhstan.js';
12
13
  import { authorityData } from './registry.js';
13
14
  import { placeClockAt } from './clock.js';
14
15
  /**
@@ -32,14 +33,17 @@ export function candidateInstants(place, year, month, day, asrShadow = 1, opts =
32
33
  case 'morocco':
33
34
  case 'algeria':
34
35
  case 'indonesia':
35
- case 'turkiyetakvimi': {
36
+ case 'turkiyetakvimi':
37
+ case 'kazakhstan': {
36
38
  const t = place.authority === 'morocco'
37
39
  ? moroccoTimes(place.lat, place.lon, year, month, day, place.dipDeg, asrShadow, place.dipMaghribDeg)
38
40
  : place.authority === 'algeria'
39
41
  ? algeriaTimes(place.lat, place.lon, year, month, day, asrShadow)
40
- : place.authority === 'turkiyetakvimi'
41
- ? takvimTimes(place.lat, place.lon, year, month, day, place.temkin, asrShadow)
42
- : kemenagTimes(place.lat, place.lon, year, month, day, { highland: place.highland, twilightDip: place.twilightDip, asrShadow, afternoon: place.afternoon });
42
+ : place.authority === 'kazakhstan'
43
+ ? kazakhstanTimes(place.lat, place.lon, year, month, day)
44
+ : place.authority === 'turkiyetakvimi'
45
+ ? takvimTimes(place.lat, place.lon, year, month, day, place.temkin, asrShadow)
46
+ : kemenagTimes(place.lat, place.lon, year, month, day, { highland: place.highland, twilightDip: place.twilightDip, asrShadow, afternoon: place.afternoon });
43
47
  // the correction list: the authority's few times on the other side of a minute (the standard Asr only)
44
48
  const c = !t || !fix ? undefined : fix.correction(place.lat, place.lon, year, month, day);
45
49
  if (!t || !c)
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The shapes the library speaks in. Nothing here computes anything.
3
3
  */
4
- export type Authority = 'sweden' | 'diyanet' | 'morocco' | 'algeria' | 'indonesia' | 'turkiyetakvimi';
4
+ export type Authority = 'sweden' | 'diyanet' | 'morocco' | 'algeria' | 'indonesia' | 'turkiyetakvimi' | 'kazakhstan';
5
5
  export declare const AUTHORITIES: readonly Authority[];
6
6
  export type PrayerKey = 'fajr' | 'sunrise' | 'dhuhr' | 'asr' | 'maghrib' | 'isha';
7
7
  export declare const PRAYER_KEYS: readonly PrayerKey[];
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The shapes the library speaks in. Nothing here computes anything.
3
3
  */
4
- export const AUTHORITIES = ['sweden', 'diyanet', 'morocco', 'algeria', 'indonesia', 'turkiyetakvimi'];
4
+ export const AUTHORITIES = ['sweden', 'diyanet', 'morocco', 'algeria', 'indonesia', 'turkiyetakvimi', 'kazakhstan'];
5
5
  export const PRAYER_KEYS = ['fajr', 'sunrise', 'dhuhr', 'asr', 'maghrib', 'isha'];
6
6
  /** The method has not reproduced its authority's tables to the minute (or not for this date). */
7
7
  export class UncertifiedMethodError extends Error {
@@ -1,2 +1,2 @@
1
- const data = { "certified": true, "checkedAt": "2026-11-11", "places": 8318, "checks": [{ "tables": "Diyanet — its tables worldwide", "places": 8318, "times": 71630078, "off": 0, "offWithoutCorrections": 9368, "from": "2024-01-01", "to": "2027-12-31" }], "corrections": { "from": "2024-01-01", "to": "2027-12-31", "entries": 9357, "sha256": "a8c6a7305611f8dcedc04a64efb8dd150d9a588c2b3ac3391bfb776d70a2ec83" }, "revision": 1 };
1
+ const data = { "certified": true, "checkedAt": "2026-11-11", "places": 8318, "checks": [{ "tables": "Diyanet — its tables worldwide", "places": 8318, "times": 71630078, "off": 0, "offWithoutCorrections": 9112, "from": "2024-01-01", "to": "2027-12-31" }], "corrections": { "from": "2024-01-01", "to": "2027-12-31", "entries": 9101, "sha256": "3b8fabadcd4f2098984daf5105c4223f526c5046f46748fab200dd990ce4a042" }, "revision": 2 };
2
2
  export default data;