@dvsa/appdev-api-common
Version:
Utils library for common API functionality
274 lines (273 loc) • 8.93 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DateTime = void 0;
const dayjs_1 = __importDefault(require("dayjs"));
const customParseFormat_1 = __importDefault(require("dayjs/plugin/customParseFormat"));
const timezone_1 = __importDefault(require("dayjs/plugin/timezone"));
const utc_1 = __importDefault(require("dayjs/plugin/utc"));
/**
* DateTime utility class for handling dates with UK timezone support
*/
class DateTime {
instance;
static UKLocalDateTimeFormat = "DD/MM/YYYY HH:mm:ss";
static UKLocalDateFormat = "DD/MM/YYYY";
static UK_TIMEZONE = "Europe/London";
/**
* Creates a new DateTime instance
* @param sourceDateTime - Initial date/time (string, Date, or another DateTime)
* @param format - Optional format string for parsing string dates
*/
constructor(sourceDateTime, format = undefined) {
// Set up dayjs plugins
dayjs_1.default.extend(customParseFormat_1.default);
dayjs_1.default.extend(timezone_1.default);
dayjs_1.default.extend(utc_1.default);
if (sourceDateTime === undefined || sourceDateTime === null) {
// For current time, directly get the UK time but preserve the timezone
this.instance = (0, dayjs_1.default)().tz(DateTime.UK_TIMEZONE);
}
else if (typeof sourceDateTime === "string" ||
sourceDateTime instanceof Date) {
// For string inputs, PRESERVE THE ORIGINAL TIME without timezone conversion
// This is essential for test consistency
if (format) {
this.instance = (0, dayjs_1.default)(sourceDateTime, format);
}
else {
this.instance = (0, dayjs_1.default)(sourceDateTime);
}
}
else if (sourceDateTime instanceof DateTime) {
// Clone a DateTime instance
this.instance = sourceDateTime.instance.clone();
}
else {
throw new Error("Invalid date input");
}
}
/**
* Converts to a JavaScript Date object
* @returns Date object
*/
toDate() {
return this.instance.toDate();
}
/**
* Creates a new DateTime instance from a date source
* @param sourceDateTime - Source date/time
* @param format - Optional format string for parsing
* @returns New DateTime instance or null if source is null
*/
static at(sourceDateTime, format = undefined) {
if (!sourceDateTime) {
return null;
}
return new DateTime(sourceDateTime, format);
}
/**
* Formats a date in UK local date time format (DD/MM/YYYY HH:mm:ss)
* @param sourceDateTime - Source date/time
* @returns Formatted string or null if source is null
*/
static StandardUkLocalDateTimeAdapter(sourceDateTime) {
return (DateTime.at(sourceDateTime)?.format(DateTime.UKLocalDateTimeFormat) ||
null);
}
/**
* Formats a date in UK local date format (DD/MM/YYYY)
* @param sourceDateTime - Source date/time
* @returns Formatted string or null if source is null
*/
static StandardUkLocalDateAdapter(sourceDateTime) {
return (DateTime.at(sourceDateTime)?.format(DateTime.UKLocalDateFormat) || null);
}
/**
* Adds time to this DateTime instance (mutable operation)
* @param amount - Amount to add
* @param unit - Unit of time (day, month, year, etc.)
* @returns This instance for chaining
*/
add(amount, unit) {
this.instance = this.instance.add(amount, unit);
return this;
}
/**
* Subtracts time from this DateTime instance (mutable operation)
* @param amount - Amount to subtract
* @param unit - Unit of time (day, month, year, etc.)
* @returns This instance for chaining
*/
subtract(amount, unit) {
this.instance = this.instance.subtract(amount, unit);
return this;
}
/**
* Formats the date with a custom format string
* @param formatString - Format pattern
* @returns Formatted date string
*/
format(formatString) {
return this.instance.format(formatString);
}
/**
* Gets the day of week (0-6, Sunday is 0)
* @returns Day of week
*/
day() {
return this.instance.day();
}
/**
* Sets the date to the start of a specified unit (mutable operation)
* @param unit - Unit of time (day, month, year, etc.)
* @returns This instance for chaining
*/
startOf(unit) {
this.instance = this.instance.startOf(unit);
return this;
}
/**
* Converts to string in UK date time format
* @returns Formatted date string
*/
toString() {
return this.format(DateTime.UKLocalDateTimeFormat);
}
/**
* Gets ISO string representation
* @returns ISO format string
*/
toISOString() {
return this.instance.toISOString();
}
/**
* Calculates the difference between dates
* @param targetDate - Target date to compare with
* @param unit - Unit for the difference calculation
* @param precise - Whether to return decimal result
* @returns Difference in specified units
*/
diff(targetDate, unit, precise) {
const date = new DateTime(targetDate);
return this.instance.diff(date.instance, unit, precise);
}
/**
* Calculates the difference in days
* @param targetDate - Target date to compare with
* @returns Difference in days
*/
daysDiff(targetDate) {
const date = new DateTime(targetDate);
return this.instance
.startOf("day")
.diff(date.instance.startOf("day"), "day");
}
/**
* Calculates duration from this date to target
* @param targetDate - Target date
* @param unit - Unit for duration calculation
* @returns Duration in specified units
*/
compareDuration(targetDate, unit) {
const date = new DateTime(targetDate);
return date.instance.diff(this.instance, unit);
}
/**
* Checks if the date is valid
* @returns True if valid date
*/
isValid() {
return this.instance.isValid();
}
/**
* Checks if this date is before the target date
* @param targetDate - Target date to compare with
* @returns True if this date is before target
*/
isBefore(targetDate) {
const date = new DateTime(targetDate);
return this.instance.isBefore(date.instance);
}
/**
* Checks if this date is after the target date
* @param targetDate - Target date to compare with
* @returns True if this date is after target
*/
isAfter(targetDate) {
const date = new DateTime(targetDate);
return this.instance.isAfter(date.instance);
}
/**
* Checks if this date is between start and end dates
* @param startDate - Start date of range
* @param endDate - End date of range
* @returns True if date is between start and end
*/
isBetween(startDate, endDate) {
const start = new DateTime(startDate);
const end = new DateTime(endDate);
return (this.instance.isAfter(start.instance) &&
this.instance.isBefore(end.instance));
}
/**
* Sets the timezone (mutable operation)
* @param tz - Timezone identifier
* @returns This instance for chaining
*/
setTimezone(tz) {
this.instance = this.instance.tz(tz);
return this;
}
/**
* Converts to UK timezone (mutable operation)
* @returns This instance for chaining
*/
toUKTime() {
this.instance = this.instance.tz(DateTime.UK_TIMEZONE);
return this;
}
/**
* Gets the hour component
* @returns Hour (0-23)
*/
getHour() {
return this.instance.hour();
}
/**
* Gets the minute component
* @returns Minute (0-59)
*/
getMinute() {
return this.instance.minute();
}
/**
* Gets the second component
* @returns Second (0-59)
*/
getSecond() {
return this.instance.second();
}
/**
* Creates a clone of this DateTime
* @returns New DateTime instance with the same date/time
*/
clone() {
return new DateTime(this);
}
/**
* Provides debug information about this DateTime
* @returns Object with diagnostic information
*/
debug() {
return {
formatted: this.format("DD/MM/YYYY HH:mm:ss"),
isoString: this.toISOString(),
hour: this.getHour(),
utcOffset: this.instance.utcOffset(),
};
}
}
exports.DateTime = DateTime;