يخطئ مؤقت الخرق على أيام العمل في الاتجاهين ما لم يحدد العقد التقويم ويوم بدء العدّ والمنطقة الزمنية. توفر Narwhal العطل الرسمية لبلد وسنة، أما كل قاعدة أخرى فمصدرها كود المكتب والعقد.
ابدأ المؤقت من تقويم يمكن للعقد تسميته
المؤقت الذي يعمل خلال عطلة رسمية يُظهر خرقًا لم يسمح به العقد قط. والمؤقت الذي يتوقف في يوم لا يستثنيه العقد يُخفي خرقًا حقيقيًا. الحل تقويم يمكن للطرفين الإشارة إليه. يقرأ هذا الطلب العطل الرسمية في سنغافورة لعام 2026 ويُبقي على الإدخالين المحيطين بـ Deepavali.
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/calendars/holidays/SGP/2026"{
"country": "SGP",
"coverage": [
{
"scope": "national_public",
"subdivision_codes": []
}
],
"holidays": [
{
"date": "2026-11-08",
"name": "Deepavali",
"holiday_key": "deepavali",
"scope": "national_public",
"subdivision_codes": []
},
{
"date": "2026-11-09",
"name": "Deepavali (Observed)",
"holiday_key": "deepavali",
"scope": "national_public",
"subdivision_codes": [],
"observed": true
}
]
}لكل إدخال date وname وscope وsubdivision_codes. تاريخ Deepavali هو الأحد 8 نوفمبر. أما الإدخال الموسوم observed: true فهو الاثنين 9 نوفمبر، يوم العطلة البديلة، ويقع في يوم عمل. وتسمّي قائمة coverage النطاقات التي يحتويها التقويم، وهي national_public لسنغافورة. لا توفر الـ API سوى العطل، فبقية الساعة شأن تعاقدي.
ما الذي يجب أن يحدده العقد قبل تشغيل الكود
يحتاج الكود إلى إجابة عن كل صف في الجدول. وحيث يسكت العقد، سيكتشف المكتب والعميل ذلك عند أول تذكرة متنازع عليها.
| الإعداد | السؤال الموجَّه إلى العقد | الجهة المزوِّدة |
|---|---|---|
| التقويم | أي بلد، وأي نطاق للعطل؟ | العقد، ثم مرشِّح scope في الـ API |
| الأيام المحسوبة | هل يُستثنى السبت والأحد؟ | العقد |
| اليوم الأول | هل يوم الفتح هو اليوم 0 أم اليوم 1؟ | العقد |
| الموعد النهائي | هل موعد الاستحقاق هو نهاية ذلك اليوم؟ | العقد |
| المنطقة الزمنية | تاريخ أي منطقة محلي يبدأ الساعة؟ | العقد |
| الوقت الموقوف | هل تتوقف الساعة بينما ينتظر الرد من العميل؟ | العقد ونظام التذاكر |
| ساعات اليوم | هل يعني يوم العمل ساعات الدوام؟ | العقد وجدول الدعم |
حين يكون لكل صف جواب مكتوب يصير المؤقت دالة لا تترك مجالًا للتقدير. وتحسم الـ API صف التقويم فقط ولا شيء غيره.
حساب تاريخ الاستحقاق واختبار الخرق
يجمع السكربت تواريخ العطل في مجموعة ويعدّ يوم العمل أي يوم من أيام الأسبوع خارج المجموعة. يوم الفتح هو اليوم 0 فيبدأ العدّ من اليوم التالي. تحوّل الكتلة الأولى الطابع الزمني للتذكرة إلى التاريخ في المنطقة الزمنية للعقد، وتختبر الكتلة الثانية تذكرة تم حلها.
import json, os, urllib.request
from datetime import date, datetime, timedelta
from zoneinfo import ZoneInfo
def get(path):
req = urllib.request.Request("https://api.narwhalapi.com" + path,
headers={"Authorization": "Bearer " + os.environ["NARWHAL_API_KEY"]})
with urllib.request.urlopen(req, timeout=30) as r:
return json.load(r)
def holiday_dates(country, years):
return {date.fromisoformat(h["date"]) for y in years for h in get(f"/v1/calendars/holidays/{country}/{y}")["holidays"]}
def is_working_day(d, off):
return d.weekday() < 5 and d not in off
def due_date(opened, working_days, off):
d, left = opened, working_days
while left:
d += timedelta(1)
left -= is_working_day(d, off)
return d
def elapsed_working_days(opened, resolved, off):
return sum(is_working_day(opened + timedelta(n), off) for n in range(1, (resolved - opened).days + 1))
off = holiday_dates("SGP", (2026,))
sg = ZoneInfo("Asia/Singapore")
# Clock start: the ticket timestamp becomes a date in the contract's time zone.
created = datetime(2026, 11, 5, 20, 0, tzinfo=ZoneInfo("America/New_York"))
opened = created.astimezone(sg).date()
print("created", created.date(), "in New York is", opened, "in Singapore")
print("3 working days from the Singapore date:", due_date(opened, 3, off))
print("3 working days from the New York date: ", due_date(created.date(), 3, off))
# Breach test: compare the resolution date with the due date.
opened, resolved = date(2026, 2, 13), date(2026, 2, 27)
due = due_date(opened, 5, off)
late = elapsed_working_days(opened, resolved, off) - 5
print("5 working days from", opened, "is due", due, "; resolved", resolved, "so", late, "working days late")
created 2026-11-05 in New York is 2026-11-06 in Singapore
3 working days from the Singapore date: 2026-11-12
3 working days from the New York date: 2026-11-11
5 working days from 2026-02-13 is due 2026-02-24 ; resolved 2026-02-27 so 3 working days lateأُنشئت تذكرة نيويورك يوم الخميس 5 نوفمبر الساعة 20:00، وهو في سنغافورة الجمعة 6 نوفمبر أصلًا. ثلاثة أيام عمل من التاريخ السنغافوري تنتهي يوم الخميس 12 نوفمبر، لأن الاثنين 9 نوفمبر هو عطلة Deepavali المراعاة. أما بالعدّ من تاريخ نيويورك فيحين موعد التذكرة نفسها يوم الأربعاء 11 نوفمبر، أي قبل يوم، فيكون صف المنطقة الزمنية هو ما يحدد هل يخرق المكتب. التذكرة الثانية فُتحت يوم الجمعة 13 فبراير ويحين موعدها يوم الثلاثاء 24 فبراير، لأن رأس السنة الصينية يأخذ الثلاثاء 17 والأربعاء 18 فبراير. وقد حُلّت يوم الجمعة 27 فبراير فهي متأخرة 3 أيام عمل.
كيف يتعامل المؤقت مع عطلة تقع في عطلة نهاية الأسبوع؟
يستبعد اختبار أيام الأسبوع ذلك اليوم أولًا، فلا يُطرح مرتين. تاريخ Hari Raya Puasa هو السبت 21 مارس 2026 في استجابة سنغافورة، وتاريخ Deepavali هو الأحد 8 نوفمبر، ولا يغيّر أي منهما العدّ. العطلة البديلة إدخال مستقل بقيمة observed: true، فتستبعدها الساعة دون كود إضافي.
أي نطاق ينبغي أن تستخدمه اتفاقية مستوى الخدمة؟
استخدم النطاق الذي يطابق التقويم الذي يتبعه نشاط العميل. تعيد سنغافورة national_public وحده، وتعيد إندونيسيا national_public وcollective_leave، وتعيد أستراليا إدخالات إقليمية بقيم subdivision_codes إضافة إلى نطاق bank. تقبل نقطة نهاية السنة مرشِّح scope اختياريًا. مرّره عندما تستثني الاتفاقية نوعًا واحدًا من الأيام، واستخدم النطاق نفسه في كل طلب كي يمكن تكرار العدّ.
هل تستطيع الـ API عدّ ساعات العمل؟
لا. تعيد نقاط نهاية التقويم تواريخ العطل. أما ساعات الدوام واستراحات الغداء والإيقاف المؤقت أثناء انتظار رد العميل فمصدرها جدول الدعم ونظام التذاكر. وفي اتفاقية مكتوبة بالساعات، خذ أيام العمل من هذا الكود ثم طبّق الجدول على اليوم الأول واليوم الأخير.
كيف أقلل الطلبات مع كثرة التذاكر المفتوحة؟
اجلب كل بلد وسنة مرة واحدة، واحتفظ بمجموعة التواريخ في الذاكرة أو في جدول خاص بك. وتعيد كل تذكرة لذلك البلد والسنة استخدام المجموعة نفسها. استدعِ نقطة نهاية السنة مجددًا فقط لتذكرة تمتد إلى سنة لم تحمّلها. ويعرض دليل حساب أيام العمل بين تاريخين الحساب نفسه مع خيار جدول بيانات.
نُشر في .