UNPKG

@ts4ocds/core

Version:

TS4OCDS is a library of TypeScript entities that takes an approach to befriend large OCDS JSONs with your per-project routine of writing whole lotta interfaces for them.

109 lines (93 loc) 3.98 kB
/** * @packageDocumentation * @module Standard.Period */ import { Initializable } from '@ts4ocds/utils'; import type { RangedPeriod } from './ranged-period'; import type { ExtendedPeriod } from './extended-period'; /** * Key events during a contracting process may have a known {@link Period.startDate | start date}, {@link Period.endDate | end date}, {@link Period.durationInDays | duration}, * or {@link Period.maxExtentDate | maximum extent} (the latest date the period can extend to). * In some cases, not all of these fields will have known or relevant values. */ export class Period extends Initializable<Period> { /** * The start date for the period. * When known, a precise start date must be provided. */ public startDate?: Date | string; /** * The end date for the period. * When known, a precise end date must be provided. */ public endDate?: Date | string; /** * The period cannot be extended beyond this date. * This field can be used to express the maximum available date for extension or renewal of this period. */ public maxExtentDate?: Date | string; /** * The maximum duration of this period in days. * A user interface can collect or display this data in months or years as appropriate, * and then convert it into days when storing this field. * This field can be used when exact dates are not known. * If a {@link Period.startDate | `startDate`} and {@link Period.endDate | `endDate`} are set, this field, if used, * should be equal to the difference between {@link Period.startDate | `startDate`} and {@link Period.endDate | `endDate`}. * Otherwise, if a {@link Period.startDate | `startDate`} and {@link Period.maxExtentDate | `maxExtentDate`} are set, this field, if used, * should be equal to the difference between {@link Period.startDate | `startDate`} and {@link Period.maxExtentDate | `maxExtentDate`}. */ public durationInDays?: number; /** * Used to check if this period is defined through the use of {@link Period.startDate | `startDate`} and {@link Period.maxExtentDate | `maxExtentDate`} fields. */ public isExtended(): this is ExtendedPeriod { return this.startDate !== undefined && this.maxExtentDate !== undefined; } /** * Used to check if this period is defined through the use of {@link Period.startDate | `startDate`} and {@link Period.endDate | `endDate`} fields. */ public isRanged(): this is RangedPeriod { return this.startDate !== undefined && this.endDate !== undefined; } /** * Returns the number of days this period is being valid for. */ public getRange(maxDate: Date | string): number { return (new Date(maxDate).getTime() - new Date(this.startDate || '').getTime()) / (1000 * 60 * 60 * 24) ?? -1; } /** * Sets the range for this period. */ public setRange(startDate: NonNullable<Period['startDate']>, endDate: NonNullable<Period['endDate']>): void { this.startDate = startDate; this.endDate = endDate; this.durationInDays = this.getRange(this.endDate); } /** * Sets the extent for this period. */ public setExtent( startDate: NonNullable<Period['startDate']>, maxExtentDate: NonNullable<Period['maxExtentDate']> ): void { this.startDate = startDate; this.maxExtentDate = maxExtentDate; this.durationInDays = this.getRange(this.maxExtentDate); } /** * Checks if this period's range is valid according to the {@link Period.durationInDays | `durationInDays` field} description. */ public isRangeValid(): boolean { return Boolean(this.getRange(this.endDate as Date) >= 0); } /** * * Checks if this period's duration is valid according to the {@link Period.durationInDays | `durationInDays` field} description. */ public isDurationValid( maxDate: Date | string, durationInDays: Period['durationInDays'] = this.durationInDays ): boolean { return durationInDays === this.getRange(maxDate); } }