Intervalos de tiempo
Un atributo timeInterval es una regla de recurrencia, no una lista de franjas: una fecha de anclaje, rangos horarios diarios e indicadores de repetición. Para convertirlo en pares [start, end] concretos para la ventana que muestras, usa las utilidades de nivel superior expandAttributeTimeIntervals y expandTimeIntervals y la guarda de tipo 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'], …]
Las tres utilidades son puras: no modifican su entrada ni hacen solicitudes.
Dónde están los horarios
La API devuelve los horarios con dos formas, y las utilidades aceptan ambas:
| Forma | Dónde encontrarla | Contiene |
|---|---|---|
Entidad (ITimeIntervalEntitySchedule) | attributeValues[marker].value[].values[] en páginas, productos, bloques y conjuntos de atributos | un rango dates con pares times |
Formulario (ITimeIntervalSchedule) | attributes[].localizeInfos.intervals[] en los formularios | un range con intervals que llevan un period de franja en minutos |
expandAttributeTimeIntervals(attr, window)
Despliega un atributo de entidad en una sola llamada: recorre los grupos y horarios del atributo, despliega cada uno y combina los resultados. La combinación es importante, porque la eliminación de duplicados y el orden solo se garantizan dentro de un único horario; si combinas los grupos a mano, puedes obtener franjas duplicadas o desordenadas.
Para cualquier cosa que no sea un atributo timeInterval devuelve un array vacío, así que puedes llamarla sin comprobar antes 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)
Despliega un único horario. Úsala cuando ya tienes uno, normalmente en los formularios, cuyos horarios ya están tipados en 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 tiene el tipo unknown, porque su forma depende de type. Esta guarda de tipo acota un atributo a ITimeIntervalAttributeValue, para que puedas acceder a los horarios sin una conversión de tipo:
import { isTimeIntervalAttribute } from 'oneentry';
const attr = page.attributeValues.interval;
if (isTimeIntervalAttribute(attr)) {
attr.value[0].values[0].dates; // fully typed
}
La ventana
const window = { from: '2025-04-01', to: '2025-04-30' };
fromytoaceptan unDate, una cadena ISO o milisegundos desde epoch.- Ambos límites son inclusivos y se comparan por día UTC; la hora del día en
from/tose ignora. - La ventana es obligatoria: un horario es una regla de recurrencia abierta, y solo tú sabes hasta dónde desplegarla.
Semántica de la recurrencia
dates[0]/range[0]es a la vez la fase de la recurrencia y el primer día válido. No se devuelve nada anterior, por amplia que sea la ventana.dates[1]/range[1]termina la validez. Si no es posterior al inicio, el horario se ancla a ese único día; con un indicador de recurrencia activado, la recurrencia pasa a ser abierta y solo la ventana limita el resultado.inEveryWeekse repite cada 7 días a partir del anclaje.inEveryMonthse repite el mismo día del mes y omite los meses que son demasiado cortos.- Con ambas opciones activadas, se aplica la regla semanal.
- Sin ningún indicador, el horario es un simple rango de fechas: cada día del rango produce franjas.
- El resultado no tiene duplicados y está ordenado por inicio y luego por fin.
- Todos los cálculos se hacen en UTC, así que el resultado no depende de la zona horaria de la máquina.
Migrar desde el campo timeIntervals
Las versiones anteriores del SDK añadían un array timeIntervals calculado a cada valor de atributo timeInterval. Ese campo ya no existe. Contenía un año completo de franjas independientemente de lo que necesitara quien hacía la llamada: un solo atributo con franjas de una hora se desplegaba en unas 2000 líneas de JSON, y con periodos de franja más finos se llegaba a megabytes, suficiente para superar los límites de la caché de datos de los frameworks. Además, nunca se declaró en ninguna interfaz ni esquema, así que el código TypeScript solo podía acceder a él mediante una conversión de tipo.
Antes, se leía el campo precalculado:
const slots = page.attributeValues.interval.value[0].values[0].timeIntervals;
Ahora, expande la ventana que realmente renderizas:
import { expandAttributeTimeIntervals } from 'oneentry';
const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});
Los datos de origen (dates/range, times/intervals, inEveryWeek, inEveryMonth) no cambian y siguen presentes en cada horario. No se pierde nada: las franjas se calculan bajo demanda en lugar de por adelantado, y lo que se almacena en caché es la regla compacta.
Los métodos _addTimeIntervalsToSchedules y _addTimeIntervalsToFormSchedules también se eliminaron de todos los módulos (a pesar del prefijo _, se podían llamar, p. ej., Pages._addTimeIntervalsToSchedules). Usa expandTimeIntervals en su lugar.
Tipos
Todos ellos se exportan desde la raíz del paquete y desde oneentry/types (consulta Importar tipos):
| Tipo | Describe |
|---|---|
ITimeIntervalAttributeValue | Un IAttributeValue acotado a type: 'timeInterval', cuyo value es un array de grupos |
ITimeIntervalGroup | Una entrada del value del atributo: horarios que comparten un intervalId |
ITimeIntervalEntitySchedule | Un horario de entidad: dates, times, inEveryWeek, inEveryMonth |
ITimeIntervalSchedule | Un horario de formulario: range, intervals, inEveryWeek, inEveryMonth |
ITimeIntervalRange | Un rango diario con start, end y un period de franja en minutos (null cuando no está dividido) |
ITimeIntervalPoint | Un momento del día: { hours, minutes } |
ITimeIntervalWindow | La ventana de despliegue: { from, to } |
TimeIntervalPair | Una franja resuelta: [start, end], ambas cadenas ISO 8601 en UTC |
Ejemplo: mostrar un mes de franjas
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]>>);
Relacionado
- Valores de atributos: la forma normalizada de cada valor de atributo
- Importar tipos: importar
ITimeIntervalWindowy los tipos relacionados - Módulo Forms: atributos de formulario con
localizeInfos.intervals