انتقل إلى المحتوى الرئيسي

الفترات الزمنية

سمة timeInterval هي قاعدة تكرار، وليست قائمة فترات: تاريخ مرجعي، ونطاقات زمنية يومية، وعلامات تكرار. لتحويلها إلى أزواج [start, end] محددة للنافذة التي تعرضها، استخدم الدالتين المساعدتين على المستوى الأعلى expandAttributeTimeIntervals وexpandTimeIntervals وحارس النوع isTimeIntervalAttribute.

import { expandAttributeTimeIntervals } from 'oneentry';

const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});
// [['2025-04-14T09:00:00.000Z', '2025-04-14T10:00:00.000Z'], …]

الدوال المساعدة الثلاث نقية: لا تعدّل مدخلاتها ولا تجري أي طلبات.

أين توجد الجداول الزمنية​

تُعيد واجهة API الجداول الزمنية بشكلين، وتقبل الدوال المساعدة كليهما:

الشكلأين تجدهيحمل
الكيان (ITimeIntervalEntitySchedule)attributeValues[marker].value[].values[] في الصفحات والمنتجات والكتل ومجموعات السماتنطاق dates مع أزواج times
النموذج (ITimeIntervalSchedule)attributes[].localizeInfos.intervals[] في النماذجنطاق range مع intervals تحمل period للفترة بالدقائق

expandAttributeTimeIntervals(attr, window)​

توسّع سمة كيان في استدعاء واحد: تمر على مجموعات السمة وجداولها الزمنية، وتوسّع كل منها وتدمج النتائج. الدمج مهم، لأن إزالة التكرار والترتيب لا يصحّان إلا ضمن جدول زمني واحد؛ ودمج المجموعات يدويًا قد يعطيك فترات مكررة أو غير مرتبة.

لأي شيء ليس سمة timeInterval تُعيد مصفوفة فارغة، فيمكنك استدعاؤها دون التحقق من type أولًا.

import { expandAttributeTimeIntervals } from 'oneentry';

const page = await Pages.getPageByUrl('booking');
if ('statusCode' in page) throw new Error(page.message);

const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});

expandTimeIntervals(schedule, window)​

توسّع جدولًا زمنيًا واحدًا. استخدمها عندما يكون لديك جدول بالفعل، عادةً في النماذج، حيث تكون الجداول محددة النوع أصلًا في localizeInfos.intervals:

import { expandTimeIntervals } from 'oneentry';

const form = await Forms.getFormByMarker('booking_form');
if ('statusCode' in form) throw new Error(form.message);
const field = form.attributes.find((a) => a.marker === 'schedule');

const slots = (field?.localizeInfos.intervals ?? []).flatMap((schedule) =>
expandTimeIntervals(schedule, { from: '2025-05-01', to: '2025-05-31' }),
);

isTimeIntervalAttribute(attr)​

نوع IAttributeValue.value هو unknown، لأن شكله يعتمد على type. يضيّق حارس النوع هذا السمة إلى ITimeIntervalAttributeValue، فتصل إلى الجداول الزمنية دون تحويل نوع:

import { isTimeIntervalAttribute } from 'oneentry';

const attr = page.attributeValues.interval;

if (isTimeIntervalAttribute(attr)) {
attr.value[0].values[0].dates; // fully typed
}

النافذة​

const window = { from: '2025-04-01', to: '2025-04-30' };
  • تقبل from وto قيمة Date أو سلسلة ISO أو أجزاء الثانية منذ epoch.
  • كلا الحدين شاملان ويُقارنان حسب يوم UTC؛ ويُتجاهل الوقت من اليوم في from/to.
  • النافذة إلزامية: الجدول الزمني قاعدة تكرار مفتوحة النهاية، وأنت وحدك تعرف إلى أي مدى توسّعها.

دلالات التكرار​

  • dates[0] / range[0] هو طور التكرار وأول يوم صالح في آن واحد. لا يُعاد شيء قبله، مهما اتسعت النافذة.
  • dates[1] / range[1] ينهي الصلاحية. إذا لم يكن بعد البداية، يُثبَّت الجدول على ذلك اليوم الواحد؛ ومع ضبط علامة تكرار، يصبح التكرار حينها مفتوح النهاية ولا يحد النتيجة سوى حدود النافذة.
  • inEveryWeek يكرر كل 7 أيام بدءًا من التاريخ المرجعي.
  • inEveryMonth يكرر في اليوم نفسه من الشهر، متخطيًا الأشهر الأقصر من اللازم.
  • عند تعيين العلامتين معًا، تُطبَّق القاعدة الأسبوعية.
  • دون أي علامة، يكون الجدول نطاق تواريخ عاديًا: كل يوم فيه يُنتج فترات.
  • تُزال التكرارات من النتيجة وتُرتب حسب البداية ثم حسب النهاية.
  • كل الحسابات بتوقيت UTC، فلا تعتمد النتيجة على المنطقة الزمنية للجهاز.

الترحيل من الحقل timeIntervals​

كانت إصدارات SDK السابقة تضيف مصفوفة timeIntervals محسوبة إلى كل قيمة سمة timeInterval. هذا الحقل لم يعد موجودًا. كان يحمل سنة كاملة من الفترات بغض النظر عما يحتاجه المستدعي: سمة واحدة بفترات كل ساعة كانت تتوسع إلى نحو 2,000 سطر JSON، وفترات أدق كانت تبلغ ميغابايتات، بما يكفي لتجاوز حدود ذاكرة التخزين المؤقت للبيانات في أطر العمل. ولم يُعرَّف قط في أي واجهة أو مخطط، فلم يكن كود TypeScript يصل إليه إلا عبر تحويل نوع.

في السابق، كنت تقرأ الحقل المحسوب مسبقًا:

const slots = page.attributeValues.interval.value[0].values[0].timeIntervals;

الآن، وسّع النافذة التي تعرضها فعلًا:

import { expandAttributeTimeIntervals } from 'oneentry';

const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});

البيانات المصدرية (dates/range، times/intervals، inEveryWeek، inEveryMonth) لم تتغير وما زالت موجودة في كل جدول زمني. لم يُفقد شيء: تُحسب الفترات عند الطلب بدلًا من حسابها مسبقًا، والقاعدة المضغوطة هي ما يُخزن مؤقتًا.

أُزيلت أيضًا الطريقتان _addTimeIntervalsToSchedules و_addTimeIntervalsToFormSchedules من كل وحدة (رغم البادئة _ كان يمكن استدعاؤهما، مثل Pages._addTimeIntervalsToSchedules). استخدم expandTimeIntervals بدلًا منهما.

الأنواع​

جميع هذه الأنواع مُصدَّرة من جذر الحزمة ومن oneentry/types (راجع استيراد الأنواع):

النوعيصف
ITimeIntervalAttributeValueIAttributeValue مضيّقًا إلى type: 'timeInterval'، وقيمته value مصفوفة من المجموعات
ITimeIntervalGroupإدخال واحد من value الخاصة بالسمة: جداول زمنية تتشارك intervalId
ITimeIntervalEntityScheduleجدول زمني واحد لكيان: dates، times، inEveryWeek، inEveryMonth
ITimeIntervalScheduleجدول زمني واحد لنموذج: range، intervals، inEveryWeek، inEveryMonth
ITimeIntervalRangeنطاق يومي مع start وend وperiod للفترة بالدقائق (null عندما لا يكون مقسّمًا)
ITimeIntervalPointنقطة في اليوم: { hours, minutes }
ITimeIntervalWindowنافذة التوسيع: { from, to }
TimeIntervalPairفترة واحدة محلولة: [start, end]، كلاهما سلسلتان ISO 8601 بتوقيت UTC

مثال: عرض فترات شهر​

import { expandAttributeTimeIntervals } from 'oneentry';

const page = await Pages.getPageByUrl('booking');

if ('statusCode' in page) {
throw new Error(page.message);
}

const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});

// Group the slots by day for a calendar view
const byDay = slots.reduce((acc, [start, end]) => {
const day = start.slice(0, 10);
(acc[day] ??= []).push([start, end]);
return acc;
}, {} as Record<string, Array<[string, string]>>);

ذات صلة​