Skip to content

Commit

Permalink
feat(date-time): Added the static validate method to the `StormDateTi…
Browse files Browse the repository at this point in the history
…me` utility classes
  • Loading branch information
sullivanpj committed Oct 18, 2024
1 parent 6ffdb40 commit 3169747
Show file tree
Hide file tree
Showing 7 changed files with 267 additions and 140 deletions.
12 changes: 10 additions & 2 deletions packages/date-time/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ export type DateTimeErrorCode =
| ErrorCode
| "datetime_create_failure"
| "ms_format"
| "formatting_failure";
| "formatting_failure"
| "invalid_instant"
| "invalid_time"
| "rfc_3339_format"
| "invalid_day_of_month";
export const DateTimeErrorCode = {
...ErrorCode,
datetime_create_failure: "datetime_create_failure" as DateTimeErrorCode,
ms_format: "ms_format" as DateTimeErrorCode,
formatting_failure: "formatting_failure" as DateTimeErrorCode
formatting_failure: "formatting_failure" as DateTimeErrorCode,
invalid_instant: "invalid_instant" as DateTimeErrorCode,
invalid_time: "invalid_time" as DateTimeErrorCode,
rfc_3339_format: "rfc_3339_format" as DateTimeErrorCode,
invalid_day_of_month: "invalid_day_of_month" as DateTimeErrorCode
};
131 changes: 83 additions & 48 deletions packages/date-time/src/storm-date-time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ import {
isNumber,
isObject,
isSet,
isSetString
isSetString,
MessageType,
ValidationDetails
} from "@storm-stack/types";
import { RFC_3339_DATETIME_REGEX } from "./constants";
import { DateTimeErrorCode } from "./errors";
import { isInstant } from "./utilities/is-instant";

/**
Expand Down Expand Up @@ -171,6 +174,76 @@ export class StormDateTime extends Date {
new Intl.DateTimeFormat().resolvedOptions().calendar)
});

/**
* Validate the input date value
*
* @param dateTime - The date value to validate
* @param _options - The options to use
* @returns A boolean representing whether the value is a valid *date-time*
*/
public static validate(
value?: DateTimeInput,
_options?: DateTimeOptions
): ValidationDetails | null {
if (StormDateTime.isDateTime(value)) {
return value.validate();
}
if (isInstant(value)) {
if (value.epochMilliseconds) {
return null;
}

return {
code: DateTimeErrorCode.invalid_instant,
type: MessageType.ERROR
};
}

let datetime: string | undefined;
if (isDate(value) || isNumber(value) || isBigInt(value)) {
const date =
isNumber(value) || isBigInt(value) ? new Date(Number(value)) : value;

if (Number.isNaN(date.getTime())) {
return {
code: DateTimeErrorCode.invalid_time,
type: MessageType.ERROR
};
}

datetime = date.toISOString();
} else {
datetime =
value === null || value === void 0 ? void 0 : value.toUpperCase();
}

if (!datetime) {
return {
code: DateTimeErrorCode.invalid_value,
type: MessageType.ERROR
};
}

// Validate the structure of the date-string
if (!RFC_3339_DATETIME_REGEX.test(datetime)) {
return {
code: DateTimeErrorCode.rfc_3339_format,
type: MessageType.ERROR
};
}

// Check if it is a correct date using the javascript Date parse() method.
if (!Date.parse(datetime)) {
return {
code: DateTimeErrorCode.rfc_3339_format,
type: MessageType.ERROR
};
}

// Success - Valid
return null;
}

/**
* A private accessor that stores the `Temporal.Instant` object of the DateTime object
*/
Expand Down Expand Up @@ -217,7 +290,7 @@ export class StormDateTime extends Date {
: undefined;

super(instant ? Number(instant.epochMilliseconds) : "MISSING_DATE");
if (instant && this.validate(_dateTime, options)) {
if (instant && StormDateTime.validate(_dateTime, options) === null) {
this.#instant = instant;

const timeZone =
Expand Down Expand Up @@ -290,7 +363,7 @@ export class StormDateTime extends Date {
* An accessor that returns the `isValid` boolean of the DateTime object
*/
public get isValid(): boolean {
return this.validate(this.#zonedDateTime.epochMilliseconds, this.#options);
return this.validate() === null;
}

/**
Expand All @@ -308,53 +381,15 @@ export class StormDateTime extends Date {
}

/**
* Validate the input date value
* A function that validates the current DateTime object
*
* @param dateTime - The date value to validate
* @param _options - The options to use
* @returns A boolean representing whether the value is a valid *date-time*
* @returns A StormError object if the DateTime object is invalid, otherwise null
*/
protected validate(
value?: DateTimeInput,
_options?: DateTimeOptions
): boolean {
if (StormDateTime.isDateTime(value)) {
return value.isValid;
}
if (isInstant(value)) {
return Boolean(value.epochMilliseconds);
}

let datetime: string | undefined;
if (isDate(value) || isNumber(value) || isBigInt(value)) {
const date =
isNumber(value) || isBigInt(value) ? new Date(Number(value)) : value;

if (Number.isNaN(date.getTime())) {
return false;
}

datetime = date.toUTCString();
} else {
datetime =
value === null || value === void 0 ? void 0 : value.toUpperCase();
}

if (!datetime) {
return false;
}

// Validate the structure of the date-string
if (!RFC_3339_DATETIME_REGEX.test(datetime)) {
return false;
}

// Check if it is a correct date using the javascript Date parse() method.
if (!Date.parse(datetime)) {
return false;
}

return true;
public validate(): ValidationDetails | null {
return StormDateTime.validate(
this.#zonedDateTime.epochMilliseconds,
this.#options
);
}

/**
Expand Down
Loading

0 comments on commit 3169747

Please sign in to comment.