performance improvements

This commit is contained in:
2023-04-27 14:05:34 +10:00
parent 0a956e1fc5
commit c6e1b0248d
2 changed files with 142 additions and 183 deletions

View File

@@ -71,199 +71,166 @@ export class SMDate {
*/ */
public parse( public parse(
dateString: string, dateString: string,
options: { format?: string; utc?: boolean } = {} { format = "dmy", utc = false } = {}
): SMDate { ): SMDate {
const now = new Date(); const now = new Date();
if (dateString.toLowerCase() == "now") { if (dateString.toLowerCase() === "now") {
this.date = now; this.date = now;
return this; return this;
} }
// Parse the date format to determine the order of the date components // Cache regular expressions
const order = (options.format || "dmy").toLowerCase().split(""); const isoDateRegex =
options.utc = options.utc || false; /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,10})?Z$/i;
const timeRegex =
let components = []; /^(\d+)(?::(\d+))?(?::(\d+))? ?(am?|a\.m\.|pm?|p\.m\.)?$/i;
let time = "";
// Test if the dateString is in ISO 8601 // Test if the dateString is in ISO 8601
if ( if (isoDateRegex.test(dateString)) {
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,10})?Z$/i.test( format = "YMd";
dateString
)
) {
options.format = "YMd";
[dateString, time] = dateString.split("T"); [dateString, time] = dateString.split("T");
time = time.slice(0, -8); time = time.slice(0, -8);
} }
// Split the date string into an array of components based on the length of each date component // Split the date string into an array of components based on the length of each date component
components = dateString.split(/[ /-]/); const components = dateString.split(/[ /-]/);
for (let i = 0; i < components.length; i++) { let time = "";
if (components[i].includes(":")) { for (const component of components) {
time = components[i]; if (isNaN(parseInt(component))) {
components.splice(i, 1); return this;
}
if (component.includes(":")) {
time = component;
const index = components.indexOf(component);
if ( if (
i < components.length && index < components.length - 1 &&
/^(am?|a\.m\.|pm?|p\.m\.)$/i.test(components[i]) /^(am?|a\.m\.|pm?|p\.m\.)$/i.test(components[index + 1])
) { ) {
time += " " + components[i].toUpperCase(); time += " " + components[index + 1].toUpperCase();
components.splice(i, 1); components.splice(index + 1, 1);
} }
components.splice(index, 1);
break; break;
} }
} }
if (components.every((v) => !isNaN(parseInt(v))) == false) {
return this;
}
if (components.length > 3) {
return this;
}
// Map the date components to the expected order based on the format
const [day, month, year] = const [day, month, year] =
order[0] === "d" format === "dmy"
? [components[0], components[1], components[2]] ? components
: order[0] === "m" : format === "mdy"
? [components[1], components[0], components[2]] ? [components[1], components[0], components[2]]
: [components[2], components[1], components[0]]; : [components[2], components[1], components[0]];
let parsedDay: number = 0, if (year === undefined || year.length === 3 || year.length >= 5) {
parsedMonth: number = 0,
parsedYear: number = 0;
if (year == undefined || year.length == 3 || year.length >= 5) {
return this; return this;
} }
if (day && day.length != 0 && month && month.length != 0) { // numeric
// Parse the day, month, and year components for (const component of [day, month, year]) {
parsedDay = parseInt(day.padStart(2, "0"), 10); if (isNaN(parseInt(component))) {
parsedMonth = this.getMonthAsNumber(month);
parsedYear = year
? parseInt(year.padStart(4, "20"), 10)
: now.getFullYear();
} else {
parsedDay = now.getDate();
parsedMonth = now.getMonth() + 1;
parsedYear = now.getFullYear();
}
let parsedHours: number = 0,
parsedMinutes: number = 0,
parsedSeconds: number = 0;
if (time) {
const regEx = new RegExp(
/^(\d+)(?::(\d+))?(?::(\d+))? ?(am?|a\.m\.|pm?|p\.m\.)?$/,
"i"
);
if (regEx.test(time)) {
const match = time.match(regEx);
if (match) {
parsedHours = parseInt(match[1]);
parsedMinutes = match[2] ? parseInt(match[2]) : 0;
parsedSeconds = match[3] ? parseInt(match[3]) : 0;
if (
parsedHours < 0 ||
parsedHours > 23 ||
(match[4] &&
(/(am|pm)/i.test(match[4]) == false ||
parsedHours > 12)) ||
parsedMinutes < 0 ||
parsedMinutes > 59 ||
parsedSeconds < 0 ||
parsedSeconds > 59
) {
// not valid
this.date = null;
return this;
}
if (match[4] && /pm/i.test(match[4]) && parsedHours < 12) {
parsedHours += 12;
}
if (
match[4] &&
/am/i.test(match[4]) &&
parsedHours === 12
) {
parsedHours = 0;
}
} else {
return this;
}
} else {
return this; return this;
} }
} }
// Create a date object with the parsed components const parsedDay = parseInt(day.padStart(2, "0"), 10);
let date: Date | null = null; const parsedMonth = this.getMonthAsNumber(month);
if (options.utc) { const parsedYear = parseInt(year.padStart(4, "20"), 10);
date = new Date(
Date.UTC( const parsedTime = timeRegex.exec(time);
parsedYear, if (time && parsedTime) {
parsedMonth - 1, const [_, hourStr, minuteStr, secondStr, ampm] = parsedTime;
parsedDay, let parsedHours = parseInt(hourStr);
parsedHours, const parsedMinutes = parseInt(minuteStr || "0");
parsedMinutes, const parsedSeconds = parseInt(secondStr || "0");
parsedSeconds
) if (parsedHours < 0 || parsedHours > 23) {
); return this;
}
if (ampm) {
if (/pm/i.test(ampm) && parsedHours < 12) {
parsedHours += 12;
} else if (/am/i.test(ampm) && parsedHours === 12) {
parsedHours = 0;
}
}
if (
parsedMinutes < 0 ||
parsedMinutes > 59 ||
parsedSeconds < 0 ||
parsedSeconds > 59
) {
return this;
}
time = `${parsedHours.toString().padStart(2, "0")}:${parsedMinutes
.toString()
.padStart(2, "0")}:${parsedSeconds
.toString()
.padStart(2, "0")}`;
} else { } else {
date = new Date( time = "00:00:00";
parsedYear,
parsedMonth - 1,
parsedDay,
parsedHours,
parsedMinutes,
parsedSeconds
);
} }
// Test created date object const date = utc
let checkYear: number, ? new Date(
checkMonth: number, Date.UTC(
checkDay: number, parsedYear,
checkHours: number, parsedMonth - 1,
checkMinutes: number, parsedDay,
checkSeconds: number; parsedHours,
if (options.utc) { parsedMinutes,
parsedSeconds
)
)
: new Date(
parsedYear,
parsedMonth - 1,
parsedDay,
parsedHours,
parsedMinutes,
parsedSeconds
);
if (isNaN(date.getTime())) {
return this;
}
if (utc) {
const isoDate = date.toISOString(); const isoDate = date.toISOString();
checkYear = parseInt(isoDate.substring(0, 4), 10); const checkYear = parseInt(isoDate.substring(0, 4), 10);
checkMonth = parseInt(isoDate.substring(5, 7), 10); const checkMonth = parseInt(isoDate.substring(5, 7), 10);
checkDay = new Date(isoDate).getUTCDate(); const checkDay = new Date(isoDate).getUTCDate();
checkHours = parseInt(isoDate.substring(11, 13), 10); const checkHours = parseInt(isoDate.substring(11, 13), 10);
checkMinutes = parseInt(isoDate.substring(14, 16), 10); const checkMinutes = parseInt(isoDate.substring(14, 16), 10);
checkSeconds = parseInt(isoDate.substring(17, 19), 10); const checkSeconds = parseInt(isoDate.substring(17, 19), 10);
if (
checkYear !== parsedYear ||
checkMonth !== parsedMonth ||
checkDay !== parsedDay ||
checkHours !== parsedHours ||
checkMinutes !== parsedMinutes ||
checkSeconds !== parsedSeconds
) {
return this;
}
} else { } else {
checkYear = date.getFullYear(); if (
checkMonth = date.getMonth() + 1; date.getFullYear() !== parsedYear ||
checkDay = date.getDate(); date.getMonth() + 1 !== parsedMonth ||
checkHours = date.getHours(); date.getDate() !== parsedDay ||
checkMinutes = date.getMinutes(); date.getHours() !== parsedHours ||
checkSeconds = date.getSeconds(); date.getMinutes() !== parsedMinutes ||
} date.getSeconds() !== parsedSeconds
) {
if ( return this;
Number.isNaN(date.getTime()) == false && }
checkYear == parsedYear &&
checkMonth == parsedMonth &&
checkDay == parsedDay &&
checkHours == parsedHours &&
checkMinutes == parsedMinutes &&
checkSeconds == parsedSeconds
) {
this.date = date;
} else {
this.date = null;
} }
this.date = date;
return this; return this;
} }
@@ -297,7 +264,7 @@ export class SMDate {
day = new Date(isoDate).getUTCDay(); day = new Date(isoDate).getUTCDay();
hour = isoDate.substring(11, 13); hour = isoDate.substring(11, 13);
min = isoDate.substring(14, 16); min = isoDate.substring(14, 16);
sec = isoDate.substring(17, 18); sec = isoDate.substring(17, 19);
} else { } else {
year = this.date.getFullYear().toString(); year = this.date.getFullYear().toString();
month = (this.date.getMonth() + 1).toString(); month = (this.date.getMonth() + 1).toString();
@@ -367,45 +334,36 @@ export class SMDate {
* @returns {string} A relative date string. * @returns {string} A relative date string.
*/ */
public relative(): string { public relative(): string {
let prefix = "";
let postfix = " ago";
if (this.date === null) { if (this.date === null) {
return ""; return "";
} }
const now = new Date(); const now = new Date();
let dif = Math.round((now.getTime() - this.date.getTime()) / 1000); const dif = Math.round((now.getTime() - this.date.getTime()) / 1000);
if (dif < 0) {
dif = Math.abs(dif);
prefix = "In ";
postfix = "";
}
if (dif < 60) { if (dif < 60) {
return "Just now"; return "Just now";
} else if (dif < 3600) { } else if (dif < 3600) {
const v = Math.round(dif / 60); const v = Math.round(dif / 60);
return prefix + v + " min" + (v != 1 ? "s" : "") + postfix; return `${v} min${v != 1 ? "s" : ""} ago`;
} else if (dif < 86400) { } else if (dif < 86400) {
const v = Math.round(dif / 3600); const v = Math.round(dif / 3600);
return prefix + v + " hour" + (v != 1 ? "s" : "") + postfix; return `${v} hour${v != 1 ? "s" : ""} ago`;
} else if (dif < 604800) { } else if (dif < 604800) {
const v = Math.round(dif / 86400); const v = Math.round(dif / 86400);
return prefix + v + " day" + (v != 1 ? "s" : "") + postfix; return `${v} day${v != 1 ? "s" : ""} ago`;
} else if (dif < 2419200) { } else if (dif < 2419200) {
const v = Math.round(dif / 604800); const v = Math.round(dif / 604800);
return prefix + v + " week" + (v != 1 ? "s" : "") + postfix; return `${v} week${v != 1 ? "s" : ""} ago`;
} else {
return (
this.monthString[this.date.getMonth()] +
" " +
this.date.getDate() +
", " +
this.date.getFullYear()
);
} }
return (
this.monthString[this.date.getMonth()] +
" " +
this.date.getDate() +
", " +
this.date.getFullYear()
);
} }
/** /**

View File

@@ -56,14 +56,15 @@ export const bytesReadable = (bytes: number): string => {
const units = ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; const units = ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
let u = -1; let u = -1;
const r = 10 ** 1; const r = 10 ** 1;
let tempBytes = bytes;
do { while (
bytes /= 1000; Math.round(Math.abs(tempBytes) * r) / r >= 1000 &&
++u;
} while (
Math.round(Math.abs(bytes) * r) / r >= 1000 &&
u < units.length - 1 u < units.length - 1
); ) {
tempBytes /= 1000;
++u;
}
return bytes.toFixed(1) + " " + units[u]; return tempBytes.toFixed(1) + " " + units[u];
}; };