Skip to content
Snippets Groups Projects
consumptionPeriodSelectorService.ts 6.04 KiB
Newer Older
  • Learn to ignore specific revisions
  • Hugo NOUTS's avatar
    Hugo NOUTS committed
    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
      }
    }