import moment from 'moment'; import {Series, SeriesDataUnit} from 'sentry/types/echarts'; export function zeroFillSeries( series: Series, interval: moment.Duration, startTime?: moment.Moment, endTime?: moment.Moment, zerofillValue?: any ): Series { if (!series?.data?.length) { return series; } if (!zerofillValue) { zerofillValue = 0; } const firstDatum = series.data[0]; const lastDatum = series.data[series.data.length - 1]; const dateFormat = moment(firstDatum.name).creationData().format?.toString(); if (!dateFormat) { return series; } const newData: SeriesDataUnit[] = []; const startTimeNearestInterval = startTime && roundDownToNearest12HourInterval(startTime); const endTimeNearestInterval = endTime && roundDownToNearest12HourInterval(endTime); const seriesData = [ ...(startTimeNearestInterval && startTimeNearestInterval.diff(moment(firstDatum.name)) < 0 ? [{value: zerofillValue, name: startTimeNearestInterval.format(dateFormat)}] : []), ...series.data, ...(endTimeNearestInterval && endTimeNearestInterval.diff(moment(lastDatum.name)) > 0 ? [{value: zerofillValue, name: endTimeNearestInterval.format(dateFormat)}] : []), ]; let currentDatum, nextDatum, lastSeenDate, nextDate, diff; for (let index = 0; index < seriesData.length - 1; index++) { // Push the first datapoint if (index === 0) { newData.push({ ...seriesData[index], name: moment(seriesData[index].name).format(dateFormat), }); } currentDatum = seriesData[index]; nextDatum = seriesData[index + 1]; lastSeenDate = moment(currentDatum.name); nextDate = moment(nextDatum.name); diff = moment.duration(nextDate.diff(lastSeenDate)); while (diff.asMilliseconds() > interval.asMilliseconds()) { // The gap between the two datapoints is more than the intended interval! // We need to fill 0s lastSeenDate.add(interval); newData.push({ value: zerofillValue, name: moment(lastSeenDate).format(dateFormat), }); diff = moment.duration(moment(nextDatum.name).diff(lastSeenDate)); } // Push the next datapoint newData.push({ ...nextDatum, name: moment(nextDatum.name).format(dateFormat), }); } return { ...series, data: newData, }; } function roundDownToNearest12HourInterval(time: moment.Moment) { const hour = time.hour(); const nearestDay = time.clone().startOf('day'); if (hour < 12) { return nearestDay; } return nearestDay.add(12, 'hour'); }