import { DateTime } from 'luxon' import { FluidType } from 'enum/fluid.enum' import { ITimePeriod, TimeStep, TimePeriod } from './dataConsumptionContracts' import Config from '../../config.json' import IFluidConfig from './IFluidConfig' export default class ConsumptionPeriodSelector { private readonly _dataDelayOffsetConfig: IFluidConfig[] constructor() { this._dataDelayOffsetConfig = Config.fluidConfig } public getTimePeriods( date: DateTime, fluidTypes: FluidType[], timeStep: TimeStep ): any { const endOfOffsetDate = this.applyOffsetToDate( date, this.calculateFluidTypesOffset(fluidTypes) ).endOf('day') let lastDayOfCompletePeriod if (this.isLastDayOfTimePeriod(endOfOffsetDate, timeStep)) lastDayOfCompletePeriod = endOfOffsetDate else lastDayOfCompletePeriod = this.getLastDayOfCompletePeriod( endOfOffsetDate, timeStep ).endOf('day') const timePeriod: ITimePeriod = this.getLastCompletePeriod( lastDayOfCompletePeriod, timeStep ) const comparisonTimePeriod: ITimePeriod = this.getComparisonTimePeriod( timePeriod, timeStep ) return { timePeriod: timePeriod, comparisonTimePeriod: comparisonTimePeriod, } } public calculateFluidTypesOffset(fluidTypes: FluidType[]): number { const allOffsets: number[] = [] fluidTypes.forEach(fluidType => allOffsets.push(this._dataDelayOffsetConfig[fluidType].dataDelayOffset) ) // eslint-disable-next-line prefer-spread const maxOffset = Math.max.apply(Math, allOffsets) return maxOffset } public applyOffsetToDate(date: DateTime, offset: number): DateTime { return date.minus({ days: offset }) } public isLastDayOfTimePeriod(date: DateTime, timeStep: TimeStep) { const lastDayOfTimePeriod = this.getLastDayOfTimePeriod(date, timeStep) return ( date.year === lastDayOfTimePeriod.year && date.month === lastDayOfTimePeriod.month && date.day === lastDayOfTimePeriod.day ) } public getLastDayOfTimePeriod(date: DateTime, timeStep: TimeStep): DateTime { switch (timeStep) { case TimeStep.HALF_AN_HOUR || TimeStep.HOUR: return DateTime.local(date.year, date.month, date.day) case TimeStep.DAY: return DateTime.local(date.year, date.month, date.day) .setLocale('fr-CA') .endOf('week') case TimeStep.MONTH: return DateTime.local(date.year, date.month, 1) .plus({ months: 1 }) .minus({ days: 1 }) case TimeStep.YEAR: return DateTime.local(date.year, 1, 1) .plus({ years: 1 }) .minus({ days: 1 }) default: return date } } public getLastDayOfCompletePeriod(date: DateTime, timeStep: TimeStep) { switch (timeStep) { case TimeStep.HALF_AN_HOUR || TimeStep.HOUR: return DateTime.local(date.year, date.month, date.day) case TimeStep.DAY: return DateTime.local(date.year, date.month, date.day) .setLocale('fr-CA') .startOf('week') .minus({ days: 1 }) case TimeStep.MONTH: return DateTime.local(date.year, date.month, 1).minus({ days: 1 }) case TimeStep.YEAR: return DateTime.local(date.year, 1, 1).minus({ days: 1 }) default: return date } } public getStartDateFromEndDateByTimeStep( startDate: DateTime, timeStep: TimeStep ) { switch (timeStep) { case TimeStep.HALF_AN_HOUR || TimeStep.HOUR: return DateTime.local(startDate.year, startDate.month, startDate.day) case TimeStep.DAY: return DateTime.local(startDate.year, startDate.month, startDate.day) .setLocale('fr-CA') .startOf('week') case TimeStep.MONTH: return DateTime.local(startDate.year, startDate.month, 1) case TimeStep.YEAR: return DateTime.local(startDate.year, 1, 1) default: return startDate } } public getLastCompletePeriod( lastDay: DateTime, timeStep: TimeStep ): ITimePeriod { // calculate last day of the tobe coimpleted period const lastCompleteTimePeriod = { startDate: this.getStartDateFromEndDateByTimeStep(lastDay, timeStep), endDate: lastDay, } return lastCompleteTimePeriod } public getComparisonTimePeriod( timePeriod: ITimePeriod, timeStep: TimeStep ): ITimePeriod { let comparisonTimePeriodStartDate: DateTime let comparisonTimePeriodEndDate: DateTime switch (timeStep) { case TimeStep.HALF_AN_HOUR || TimeStep.HOUR: comparisonTimePeriodStartDate = timePeriod.startDate.minus({ days: 1 }) comparisonTimePeriodEndDate = timePeriod.endDate.minus({ days: 1 }) break case TimeStep.DAY: comparisonTimePeriodStartDate = timePeriod.startDate .minus({ days: 1 }) .setLocale('fr-CA') .startOf('week') comparisonTimePeriodEndDate = timePeriod.startDate.minus({ days: 1 }) break case TimeStep.MONTH: comparisonTimePeriodStartDate = DateTime.local( timePeriod.startDate.year - 1, timePeriod.startDate.month, timePeriod.startDate.day ) comparisonTimePeriodEndDate = DateTime.local( timePeriod.endDate.year - 1, timePeriod.endDate.month, 1 ).endOf('month') break case TimeStep.YEAR: comparisonTimePeriodStartDate = DateTime.local( timePeriod.startDate.year - 1, timePeriod.startDate.month, timePeriod.startDate.day ) comparisonTimePeriodEndDate = DateTime.local( timePeriod.endDate.year - 1, timePeriod.endDate.month, timePeriod.endDate.day ).endOf('year') break default: comparisonTimePeriodStartDate = timePeriod.startDate comparisonTimePeriodEndDate = timePeriod.endDate } const comparisonTimePeriod: ITimePeriod = { startDate: comparisonTimePeriodStartDate, endDate: comparisonTimePeriodEndDate, } return comparisonTimePeriod } }