function inferTimeStepFromData(data: readonly { time: Time }[]): TimeStep {
const times = data.reduce<number[]>((acc, item) => {
if (typeof item.time === 'number' && Number.isFinite(item.time)) {
acc.push(Number(item.time));
}
return acc;
}, []);
if (times.length < 2) {
return createTimeStep('minute', 1, 'inferred:minute:1');
}
const uniqueTimes = Array.from(new Set(times)).sort((a, b) => a - b);
const latestTimes = uniqueTimes.slice(-100);
const distances: number[] = [];
for (let index = 1; index < latestTimes.length; index += 1) {
const prevTime = latestTimes[index - 1];
const currentTime = latestTimes[index];
const distance = currentTime - prevTime;
if (distance > 0) {
distances.push(distance);
}
}
if (!distances.length) {
return createTimeStep('minute', 1, 'inferred:minute:1');
}
distances.sort((a, b) => a - b);
const medianDistance = distances[Math.floor(distances.length / 2)];
if (medianDistance < 60) {
const amount = Math.max(1, Math.round(medianDistance));
return createTimeStep('second', amount, `inferred:second:${amount}`);
}
if (medianDistance < 3600) {
const amount = Math.max(1, Math.round(medianDistance / 60));
return createTimeStep('minute', amount, `inferred:minute:${amount}`);
}
if (medianDistance < DAY_SECONDS) {
const amount = Math.max(1, Math.round(medianDistance / 3600));
return createTimeStep('hour', amount, `inferred:hour:${amount}`);
}
if (medianDistance < DAY_SECONDS * 27) {
const amount = Math.max(1, Math.round(medianDistance / DAY_SECONDS));
return createTimeStep('day', amount, `inferred:day:${amount}`);
}
if (medianDistance < DAY_SECONDS * 90) {
const amount = Math.max(1, Math.round(medianDistance / (DAY_SECONDS * 30)));
return createTimeStep('month', amount, `inferred:month:${amount}`);
}
if (medianDistance < DAY_SECONDS * 365) {
const amount = Math.max(1, Math.round(medianDistance / (DAY_SECONDS * 7)));
return createTimeStep('week', amount, `inferred:week:${amount}`);
}
const amount = Math.max(1, Math.round(medianDistance / (DAY_SECONDS * 365)));
return createTimeStep('year', amount, `inferred:year:${amount}`);
}