Aller au contenu principal

Intervalles de temps

Un attribut timeInterval est une règle de récurrence, et non une liste de créneaux : une date d'ancrage, des plages horaires quotidiennes et des indicateurs de répétition. Pour le transformer en paires concrètes [start, end] pour la fenêtre que vous affichez, utilisez les utilitaires de premier niveau expandAttributeTimeIntervals et expandTimeIntervals ainsi que la garde de type 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'], …]

Les trois utilitaires sont purs : ils ne modifient pas leur entrée et n'effectuent aucune requête.

Où se trouvent les plannings​

L'API renvoie les plannings sous deux formes, et les utilitaires acceptent les deux :

FormeOù la trouverContenu
Entité (ITimeIntervalEntitySchedule)attributeValues[marker].value[].values[] sur les pages, produits, blocs et ensembles d'attributsune plage dates avec des paires times
Formulaire (ITimeIntervalSchedule)attributes[].localizeInfos.intervals[] sur les formulairesune range avec des intervals portant une period de créneau en minutes

expandAttributeTimeIntervals(attr, window)​

Développe un attribut d'entité en un seul appel : il parcourt les groupes et les plannings de l'attribut, développe chacun d'eux et fusionne les résultats. La fusion est importante, car la déduplication et le tri ne valent qu'au sein d'un même planning ; combiner les groupes à la main peut produire des créneaux en double ou non triés.

Pour tout ce qui n'est pas un attribut timeInterval, il renvoie un tableau vide : vous pouvez donc l'appeler sans vérifier type au préalable.

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)​

Développe un seul planning. Utilisez-le lorsque vous en avez déjà un, généralement sur les formulaires, dont les plannings sont déjà typés dans 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 est typé unknown, car sa forme dépend de type. Cette garde de type affine un attribut en ITimeIntervalAttributeValue, pour que vous puissiez accéder aux plannings sans conversion de type :

import { isTimeIntervalAttribute } from 'oneentry';

const attr = page.attributeValues.interval;

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

La fenêtre​

const window = { from: '2025-04-01', to: '2025-04-30' };
  • from et to acceptent une Date, une chaîne ISO ou des millisecondes epoch.
  • Les deux bornes sont incluses et comparées par jour UTC ; l'heure dans from/to est ignorée.
  • La fenêtre est obligatoire : un planning est une règle de récurrence sans fin, et vous seul savez jusqu'où le développer.

Sémantique de la récurrence​

  • dates[0] / range[0] est à la fois la phase de la récurrence et le premier jour valide. Rien d'antérieur n'est renvoyé, quelle que soit la largeur de la fenêtre.
  • dates[1] / range[1] met fin à la validité. S'il n'est pas postérieur au début, le planning est ancré sur ce seul jour ; si un indicateur de récurrence est défini, la récurrence est alors sans fin et seule la fenêtre limite le résultat.
  • inEveryWeek répète tous les 7 jours à partir de l'ancrage.
  • inEveryMonth répète le même jour du mois, en sautant les mois trop courts.
  • Si les deux indicateurs sont définis, c'est la règle hebdomadaire qui s'applique.
  • Sans aucun indicateur, le planning est une simple plage de dates : chaque jour de la plage produit des créneaux.
  • Le résultat est dédupliqué et trié par début, puis par fin.
  • Tous les calculs se font en UTC : le résultat ne dépend pas du fuseau horaire de la machine.

Migrer depuis le champ timeIntervals​

Les versions précédentes du SDK ajoutaient un tableau calculé timeIntervals à chaque valeur d'attribut timeInterval. Ce champ n'existe plus. Il contenait une année complète de créneaux, quels que soient les besoins de l'appelant : un seul attribut avec des créneaux horaires se développait en environ 2 000 lignes de JSON, et des périodes plus fines atteignaient plusieurs mégaoctets, de quoi dépasser les limites du cache de données des frameworks. Il n'était déclaré dans aucune interface ni aucun schéma : le code TypeScript ne pouvait donc y accéder que par une conversion de type.

Auparavant, vous lisiez le champ précalculé :

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

Développez maintenant la fenêtre que vous affichez réellement :

import { expandAttributeTimeIntervals } from 'oneentry';

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

Les données sources (dates/range, times/intervals, inEveryWeek, inEveryMonth) sont inchangées et toujours présentes dans chaque planning. Rien n'est perdu : les créneaux sont calculés à la demande plutôt qu'à l'avance, et c'est la règle compacte qui est mise en cache.

Les méthodes _addTimeIntervalsToSchedules et _addTimeIntervalsToFormSchedules ont également été retirées de tous les modules (malgré le préfixe _, elles pouvaient être appelées, par ex. Pages._addTimeIntervalsToSchedules). Utilisez expandTimeIntervals à la place.

Types​

Tous sont exportés depuis la racine du paquet et depuis oneentry/types (voir Importer les types) :

TypeDécrit
ITimeIntervalAttributeValueUn IAttributeValue restreint à type: 'timeInterval', dont la value est un tableau de groupes
ITimeIntervalGroupUne entrée de la value de l'attribut : des plannings qui partagent un intervalId
ITimeIntervalEntityScheduleUn planning d'entité : dates, times, inEveryWeek, inEveryMonth
ITimeIntervalScheduleUn planning de formulaire : range, intervals, inEveryWeek, inEveryMonth
ITimeIntervalRangeUne plage quotidienne avec start, end et une period de créneau en minutes (null si non découpée)
ITimeIntervalPointUn instant de la journée : { hours, minutes }
ITimeIntervalWindowLa fenêtre de développement : { from, to }
TimeIntervalPairUn créneau résolu : [start, end], deux chaînes ISO 8601 UTC

Exemple : afficher un mois de créneaux​

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]>>);

Voir aussi​