From e9ff59708aa102b13a033cfc0418e4f0cc21f2e2 Mon Sep 17 00:00:00 2001 From: Attila Gazso <230163+agazso@users.noreply.github.com> Date: Thu, 21 Sep 2023 17:34:54 +0200 Subject: [PATCH] feat: chat list timestamp (#426) --- src/lib/utils/format.test.ts | 23 ++++++++++++++- src/lib/utils/format.ts | 54 ++++++++++++++++++++++++++++++++++++ src/routes/+page.svelte | 4 +++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/lib/utils/format.test.ts b/src/lib/utils/format.test.ts index c063e27e..06fa7dd7 100644 --- a/src/lib/utils/format.test.ts +++ b/src/lib/utils/format.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest' -import { toDecimal, toSignificantString, toBigInt } from './format' +import { toDecimal, toSignificantString, toBigInt, formatTimestamp } from './format' describe('toDecimal', () => { const testValues = [ @@ -55,3 +55,24 @@ describe('toBigInt', () => { }) }) }) + +describe('formatTimestamp', () => { + const currentDate = new Date(1695301187859) + const testValues = [ + { timestamp: 1695292194040, expectedOut: '12:29' }, + { timestamp: 1695292052039, expectedOut: '12:27' }, + { timestamp: 1695215231556, expectedOut: 'Wed' }, + { timestamp: 1695213720514, expectedOut: 'Wed' }, + { timestamp: 1695213620936, expectedOut: 'Wed' }, + { timestamp: 1695136556259, expectedOut: 'Tue' }, + { timestamp: 1695062899168, expectedOut: 'Mon' }, + { timestamp: 1694447288453, expectedOut: 'Sep 11' }, + { timestamp: 1694258558099, expectedOut: 'Sep 9' }, + ] + + testValues.forEach(({ timestamp, expectedOut }) => { + it(`with timestamp=${timestamp} should return ${expectedOut}`, () => { + expect(formatTimestamp(timestamp, currentDate)).toEqual(expectedOut) + }) + }) +}) diff --git a/src/lib/utils/format.ts b/src/lib/utils/format.ts index 4024849f..9096b0d7 100644 --- a/src/lib/utils/format.ts +++ b/src/lib/utils/format.ts @@ -96,3 +96,57 @@ export function formatDateAndTime(timestamp: number) { const dateTime = timeFormat.format(date) return `${dateString} at ${dateTime}` } + +export function formatTimestamp(timestamp: number, currentDate = new Date()) { + if (timestamp <= 0) { + return '' + } + + const locale = new Intl.DateTimeFormat().resolvedOptions().locale + const date = new Date(timestamp) + + // today at 00:00 + const today = new Date( + currentDate.getFullYear(), + currentDate.getMonth(), + currentDate.getDate(), + 0, + 0, + 0, + 0, + ) + + // a week before `today` + // this is used for the calculating a day, but it should not include + // the same day twice, hence we only count the last 6 days + const lastWeek = new Date(today.valueOf() - 6 * 24 * 60 * 60 * 1000) + + // if it is today, show only the time with a 24 hour clock + if (timestamp >= today.valueOf()) { + const timeFormat = new Intl.DateTimeFormat(locale, { + hour: 'numeric', + minute: 'numeric', + hour12: false, + }) + const dateTime = timeFormat.format(date) + + return dateTime + } + + // if it is last week, show only the day of the week + if (timestamp >= lastWeek.valueOf()) { + const dayFormat = new Intl.DateTimeFormat(locale, { + weekday: 'short', + }) + + return dayFormat.format(date) + } + + // if it is older than a week, show the month and day + const dateFormat = new Intl.DateTimeFormat(locale, { + month: 'short', + day: 'numeric', + }) + + return dateFormat.format(date) +} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 2dc04846..a4e2c444 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -20,6 +20,7 @@ import AuthenticatedOnly from '$lib/components/authenticated-only.svelte' import Layout from '$lib/components/layout.svelte' import Events from '$lib/components/icons/events.svelte' + import { formatTimestamp } from '$lib/utils/format' $: orderedChats = Array.from($chats.chats) .map(([, chat]) => chat) @@ -184,6 +185,9 @@ {/if} + + {formatTimestamp(lastMessage?.timestamp ?? 0)} +

{#if chat.joined}