From 620104e1bf0237340e11fecc843472473edae5e4 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Fri, 1 Dec 2023 13:44:52 +0000 Subject: [PATCH] Refactor timeSince formatting + usage --- src/util/check.ts | 0 src/util/format.ts | 76 ++++++++++++++++++++++++++++---------------- src/util/messages.ts | 26 ++++++++------- 3 files changed, 63 insertions(+), 39 deletions(-) delete mode 100644 src/util/check.ts diff --git a/src/util/check.ts b/src/util/check.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/util/format.ts b/src/util/format.ts index fe6971a..084a2c2 100644 --- a/src/util/format.ts +++ b/src/util/format.ts @@ -33,39 +33,59 @@ export const plural = (number: number, singular: string, plural: string) => export const timeSince = ( start: Date, end: Date, - minutes = false, - seconds = false, + { + accuracy = "hours", + floor = true, + }: { + accuracy?: "seconds" | "minutes" | "hours"; + floor?: boolean; + } = {}, ) => { - const diff = Math.abs(end.getTime() - start.getTime()); - const secs = Math.floor(diff / 1000); - const mins = seconds - ? Math.floor(diff / 1000 / 60) - : Math.round(diff / 1000 / 60); - const hours = - minutes || seconds - ? Math.floor(diff / 1000 / 60 / 60) - : Math.round(diff / 1000 / 60 / 60); - const days = Math.floor(diff / 1000 / 60 / 60 / 24); + // Determine our accuracy + const minutes = accuracy === "minutes" || accuracy === "seconds"; + const seconds = accuracy === "seconds"; + // Get the difference in seconds + const diff = Math.abs((end.getTime() - start.getTime()) / 1000); + + // Get the values for each unit + let secs = Math.round(diff); + let mins = Math[floor ? "floor" : "ceil"](secs / 60); + let hours = Math[floor ? "floor" : "ceil"](mins / 60); + const days = Math[floor ? "floor" : "ceil"](hours / 24); + + // Truncate the values + secs %= 60; + mins %= 60; + hours %= 24; + + // Decide which units to show const parts = [ - // Only show days if there are days - days > 0 && plural(days, "day", "days"), - // Only show hours if there are hours, seconds, or minutes - hours > 0 && - (hours % 24 !== 0 || - (minutes && mins % 60 !== 0) || - (seconds && secs % 60 !== 0)) && - plural(hours % 24, "hour", "hours"), - // Only show minutes if there are minutes or seconds - minutes && - mins > 0 && - (mins % 60 !== 0 || (seconds && secs % 60 !== 0)) && - plural(mins % 60, "minute", "minutes"), - // Only show seconds if there are seconds - seconds && secs > 0 && plural(secs % 60, "second", "seconds"), + // We'll show the number of days if it's non-zero + ...(days ? [plural(days, "day", "days")] : []), + // We'll show the number of hours if it's non-zero + // We'll also show the number of hours if there are days, and minutes are enabled, and they're non-zero + // We'll also show the number of hours if there are days, and seconds are enabled, and they're non-zero + ...(hours || (days && minutes && mins) || (days && seconds && secs) + ? [plural(hours, "hour", "hours")] + : []), + // We'll show the number of minutes if they're enabled and non-zero + // We'll also show the number of minutes if there are days or seconds, and if seconds are enabled, and they're non-zero + ...((minutes && mins) || ((days || hours) && seconds && secs) + ? [plural(mins, "minute", "minutes")] + : []), + // We'll also show the number of seconds if they're enabled and non-zero + ...(seconds && secs ? [plural(secs, "second", "seconds")] : []), ].filter(Boolean); - // Format as a well-formed list + // If we have no parts, return less than + if (!parts.length) { + if (accuracy === "seconds") return "less than a second"; + if (accuracy === "minutes") return "less than a minute"; + return "less than an hour"; + } + + // Otherwise, return a well-formatted list if (parts.length < 3) return parts.join(" and "); return `${parts.slice(0, -1).join(", ")}, and ${parts.slice(-1)}`; }; diff --git a/src/util/messages.ts b/src/util/messages.ts index 9c716b9..b73551e 100644 --- a/src/util/messages.ts +++ b/src/util/messages.ts @@ -9,17 +9,16 @@ export const notStarted = (start: Date) => { const now = getNow(); if (start < now) return null; - // Check if we're within the same day - const sameDay = - start.getUTCFullYear() === now.getUTCFullYear() && - start.getUTCMonth() === now.getUTCMonth() && - start.getUTCDate() === now.getUTCDate(); + // Check if we're within the final day + const finalDay = start.getTime() - now.getTime() <= 1000 * 60 * 60 * 24; - // Get time until we start (show minutes if within the same day) - const timeRemaining = italic(timeSince(start, now, sameDay)); + // Get time until we start (show minutes if within the final day) + const timeRemaining = italic( + timeSince(start, now, { accuracy: finalDay ? "minutes" : "hours" }), + ); // If we're within the same day, show the time - if (sameDay) { + if (finalDay) { return ( `<:JingleJammy:1047503567981903894> Jingle Jam launches in ${timeRemaining}!` + "\n:black_small_square: Get ready to raise money for some awesome causes and grab the collection when it goes live." @@ -46,14 +45,19 @@ export const thanks = (end: Date, year: number) => { ); } - // Get time until we end - const timeRemaining = italic(timeSince(now, end)); + // Check if we're within the final hour + const finalHour = end.getTime() - now.getTime() <= 1000 * 60 * 60; + + // Get time until we end (show minutes if within the final hour) + const timeRemaining = italic( + timeSince(now, end, { accuracy: finalHour ? "minutes" : "hours" }), + ); // Otherwise, show the time remaining return ( `<:Jammy_LOVE:1047503543935967273> Thank you for supporting some wonderful causes!` + `\n:mega: There ${ - /^\D*1 /.test(timeRemaining) ? "is" : "are" + /^(\D*1|less) /.test(timeRemaining) ? "is" : "are" } still ${timeRemaining} remaining to get involved and grab the collection at ` ); };