بهطور خلاصههمهٔ فایلها در waqt.qudqu.com/api/v1/ هستند و از هر سایتی باز میشوند. هر فایل از همان کودی ساخته میشود که این سایت به کار میبرد، پس API و سایت هیچگاه دو تاریخ مختلف نمیدهند. هیچ نام ماه ایرانی در آنها نیست.
شروع سریع
یک خط import در یک <script type="module"> کافی است: نه نصب، نه کلید، نه ثبتنام. این کود همین حالا در مرورگر شما اجرا شد؛ جواب امروز زیر هر خط است.
<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>فایلها
| فایل | چه دارد | اندازه |
|---|---|---|
| calendar.json | جدول سالهای شمسی و قمری، تعریف شمارهٔ روز، وقت افغانستان | ۳ کیلوبایت |
| names.json | نام ماههای سه تقویم، روزهای هفته و رقمها، به هفت زبان | ۳ کیلوبایت |
| places.json | ۳۴ مرکز ولایت: مختصات، نام شهر و ولایت به هفت زبان | ۴ کیلوبایت |
| sun/kabul.json | وقت آفتاب برای هر روز سال شمسی؛ یک فایل برای هر مرکز ولایت | ۴ کیلوبایت |
| waqt.js | مادیول JavaScript: تبدیل و نوشتن تاریخ، وقت افغانستان، آفتاب و مهتاب | ۲۰ کیلوبایت |
تبدیل تاریخ با شمارهٔ روز
هر تاریخ یک شمارهٔ روز دارد: شمار روزها از اول جنوری ۱۹۷۰. هر سه تقویم به شمارهٔ روز و از آن تبدیل میشوند، پس یک تاریخ از راه شمارهٔ روز از یک تقویم به تقویم دیگر میرود.
مادیول این کار را با یک فنکشن میکند. بدون مادیول هم ساده است: در calendar.json آخرین سالی را پیدا کنید که پیش از آن روز یا در همان روز شروع میشود، بعد ماهها را بشمارید.
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 وری 1405تاریخ قمری و دیدن هلال
جدول قمری از تقویم امالقری است. در افغانستان ماه قمری با دیدن هلال شروع میشود، و این را از پیش نمیتوان حساب کرد: تاریخ گاهی یک روز با جدول فرق میکند. اگر ماه یک روز دیرتر از جدول شروع شد، جدول را در روز پیش بخوانید (شمارهٔ روز منهای ۱)؛ اگر یک روز زودتر، در روز بعد. فنکشنهای مادیول همین را به شکل HijriAdjustment.DAY_LATER یا HijriAdjustment.DAY_EARLIER میگیرند.
نام ماهها و روزها به هفت زبان
names.json برای هر زبان نام ماههای سه تقویم، روزهای هفته از شنبه، «قبل از ظهر» و «بعد از ظهر»، نام تقویمها و رقمهای آن زبان را دارد. پشتو نامهای خود را دارد؛ زبانهای دیگر نامهای دری را به خط خود مینویسند.
هیچ نام ماه ایرانی در این فایلها نیست، و تستهای ما هر روز را در هر زبان میسنجند. نامها را از این فایل بگیرید، نه از مرورگر: بسیاری از مرورگرها برای افغانستان نامهای ایرانی نشان میدهند.
{
"languages": {
"fa": {
"months": {
"shamsi": [
"حمل", "ثور", "جوزا", "سرطان", "اسد", "سنبله",
"میزان", "عقرب", "قوس", "جدی", "دلو", "حوت"
],
"qamari": ["محرم", …],
"gregorian": ["جنوری", …]
},
"weekdays": [
"شنبه", "یکشنبه", "دوشنبه", "سهشنبه",
"چهارشنبه", "پنجشنبه", "جمعه"
],
"digits": "۰۱۲۳۴۵۶۷۸۹",
…
},
"ps": {
"months": {
"shamsi": [
"وری", "غویی", "غبرګولی", "چنګاښ", "زمری", "وږی",
"تله", "لړم", "لیندۍ", "مرغومی", "سلواغه", "کب"
],
"qamari": ["محرم", …],
"gregorian": ["جنوري", …]
},
"weekdays": [
"شنبه", "یکشنبه", "دوشنبه", "سه شنبه",
"چهارشنبه", "پنجشنبه", "جمعه"
],
"digits": "۰۱۲۳۴۵۶۷۸۹",
…
},
"en": { "months": { "shamsi": ["Hamal", "Sawr", "Jawza", …] }, … },
…
}
}طلوع و غروب آفتاب
برای هر مرکز ولایت یک جدول هست: روشنی صبح، طلوع، ظهر آفتابی، غروب، تاریکی شب و درازی روز، برای هر روز سال شمسی، به وقت افغانستان. جدول برای هر سال درست است، با کمتر از ۲ دقیقه فرق، چون سال شمسی با آفتاب میرود.
برای دقیقهٔ دقیق یک سال، یا برای هر جای دیگر، فنکشن sunDay را به کار ببرید. فورمول آن به 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:28مهتاب
مادیول جای مهتاب در آسمان هر جا، اندازهٔ روشن آن، طلوع و غروب آن در هر روز، و وقت ماه نو و ماه تمام بعدی را میدهد. برای دیدن هلال اول ماه نیست.
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:14نسخهٔ ۱: آنچه تغییر نمیکند
- شکل فایلها ثابت است. ممکن است چیزی به آنها اضافه شود، اما هیچ نامی برداشته یا عوض نمیشود. تغییری که به این قاعده صدق نکند، /api/v2/ میشود و نسخهٔ ۱ میماند.
- از ۱ جنوری ۱۹۰۰ تا ۲۵ نومبر ۲۱۷۴ (۱۲۷۸ تا ۱۵۵۳ شمسی، ۱۳۱۷ تا ۱۶۰۰ قمری). بیرون از این، فنکشنها خطا میدهند.
- از هر سایتی. فایلها با Access-Control-Allow-Origin: * فرستاده میشوند، و مرورگرها ۱۰ دقیقه نگهشان میدارند.
- بدون آمار و کوکی. فایلها هیچ کوکی نمیگذارند و هیچ آماری جمع نمیکنند.
شرایط استفاده
مجوز: CC BY 4.0
اشتباهی دیدید، یا چیزی کم است؟ به ما بنویسید.