ElectronicBabylonianLiterature/ebl-frontend

View on GitHub
src/chronology/domain/DateConverterChecks.ts

Summary

Maintainability
A
0 mins
Test Coverage
B
85%
import {
  CalendarProps,
  GregorianProps,
  JulianProps,
  SeBabylonianProps,
} from 'chronology/domain/DateConverterBase'
import DateConverter from './DateConverter'

interface RangeParams {
  year: number
  month: number
  day: number
  yearLimit: number
  monthLimit: number
  dayLimit: number
}

export default class DateConverterChecks {
  isDateWithinValidRange(
    params: GregorianProps | JulianProps | SeBabylonianProps,
    earliestDate: CalendarProps,
    latestDate: CalendarProps
  ): [boolean, boolean] {
    const [leftLimits, rightLimits] = [
      earliestDate,
      latestDate,
    ].map((limitDate) => this.paramsToLimits(params, limitDate))
    return [
      !this.isDateBeforeValidRange({
        ...this.paramsToYearMonthDay(params),
        ...leftLimits,
      }),
      !this.isDateAfterValidRange({
        ...this.paramsToYearMonthDay(params),
        ...rightLimits,
      }),
    ]
  }

  isIncomingDateHasCorrespondingIntercalary(
    mesopotamianMonth: number,
    dateConverter: DateConverter
  ): boolean {
    const mesopotamianMonthsInYear = dateConverter.getMesopotamianMonthsOfSeYear(
      dateConverter.calendar.seBabylonianYear
    )
    return !!mesopotamianMonthsInYear.find(
      (month) => month.value === mesopotamianMonth
    )
  }

  private paramsToYearMonthDay(
    params:
      | GregorianProps
      | JulianProps
      | SeBabylonianProps
      | { [k: string]: number }
  ): { year: number; month: number; day: number } {
    const result = { year: 0, month: 0, day: 0 }
    Object.keys(params).forEach((fieldName: string) => {
      if (fieldName.includes('Year')) {
        result.year = params[fieldName]
      } else if (fieldName.includes('Month')) {
        result.month = params[fieldName]
      } else if (fieldName.includes('Day')) {
        result.day = params[fieldName]
      }
    })
    return result
  }

  private paramsToLimits(
    params: GregorianProps | JulianProps | SeBabylonianProps,
    limitDate: CalendarProps
  ): {
    yearLimit: number
    monthLimit: number
    dayLimit: number
  } {
    const filteredLimitDate = Object.fromEntries(
      Object.entries(limitDate).filter(([key]) =>
        Object.keys(params).includes(key)
      )
    )
    const limitsYMD = this.paramsToYearMonthDay(filteredLimitDate)
    return {
      yearLimit: limitsYMD.year,
      monthLimit: limitsYMD.month,
      dayLimit: limitsYMD.day,
    }
  }

  private isDateBeforeValidRange({
    year,
    month,
    day,
    yearLimit,
    monthLimit,
    dayLimit,
  }: RangeParams): boolean {
    return (
      year < yearLimit ||
      (year === yearLimit &&
        (month < monthLimit || (month === monthLimit && day < dayLimit)))
    )
  }

  private isDateAfterValidRange({
    year,
    month,
    day,
    yearLimit,
    monthLimit,
    dayLimit,
  }: RangeParams): boolean {
    return (
      year > yearLimit ||
      (year === yearLimit &&
        (month > monthLimit || (month === monthLimit && day > dayLimit)))
    )
  }
}