All files / date-range-filter si-date-range-calculation.service.ts

100% Statements 22/22
100% Branches 18/18
100% Functions 4/4
100% Lines 21/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89                                                1x                     65x 65x   65x 57x     65x 30x 30x     35x   35x     28x   5x   2x                 37x       65x 65x                     149x 149x 149x 149x 149x      
/**
 * Copyright (c) Siemens 2016 - 2025
 * SPDX-License-Identifier: MIT
 */
import { Injectable } from '@angular/core';
 
import { DateRangeFilter, ResolvedDateRange } from './si-date-range-filter.types';
 
export interface ResolveDateRangeOptions {
  /**
   * Resolve time? When set to false, hours/minutes/seconds/ms are set to zero
   * @defaultValue true
   **/
  withTime?: boolean;
  /**
   * Skip normalization? When skipped, `point1` will always be `start`, `point2` will be `end`
   */
  skipNormalization?: boolean;
}
 
/**
 * Service to transform and calculate with DateRangeFilter objects.
 */
@Injectable({ providedIn: 'root' })
export class SiDateRangeCalculationService {
  /**
   * Calculates the start and end dates of a DateRangeFilter.
   * @param filter - The date range filter object to be resolved.
   * @param options - Options for time handling
   * @returns The resolved result in form of a ResolvedDateRange object.
   */
  resolveDateRangeFilter(
    filter: DateRangeFilter,
    options?: ResolveDateRangeOptions
  ): ResolvedDateRange {
    const ref = filter.point1 === 'now' ? new Date() : new Date(filter.point1);
    const withTime = options?.withTime ?? true;
 
    if (!withTime) {
      this.removeTime(ref);
    }
 
    if (filter.point2 instanceof Date) {
      const point2 = withTime ? filter.point2 : this.removeTime(new Date(filter.point2));
      return this.normalize(ref, point2, options?.skipNormalization);
    }
 
    const offset = filter.point2;
 
    switch (filter.range) {
      case undefined:
      case 'before':
        return this.normalize(ref, this.datePlusOffset(ref, -offset), options?.skipNormalization);
      case 'after':
        return this.normalize(ref, this.datePlusOffset(ref, offset), options?.skipNormalization);
      case 'within':
        return this.normalize(
          this.datePlusOffset(ref, -offset),
          this.datePlusOffset(ref, offset),
          options?.skipNormalization
        );
    }
  }
 
  private datePlusOffset(date: Date, offset: number): Date {
    return new Date(date.getTime() + offset);
  }
 
  private normalize(date1: Date, date2: Date, skip?: boolean): ResolvedDateRange {
    const valid = !isNaN(date1.getTime()) && !isNaN(date2.getTime());
    return skip
      ? { start: date1, end: date2, valid }
      : date1 < date2
        ? { start: date1, end: date2, valid }
        : { start: date2, end: date1, valid };
  }
 
  /**
   * Utility to reset the time attributes to 0 (hours/minutes/seconds/milliseconds).
   */
  removeTime(date: Date): Date {
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);
    return date;
  }
}