diff options
Diffstat (limited to 'comm/third_party/asn1js/src/GeneralizedTime.ts')
-rw-r--r-- | comm/third_party/asn1js/src/GeneralizedTime.ts | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/comm/third_party/asn1js/src/GeneralizedTime.ts b/comm/third_party/asn1js/src/GeneralizedTime.ts new file mode 100644 index 0000000000..7743ae1436 --- /dev/null +++ b/comm/third_party/asn1js/src/GeneralizedTime.ts @@ -0,0 +1,262 @@ +import * as pvutils from "pvutils"; +import { typeStore } from "./TypeStore"; +import { IUTCTime, UTCTimeParams, UTCTimeJson, UTCTime, DateStringEncoding } from "./UTCTime"; + +export interface IGeneralizedTime extends IUTCTime { + millisecond: number; +} + +export type GeneralizedTimeParams = UTCTimeParams; + +export interface GeneralizedTimeJson extends UTCTimeJson { + millisecond: number; +} + +export class GeneralizedTime extends UTCTime { + + static { + typeStore.GeneralizedTime = this; + } + + public static override NAME = "GeneralizedTime"; + + public millisecond: number; + + constructor(parameters: GeneralizedTimeParams = {}) { + super(parameters); + + this.millisecond ??= 0; + + this.idBlock.tagClass = 1; // UNIVERSAL + this.idBlock.tagNumber = 24; // GeneralizedTime + } + + public override fromDate(inputDate: Date): void { + super.fromDate(inputDate); + this.millisecond = inputDate.getUTCMilliseconds(); + } + + public override toDate(): Date { + return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond))); + } + + public override fromString(inputString: string): void { + //#region Initial variables + let isUTC = false; + + let timeString = ""; + let dateTimeString = ""; + let fractionPart = 0; + + let parser; + + let hourDifference = 0; + let minuteDifference = 0; + //#endregion + + //#region Convert as UTC time + if (inputString[inputString.length - 1] === "Z") { + timeString = inputString.substring(0, inputString.length - 1); + + isUTC = true; + } + //#endregion + //#region Convert as local time + else { + const number = new Number(inputString[inputString.length - 1]); + + if (isNaN(number.valueOf())) + throw new Error("Wrong input string for conversion"); + + timeString = inputString; + } + //#endregion + + //#region Check that we do not have a "+" and "-" symbols inside UTC time + if (isUTC) { + if (timeString.indexOf("+") !== -1) + throw new Error("Wrong input string for conversion"); + + if (timeString.indexOf("-") !== -1) + throw new Error("Wrong input string for conversion"); + } + //#endregion + //#region Get "UTC time difference" in case of local time + else { + let multiplier = 1; + let differencePosition = timeString.indexOf("+"); + let differenceString = ""; + + if (differencePosition === -1) { + differencePosition = timeString.indexOf("-"); + multiplier = -1; + } + + if (differencePosition !== -1) { + differenceString = timeString.substring(differencePosition + 1); + timeString = timeString.substring(0, differencePosition); + + if ((differenceString.length !== 2) && (differenceString.length !== 4)) + throw new Error("Wrong input string for conversion"); + + let number = parseInt(differenceString.substring(0, 2), 10); + + if (isNaN(number.valueOf())) + throw new Error("Wrong input string for conversion"); + + hourDifference = multiplier * number; + + if (differenceString.length === 4) { + number = parseInt(differenceString.substring(2, 4), 10); + + if (isNaN(number.valueOf())) + throw new Error("Wrong input string for conversion"); + + minuteDifference = multiplier * number; + } + } + } + //#endregion + + //#region Get position of fraction point + let fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol + if (fractionPointPosition === -1) + fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol + //#endregion + + //#region Get fraction part + if (fractionPointPosition !== -1) { + const fractionPartCheck = new Number(`0${timeString.substring(fractionPointPosition)}`); + + if (isNaN(fractionPartCheck.valueOf())) + throw new Error("Wrong input string for conversion"); + + fractionPart = fractionPartCheck.valueOf(); + + dateTimeString = timeString.substring(0, fractionPointPosition); + } + else + dateTimeString = timeString; + //#endregion + + //#region Parse internal date + switch (true) { + case (dateTimeString.length === 8): // "YYYYMMDD" + parser = /(\d{4})(\d{2})(\d{2})/ig; + if (fractionPointPosition !== -1) + throw new Error("Wrong input string for conversion"); // Here we should not have a "fraction point" + break; + case (dateTimeString.length === 10): // "YYYYMMDDHH" + parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig; + + if (fractionPointPosition !== -1) { + let fractionResult = 60 * fractionPart; + this.minute = Math.floor(fractionResult); + + fractionResult = 60 * (fractionResult - this.minute); + this.second = Math.floor(fractionResult); + + fractionResult = 1000 * (fractionResult - this.second); + this.millisecond = Math.floor(fractionResult); + } + break; + case (dateTimeString.length === 12): // "YYYYMMDDHHMM" + parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig; + + if (fractionPointPosition !== -1) { + let fractionResult = 60 * fractionPart; + this.second = Math.floor(fractionResult); + + fractionResult = 1000 * (fractionResult - this.second); + this.millisecond = Math.floor(fractionResult); + } + break; + case (dateTimeString.length === 14): // "YYYYMMDDHHMMSS" + parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig; + + if (fractionPointPosition !== -1) { + const fractionResult = 1000 * fractionPart; + this.millisecond = Math.floor(fractionResult); + } + break; + default: + throw new Error("Wrong input string for conversion"); + } + //#endregion + + //#region Put parsed values at right places + const parserArray = parser.exec(dateTimeString); + if (parserArray === null) + throw new Error("Wrong input string for conversion"); + + for (let j = 1; j < parserArray.length; j++) { + switch (j) { + case 1: + this.year = parseInt(parserArray[j], 10); + break; + case 2: + this.month = parseInt(parserArray[j], 10); + break; + case 3: + this.day = parseInt(parserArray[j], 10); + break; + case 4: + this.hour = parseInt(parserArray[j], 10) + hourDifference; + break; + case 5: + this.minute = parseInt(parserArray[j], 10) + minuteDifference; + break; + case 6: + this.second = parseInt(parserArray[j], 10); + break; + default: + throw new Error("Wrong input string for conversion"); + } + } + //#endregion + + //#region Get final date + if (isUTC === false) { + const tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond); + + this.year = tempDate.getUTCFullYear(); + this.month = tempDate.getUTCMonth(); + this.day = tempDate.getUTCDay(); + this.hour = tempDate.getUTCHours(); + this.minute = tempDate.getUTCMinutes(); + this.second = tempDate.getUTCSeconds(); + this.millisecond = tempDate.getUTCMilliseconds(); + } + //#endregion + } + + public override toString(encoding: DateStringEncoding = "iso"): string { + if (encoding === "iso") { + const outputArray = []; + + outputArray.push(pvutils.padNumber(this.year, 4)); + outputArray.push(pvutils.padNumber(this.month, 2)); + outputArray.push(pvutils.padNumber(this.day, 2)); + outputArray.push(pvutils.padNumber(this.hour, 2)); + outputArray.push(pvutils.padNumber(this.minute, 2)); + outputArray.push(pvutils.padNumber(this.second, 2)); + if (this.millisecond !== 0) { + outputArray.push("."); + outputArray.push(pvutils.padNumber(this.millisecond, 3)); + } + outputArray.push("Z"); + + return outputArray.join(""); + } + + return super.toString(encoding); + } + + public override toJSON(): GeneralizedTimeJson { + return { + ...super.toJSON(), + millisecond: this.millisecond, + }; + } + +} |