Intervalos de tempo
Um atributo timeInterval é uma regra de recorrência, e não uma lista de horários: uma data de referência, faixas de horário diárias e sinalizadores de repetição. Para transformá-lo em pares concretos [start, end] para a janela que você exibe, use os helpers de nível superior expandAttributeTimeIntervals e expandTimeIntervals e o type guard 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'], …]
Os três helpers são puros: eles não alteram a entrada e não fazem requisições.
Onde ficam as agendas
A API retorna as agendas em dois formatos, e os helpers aceitam ambos:
| Formato | Onde encontrar | Contém |
|---|---|---|
Entidade (ITimeIntervalEntitySchedule) | attributeValues[marker].value[].values[] em páginas, produtos, blocos e conjuntos de atributos | uma faixa dates com pares times |
Formulário (ITimeIntervalSchedule) | attributes[].localizeInfos.intervals[] em formulários | um range com intervals que trazem um period de horário em minutos |
expandAttributeTimeIntervals(attr, window)
Expande um atributo de entidade em uma única chamada: percorre os grupos e as agendas do atributo, expande cada um e mescla os resultados. A mesclagem importa, porque a remoção de duplicatas e a ordenação só valem dentro de uma única agenda; combinar os grupos manualmente pode gerar horários duplicados ou fora de ordem.
Para qualquer coisa que não seja um atributo timeInterval, retorna um array vazio, então você pode chamá-lo sem verificar type antes.
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)
Expande uma única agenda. Use-o quando você já tem uma, normalmente em formulários, cujas agendas já estão tipadas em 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 é tipado como unknown, porque o seu formato depende de type. Este type guard restringe um atributo a ITimeIntervalAttributeValue, para que você possa acessar as agendas sem conversão de tipo:
import { isTimeIntervalAttribute } from 'oneentry';
const attr = page.attributeValues.interval;
if (isTimeIntervalAttribute(attr)) {
attr.value[0].values[0].dates; // fully typed
}
A janela
const window = { from: '2025-04-01', to: '2025-04-30' };
frometoaceitam umDate, uma string ISO ou milissegundos desde a época Unix.- Os dois limites são inclusivos e comparados pelo dia em UTC; o horário em
from/toé ignorado. - A janela é obrigatória: uma agenda é uma regra de recorrência sem fim definido, e só você sabe até onde expandi-la.
Semântica da recorrência
dates[0]/range[0]é ao mesmo tempo a fase da recorrência e o primeiro dia válido. Nada anterior é retornado, por mais ampla que seja a janela.dates[1]/range[1]encerra a validade. Se não for posterior ao início, a agenda fica ancorada nesse único dia; com um sinalizador de recorrência definido, a recorrência passa a não ter fim e apenas a janela limita o resultado.inEveryWeekrepete a cada 7 dias a partir da data de referência.inEveryMonthrepete no mesmo dia do mês, pulando os meses curtos demais.- Com as duas flags definidas, aplica-se a regra semanal.
- Sem nenhum sinalizador, a agenda é uma faixa de datas simples: todos os dias nela geram horários.
- O resultado é sem duplicatas e ordenado pelo início e depois pelo fim.
- Todos os cálculos são feitos em UTC, então o resultado não depende do fuso horário da máquina.
Migrando do campo timeIntervals
As versões anteriores do SDK adicionavam um array calculado timeIntervals a todos os valores de atributo timeInterval. Esse campo não existe mais. Ele continha um ano inteiro de horários, independentemente do que quem chamava precisava: um único atributo com horários de hora em hora se expandia para cerca de 2.000 linhas de JSON, e períodos de horário menores chegavam a megabytes, o suficiente para ultrapassar os limites de cache de dados dos frameworks. Ele também nunca foi declarado em nenhuma interface ou esquema, então o código TypeScript só conseguia acessá-lo por meio de uma conversão de tipo.
Antes, você lia o campo pré-calculado:
const slots = page.attributeValues.interval.value[0].values[0].timeIntervals;
Agora, expanda a janela que você de fato renderiza:
import { expandAttributeTimeIntervals } from 'oneentry';
const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});
Os dados de origem (dates/range, times/intervals, inEveryWeek, inEveryMonth) não mudaram e continuam presentes em todas as agendas. Nada se perde: os horários são calculados sob demanda em vez de antecipadamente, e o que vai para o cache é a regra compacta.
Os métodos _addTimeIntervalsToSchedules e _addTimeIntervalsToFormSchedules também foram removidos de todos os módulos (apesar do prefixo _, eles podiam ser chamados, por exemplo Pages._addTimeIntervalsToSchedules). Use expandTimeIntervals no lugar deles.
Tipos
Todos eles são exportados da raiz do pacote e de oneentry/types (veja Importação de tipos):
| Tipo | Descreve |
|---|---|
ITimeIntervalAttributeValue | Um IAttributeValue restrito a type: 'timeInterval', cujo value é um array de grupos |
ITimeIntervalGroup | Uma entrada do value do atributo: agendas que compartilham um intervalId |
ITimeIntervalEntitySchedule | Uma agenda de entidade: dates, times, inEveryWeek, inEveryMonth |
ITimeIntervalSchedule | Uma agenda de formulário: range, intervals, inEveryWeek, inEveryMonth |
ITimeIntervalRange | Uma faixa diária com start, end e um period de horário em minutos (null quando não é fatiada) |
ITimeIntervalPoint | Um ponto no dia: { hours, minutes } |
ITimeIntervalWindow | A janela de expansão: { from, to } |
TimeIntervalPair | Um horário resolvido: [start, end], ambos strings ISO 8601 em UTC |
Exemplo: exibindo um mês de horários
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]>>);
Relacionados
- Valores de atributos: o formato normalizado de todo valor de atributo
- Importação de tipos: como importar
ITimeIntervalWindowe tipos relacionados - Módulo Forms: atributos de formulário com
localizeInfos.intervals