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 :
| Forme | Où la trouver | Contenu |
|---|---|---|
Entité (ITimeIntervalEntitySchedule) | attributeValues[marker].value[].values[] sur les pages, produits, blocs et ensembles d'attributs | une plage dates avec des paires times |
Formulaire (ITimeIntervalSchedule) | attributes[].localizeInfos.intervals[] sur les formulaires | une 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' };
fromettoacceptent uneDate, une chaîne ISO ou des millisecondes epoch.- Les deux bornes sont incluses et comparées par jour UTC ; l'heure dans
from/toest 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.inEveryWeekrépète tous les 7 jours à partir de l'ancrage.inEveryMonthré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) :
| Type | Décrit |
|---|---|
ITimeIntervalAttributeValue | Un IAttributeValue restreint à type: 'timeInterval', dont la value est un tableau de groupes |
ITimeIntervalGroup | Une entrée de la value de l'attribut : des plannings qui partagent un intervalId |
ITimeIntervalEntitySchedule | Un planning d'entité : dates, times, inEveryWeek, inEveryMonth |
ITimeIntervalSchedule | Un planning de formulaire : range, intervals, inEveryWeek, inEveryMonth |
ITimeIntervalRange | Une plage quotidienne avec start, end et une period de créneau en minutes (null si non découpée) |
ITimeIntervalPoint | Un instant de la journée : { hours, minutes } |
ITimeIntervalWindow | La fenêtre de développement : { from, to } |
TimeIntervalPair | Un 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
- Valeurs d'attributs : la forme normalisée de chaque valeur d'attribut
- Importer les types : importer
ITimeIntervalWindowet les types associés - Module Forms : attributs de formulaire avec
localizeInfos.intervals