performance improvements
This commit is contained in:
@@ -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()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user