From 077a75dc45d610f9fe1cd7dd25d3c2d1a906a069 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Fri, 15 Nov 2024 14:43:43 +0100 Subject: [PATCH 1/3] Use an external `luxon` package The transaction table displays the relative time. The use of an external library luxon simplifies our logic. But it also solves the problem described below: - If a deposit was made at 12:00 and it's now 12:59 the counter shows the deposit was made 59 minutes ago. But if it's 13:01, the counter shows that the deposit was made 2 hours ago. --- dapp/package.json | 2 ++ dapp/src/utils/time.ts | 13 ++++++++++++- pnpm-lock.yaml | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/dapp/package.json b/dapp/package.json index 58e497878..97601a1a3 100644 --- a/dapp/package.json +++ b/dapp/package.json @@ -38,6 +38,7 @@ "ethers": "^6.10.0", "formik": "^2.4.5", "framer-motion": "^10.16.5", + "luxon": "^3.5.0", "mustache": "^4.2.0", "react": "^18.2.0", "react-confetti-explosion": "^2.1.2", @@ -51,6 +52,7 @@ "devDependencies": { "@sentry/vite-plugin": "^2.22.5", "@thesis-co/eslint-config": "github:thesis/eslint-config#7b9bc8c", + "@types/luxon": "^3.4.2", "@types/react": "^18.2.38", "@types/react-dom": "^18.2.17", "@typescript-eslint/eslint-plugin": "^6.12.0", diff --git a/dapp/src/utils/time.ts b/dapp/src/utils/time.ts index 494d73ddc..ea22baaed 100644 --- a/dapp/src/utils/time.ts +++ b/dapp/src/utils/time.ts @@ -9,6 +9,7 @@ import { ONE_YEAR_IN_SECONDS, } from "#/constants" import { TimeUnits } from "#/types" +import { DateTime } from "luxon" export const dateToUnixTimestamp = (date: Date = new Date()) => Math.floor(date.getTime() / ONE_SEC_IN_MILLISECONDS) @@ -65,6 +66,16 @@ export const getRelativeTime = (dateOrUnixTimestamp: Date | number): string => { return rtf.format(Math.floor(diff / divisor), unit) } +export const timestampToRelativeTime = (timestamp: number) => + DateTime.fromMillis(timestamp).toRelative() + +export const blockTimestampToRelativeTime = ( + unixTimestamp: number, +): string | null => { + const time = unixTimestamp * 1000 + return timestampToRelativeTime(time) +} + // The function displays the date in the format: 21 Nov 2024, 16:02 export const formatBlockTimestamp = (blockTimestamp: number) => new Date(blockTimestamp * ONE_SEC_IN_MILLISECONDS).toLocaleString( @@ -81,7 +92,7 @@ export const displayBlockTimestamp = (blockTimestamp: number) => { if (executedMoreThanDayAgo) return formatBlockTimestamp(blockTimestamp) - return getRelativeTime(blockTimestamp) + return blockTimestampToRelativeTime(blockTimestamp) } export const getExpirationDate = (duration: number, startDate?: Date) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 32d0141ee..cf2c53ac6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -83,6 +83,9 @@ importers: framer-motion: specifier: ^10.16.5 version: 10.18.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + luxon: + specifier: ^3.5.0 + version: 3.5.0 mustache: specifier: ^4.2.0 version: 4.2.0 @@ -117,6 +120,9 @@ importers: '@thesis-co/eslint-config': specifier: github:thesis/eslint-config#7b9bc8c version: https://codeload.github.com/thesis/eslint-config/tar.gz/7b9bc8c(eslint@8.57.0)(prettier@3.3.2)(typescript@5.4.5) + '@types/luxon': + specifier: ^3.4.2 + version: 3.4.2 '@types/react': specifier: ^18.2.38 version: 18.3.3 @@ -3622,6 +3628,9 @@ packages: '@types/lru-cache@5.1.1': resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} + '@types/luxon@3.4.2': + resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} + '@types/minimatch@3.0.5': resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} @@ -5873,6 +5882,7 @@ packages: ethereumjs-abi@0.6.8: resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} + deprecated: This library has been deprecated and usage is discouraged. ethereumjs-common@1.5.2: resolution: {integrity: sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==} @@ -7696,6 +7706,10 @@ packages: lru_map@0.3.3: resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + magic-string@0.30.10: resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} @@ -16132,6 +16146,8 @@ snapshots: '@types/lru-cache@5.1.1': {} + '@types/luxon@3.4.2': {} + '@types/minimatch@3.0.5': {} '@types/minimatch@5.1.2': {} @@ -21851,6 +21867,8 @@ snapshots: lru_map@0.3.3: {} + luxon@3.5.0: {} + magic-string@0.30.10: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 From 31b4e436254126e600ff040ecfc627519b9e664e Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Fri, 15 Nov 2024 15:00:07 +0100 Subject: [PATCH 2/3] Use `ONE_SEC_IN_MILLISECONDS` instead of 1000 --- dapp/src/utils/time.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dapp/src/utils/time.ts b/dapp/src/utils/time.ts index ea22baaed..375441934 100644 --- a/dapp/src/utils/time.ts +++ b/dapp/src/utils/time.ts @@ -72,7 +72,7 @@ export const timestampToRelativeTime = (timestamp: number) => export const blockTimestampToRelativeTime = ( unixTimestamp: number, ): string | null => { - const time = unixTimestamp * 1000 + const time = unixTimestamp * ONE_SEC_IN_MILLISECONDS return timestampToRelativeTime(time) } From 42f06c86bebefa1298a9e2aa070af55d4db436e5 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Fri, 15 Nov 2024 15:01:09 +0100 Subject: [PATCH 3/3] Remove unnecessary code --- dapp/src/utils/time.ts | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/dapp/src/utils/time.ts b/dapp/src/utils/time.ts index 375441934..6ff33dea0 100644 --- a/dapp/src/utils/time.ts +++ b/dapp/src/utils/time.ts @@ -3,10 +3,7 @@ import { ONE_DAY_IN_SECONDS, ONE_HOUR_IN_SECONDS, ONE_MINUTE_IN_SECONDS, - ONE_MONTH_IN_SECONDS, ONE_SEC_IN_MILLISECONDS, - ONE_WEEK_IN_SECONDS, - ONE_YEAR_IN_SECONDS, } from "#/constants" import { TimeUnits } from "#/types" import { DateTime } from "luxon" @@ -32,40 +29,6 @@ export const unixTimestampToTimeUnits = (targetUnix: number): TimeUnits => { } } -// unit, max diff, divisor -const unitsToDivisor: [Intl.RelativeTimeFormatUnit, number, number][] = [ - ["second", ONE_MINUTE_IN_SECONDS, 1], - ["minute", ONE_HOUR_IN_SECONDS, ONE_MINUTE_IN_SECONDS], - ["hour", ONE_DAY_IN_SECONDS, ONE_HOUR_IN_SECONDS], - ["day", ONE_WEEK_IN_SECONDS, ONE_DAY_IN_SECONDS], - ["week", ONE_MONTH_IN_SECONDS, ONE_WEEK_IN_SECONDS], - ["month", ONE_YEAR_IN_SECONDS, ONE_MONTH_IN_SECONDS], - ["year", Infinity, ONE_YEAR_IN_SECONDS], -] -const rtf = new Intl.RelativeTimeFormat(DATE_FORMAT_LOCALE_TAG) - -/** - * The problem of displaying relative time has already been solved in Threshold Network - * Let's use this logic to be able to display relative time such as: 2 mins ago, 3 hours ago... - * - * Source: - * https://github.com/threshold-network/token-dashboard/blob/main/src/utils/date.ts#L48-L61 - */ -export const getRelativeTime = (dateOrUnixTimestamp: Date | number): string => { - const time = - typeof dateOrUnixTimestamp === "number" - ? dateOrUnixTimestamp - : dateToUnixTimestamp(dateOrUnixTimestamp) - - const diff = Math.round(time - dateToUnixTimestamp()) - - const [unit, , divisor] = - unitsToDivisor.find(([, maxDiff]) => maxDiff > Math.abs(diff)) ?? - unitsToDivisor[0] - - return rtf.format(Math.floor(diff / divisor), unit) -} - export const timestampToRelativeTime = (timestamp: number) => DateTime.fromMillis(timestamp).toRelative()