Kurz gesagtAlle Dateien liegen unter waqt.qudqu.com/api/v1/ und lassen sich von jeder Website laden. Jede entsteht aus demselben Code, mit dem diese Seite läuft, deshalb nennen API und Seite nie zwei verschiedene Datumsangaben. Kein iranischer Monatsname steht darin.
Schnellstart
Ein import in einem <script type="module"> genügt: keine Installation, kein Schlüssel, keine Anmeldung. Dieser Code ist gerade in Ihrem Browser gelaufen; das heutige Ergebnis steht unter jeder Zeile.
<script type="module">
import { Calendar, Language, formatDate, wallTime }
from 'https://waqt.qudqu.com/api/v1/waqt.js';
// Today on Afghan time, as a day number
const today = wallTime(Date.now()).day;
console.log(formatDate(today, Calendar.SHAMSI, Language.DARI).text);
// → …
console.log(formatDate(today, Calendar.QAMARI, Language.PASHTO).text);
// → …
console.log(formatDate(today, Calendar.GREGORIAN, Language.ENGLISH).text);
// → …
</script>Die Dateien
| Datei | Was sie enthält | Größe |
|---|---|---|
| calendar.json | Die Jahrestabellen von Schamsi und Qamari, was eine Tagesnummer ist, die afghanische Zeit | 3 KB |
| names.json | Die Monate der drei Kalender, die Wochentage und die Ziffern, in sieben Sprachen | 3 KB |
| places.json | Die 34 Provinzhauptstädte: Koordinaten, die Namen von Stadt und Provinz in sieben Sprachen | 4 KB |
| sun/kabul.json | Die Sonne an jedem Tag des Schamsi-Jahres; eine Datei für jede Provinzhauptstadt | 4 KB |
| waqt.js | Das JavaScript-Modul: Datumsangaben umrechnen und schreiben, afghanische Zeit, Sonne und Mond | 20 KB |
Umrechnen mit Tagesnummern
Jedes Datum hat eine Tagesnummer: die Tage seit dem 1. Januar 1970. Alle drei Kalender lassen sich in Tagesnummern umrechnen und zurück, so kommt ein Datum über seine Tagesnummer von einem Kalender in den anderen.
Das Modul macht das mit einer Funktion. Ohne das Modul ist es auch einfach: Suchen Sie in calendar.json das letzte Jahr, das an diesem Tag oder davor beginnt, und zählen Sie dann die Monate.
import {
Calendar, Digits, HijriAdjustment, Language,
formatDate, fromGregorian, fromShamsi,
toGregorian, toQamari, toShamsi, wallTime
} from 'https://waqt.qudqu.com/api/v1/waqt.js';
// A date is a day number: whole days since 1 January 1970
const nowruz = fromGregorian(2026, 3, 21);
console.log(nowruz);
// → 20533
console.log(toShamsi(nowruz));
// → { year: 1405, month: 1, day: 1 }
console.log(toQamari(nowruz));
// → { year: 1447, month: 10, day: 2 }
console.log(toGregorian(fromShamsi(1404, 12, 29)));
// → { year: 2026, month: 3, day: 20 }
// If the month began a day later in Afghanistan than in Umm al-Qura
console.log(toQamari(nowruz, HijriAdjustment.DAY_LATER));
// → { year: 1447, month: 10, day: 1 }
// As text, in any of the seven languages
console.log(formatDate(nowruz, Calendar.SHAMSI, Language.DARI).text);
// → ۱ حمل ۱۴۰۵
console.log(formatDate(nowruz, Calendar.SHAMSI, Language.PASHTO).text);
// → ۱ وری ۱۴۰۵
console.log(formatDate(nowruz, Calendar.QAMARI, Language.ENGLISH).text);
// → 2 Shawwal 1447
// With the weekday, in Latin digits
const options = { weekday: true, digits: Digits.LATIN };
console.log(formatDate(nowruz, Calendar.SHAMSI, Language.DARI, options).text);
// → شنبه، 1 حمل 1405
// Today, on Afghan time
const today = wallTime(Date.now()).day;
console.log(formatDate(today, Calendar.QAMARI, Language.DARI).text);<?php
$api = 'https://waqt.qudqu.com/api/v1/';
$calendar = json_decode(file_get_contents($api . 'calendar.json'), true);
$names = json_decode(file_get_contents($api . 'names.json'), true);
$names = $names['languages'];
// A date as a day number: whole days since 1 January 1970
function day_number(array $calendar, string $date): int
{
$utc = new DateTimeZone('UTC');
$day = intdiv((new DateTimeImmutable($date, $utc))->getTimestamp(), 86400);
$range = $calendar['range'];
if ($day < $range['firstDay'] || $day > $range['lastDay']) {
throw new RangeException('outside the supported range');
}
return $day;
}
// The last year that starts on or before the day
function year_index(array $starts, int $day): int
{
$i = 0;
while ($i + 1 < count($starts) && $starts[$i + 1] <= $day) {
$i++;
}
return $i;
}
function to_shamsi(array $s, int $day): array
{
$i = year_index($s['yearStarts'], $day);
$rest = $day - $s['yearStarts'][$i];
$month = 1;
while ($month < 12 && $rest >= $s['monthLengths'][$month - 1]) {
$rest -= $s['monthLengths'][$month - 1];
$month++;
}
return [$s['firstYear'] + $i, $month, $rest + 1];
}
function to_qamari(array $q, int $day): array
{
$i = year_index($q['yearStarts'], $day);
$rest = $day - $q['yearStarts'][$i];
for ($month = 1; $month < 12; $month++) {
$length = ($q['monthLengthBits'][$i] >> ($month - 1)) & 1 ? 30 : 29;
if ($rest < $length) {
break;
}
$rest -= $length;
}
return [$q['firstYear'] + $i, $month, $rest + 1];
}
$nowruz = day_number($calendar, '2026-03-21');
echo implode('-', to_shamsi($calendar['shamsi'], $nowruz)), "\n";
// → 1405-1-1
echo implode('-', to_qamari($calendar['qamari'], $nowruz)), "\n";
// → 1447-10-2
// If the month began a day later in Afghanistan than in Umm al-Qura
echo implode('-', to_qamari($calendar['qamari'], $nowruz - 1)), "\n";
// → 1447-10-1
[$year, $month, $day] = to_shamsi($calendar['shamsi'], $nowruz);
echo $day, ' ', $names['fa']['months']['shamsi'][$month - 1], ' ', $year, "\n";
// → 1 حمل 1405
echo $day, ' ', $names['ps']['months']['shamsi'][$month - 1], ' ', $year, "\n";
// → 1 وری 1405Das Qamari-Datum und die Mondsichtung
Die Qamari-Tabelle ist der Umm-al-Qura-Kalender. In Afghanistan beginnt ein Qamari-Monat, wenn die neue Mondsichel gesehen wird, und das lässt sich nicht im Voraus berechnen: Ein Datum weicht manchmal um einen Tag von der Tabelle ab. Begann ein Monat einen Tag später, als die Tabelle sagt, lesen Sie die Tabelle am Tag davor (Tagesnummer minus 1); begann er einen Tag früher, am Tag danach. Die Funktionen des Moduls nehmen dasselbe als HijriAdjustment.DAY_LATER oder HijriAdjustment.DAY_EARLIER.
Monats- und Wochentagsnamen in sieben Sprachen
names.json enthält für jede Sprache die Monate der drei Kalender, die Wochentage ab Samstag, „vormittags“ und „nachmittags“, die Namen der Kalender und die Ziffern der Sprache. Paschto hat eigene Monatsnamen; die anderen Sprachen schreiben die Dari-Namen in ihrer eigenen Schrift.
Kein iranischer Monatsname steht in diesen Dateien, und unsere Tests prüfen jeden Tag in jeder Sprache. Nehmen Sie die Namen aus dieser Datei, nicht vom Browser: Viele Browser zeigen für Afghanistan iranische Namen.
{
"languages": {
"fa": {
"months": {
"shamsi": [
"حمل", "ثور", "جوزا", "سرطان", "اسد", "سنبله",
"میزان", "عقرب", "قوس", "جدی", "دلو", "حوت"
],
"qamari": ["محرم", …],
"gregorian": ["جنوری", …]
},
"weekdays": [
"شنبه", "یکشنبه", "دوشنبه", "سهشنبه",
"چهارشنبه", "پنجشنبه", "جمعه"
],
"digits": "۰۱۲۳۴۵۶۷۸۹",
…
},
"ps": {
"months": {
"shamsi": [
"وری", "غویی", "غبرګولی", "چنګاښ", "زمری", "وږی",
"تله", "لړم", "لیندۍ", "مرغومی", "سلواغه", "کب"
],
"qamari": ["محرم", …],
"gregorian": ["جنوري", …]
},
"weekdays": [
"شنبه", "یکشنبه", "دوشنبه", "سه شنبه",
"چهارشنبه", "پنجشنبه", "جمعه"
],
"digits": "۰۱۲۳۴۵۶۷۸۹",
…
},
"en": { "months": { "shamsi": ["Hamal", "Sawr", "Jawza", …] }, … },
…
}
}Sonnenaufgang und Sonnenuntergang
Für jede Provinzhauptstadt gibt es eine Tabelle: erstes Licht, Sonnenaufgang, Sonnenhöchststand, Sonnenuntergang, Dunkelheit und die Tageslänge, für jeden Tag des Schamsi-Jahres, in afghanischer Zeit. Die Tabelle gilt für jedes Jahr auf 2 Minuten genau, denn das Schamsi-Jahr folgt der Sonne.
Für die genaue Minute in einem bestimmten Jahr oder für jeden anderen Ort nehmen Sie sunDay. Die Formel dazu steht hier auch in PHP.
// A sun table needs no code: months[m - 1][d - 1] is Shamsi month m, day d
const url = 'https://waqt.qudqu.com/api/v1/sun/herat.json';
const table = await (await fetch(url)).json();
console.log(table.columns);
// → [ 'firstLight', 'sunrise', 'noon', 'sunset', 'dark', 'dayLength' ]
console.log(table.months[0][0]); // 1 Hamal
// → [ '05:30', '06:25', '12:29', '18:33', '19:27', '12:08' ]import {
Language, findPlace, formatTime, fromShamsi, sunDay, wallTime
} from 'https://waqt.qudqu.com/api/v1/waqt.js';
// Any day, any place: sunDay(day, latitude, longitude)
const herat = findPlace('herat');
const day = fromShamsi(1405, 1, 1);
const sun = sunDay(day, herat.latitude, herat.longitude);
// Instants are milliseconds: on Afghan time, to the nearest minute
const clock = (ms) => {
const minutes = Math.round(wallTime(ms).seconds / 60);
return formatTime(minutes * 60, Language.ENGLISH).clock;
};
console.log(clock(sun.sunrise), clock(sun.sunset));
// → 06:24 18:33
console.log(clock(sun.nauticalDawn), clock(sun.nauticalDusk));
// → 05:30 19:28<?php
// First light, sunrise, solar noon, sunset and nightfall, any day and place.
// The formula of waqt.js: the Astronomical Almanac's low-precision sun (about
// a hundredth of a degree), solved for each height of the sun. Instants are
// seconds since 1970, UTC.
const DAY = 86400;
// An angle in radians, into -pi to pi
function wrap(float $a): float
{
return atan2(sin($a), cos($a));
}
// The sun's declination and hour angle at the longitude, in radians
function position(float $t, float $longitude): array
{
// Days since 1 January 2000, 12:00 UTC
$n = $t / DAY + 2440587.5 - 2451545.0;
$meanLongitude = 280.46 + 0.9856474 * $n;
$anomaly = deg2rad(357.528 + 0.9856003 * $n);
$centre = 1.915 * sin($anomaly) + 0.02 * sin(2 * $anomaly);
$ecliptic = deg2rad($meanLongitude + $centre);
$tilt = deg2rad(23.439 - 0.0000004 * $n);
$y = cos($tilt) * sin($ecliptic);
$rightAscension = atan2($y, cos($ecliptic));
$declination = asin(sin($tilt) * sin($ecliptic));
$sidereal = deg2rad(280.46061837 + 360.98564736629 * $n + $longitude);
return [$declination, wrap($sidereal - $rightAscension)];
}
function solar_noon(int $day, float $longitude, int $offsetMinutes): float
{
$t = $day * DAY - $offsetMinutes * 60 + DAY / 2;
for ($k = 0; $k < 4; $k++) {
$t -= position($t, $longitude)[1] / (2 * M_PI) * DAY;
}
return $t;
}
// When the sun passes a height (degrees) before (-1) or after (1) noon;
// null when it doesn't get there that day
function crossing(
float $noon,
float $latitude,
float $longitude,
float $height,
int $side
): ?float {
$phi = deg2rad($latitude);
$t = $noon;
for ($k = 0; $k < 8; $k++) {
[$declination, $hourAngle] = position($t, $longitude);
$top = sin(deg2rad($height)) - sin($phi) * sin($declination);
$c = $top / (cos($phi) * cos($declination));
if ($c < -1 || $c > 1) {
return null;
}
$step = wrap($side * acos($c) - $hourAngle) / (2 * M_PI) * DAY;
$t += $step;
if (abs($step) < 0.2) {
break;
}
}
return $t;
}
// The sun's day at a place; $offsetMinutes: the clock's offset from UTC
// (270 in all of Afghanistan)
function sun_day(
string $date,
float $latitude,
float $longitude,
int $offsetMinutes = 270
): array {
$utc = new DateTimeZone('UTC');
$day = intdiv((new DateTimeImmutable($date, $utc))->getTimestamp(), DAY);
$noon = solar_noon($day, $longitude, $offsetMinutes);
return [
'firstLight' => crossing($noon, $latitude, $longitude, -12, -1),
'sunrise' => crossing($noon, $latitude, $longitude, -0.833, -1),
'noon' => $noon,
'sunset' => crossing($noon, $latitude, $longitude, -0.833, 1),
'dark' => crossing($noon, $latitude, $longitude, -12, 1),
];
}
// An instant as hours and minutes on the clock, to the nearest minute
function clock(float $t, int $offsetMinutes = 270): string
{
$minutes = (int) round($t / 60) + $offsetMinutes;
return sprintf('%02d:%02d', intdiv($minutes, 60) % 24, $minutes % 60);
}
$herat = sun_day('2026-03-21', 34.342, 62.203);
echo implode(' ', array_map('clock', $herat)), "\n";
// → 05:30 06:24 12:28 18:33 19:28Der Mond
Das Modul gibt die Stellung des Mondes am Himmel von jedem Ort aus, wie viel von ihm beleuchtet ist, seinen Auf- und Untergang an jedem Tag und den nächsten Neu- und Vollmond. Für die Sichtung der ersten Sichel eines Monats ist es nicht gedacht.
import {
MoonPhase, moonState, nextMoonPhase
} from 'https://waqt.qudqu.com/api/v1/waqt.js';
// The moon over Kabul on an evening (or moonState(ms, latitude, longitude))
const evening = Date.parse('2026-03-21T19:00:00+04:30');
const moon = moonState(evening);
// Percent lit, and days since the new moon
console.log(Math.round(moon.lit * 100), moon.age.toFixed(1));
// → 9 2.8
const full = nextMoonPhase(evening, MoonPhase.FULL);
console.log(new Date(full).toISOString().slice(0, 16));
// → 2026-04-02T02:14Version 1: was sich nicht ändert
- Die Dateien behalten ihre Form. Es kann etwas hinzukommen, aber kein Name wird entfernt oder geändert. Eine Änderung, die diese Regel nicht einhält, wird /api/v2/, und Version 1 bleibt.
- Vom 1. Januar 1900 bis zum 25. November 2174 (Schamsi 1278 bis 1553, Qamari 1317 bis 1600). Außerhalb davon geben die Funktionen einen Fehler.
- Von jeder Website. Die Dateien werden mit Access-Control-Allow-Origin: * gesendet, und Browser behalten sie 10 Minuten.
- Keine Statistik, keine Cookies. Die Dateien setzen keine Cookies und sammeln keine Statistiken.
Lizenz
Lizenz: CC BY 4.0
Einen Fehler gesehen, oder fehlt etwas? Schreiben Sie uns.