diff --git a/frontend/src/app/how-to/page.tsx b/frontend/src/app/how-to/page.tsx
index e7e7f48..2f36355 100644
--- a/frontend/src/app/how-to/page.tsx
+++ b/frontend/src/app/how-to/page.tsx
@@ -54,7 +54,7 @@ const Page = async () => {
{t('help:p7')}
@@ -65,11 +65,11 @@ const Page = async () => {
diff --git a/frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx b/frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx
index 13157b8..ae31ff3 100644
--- a/frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx
+++ b/frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx
@@ -10,7 +10,7 @@ import { PersonResponse } from '/src/config/api'
import { useTranslation } from '/src/i18n/client'
import { useStore } from '/src/stores'
import useSettingsStore from '/src/stores/settingsStore'
-import { calculateAvailability, calculateColumns, calculateRows, convertTimesToDates, makeClass } from '/src/utils'
+import { calculateAvailability, calculateColumns, calculateRows, convertTimesToDates, makeClass, relativeTimeFormat } from '/src/utils'
import styles from './AvailabilityViewer.module.scss'
@@ -188,7 +188,7 @@ const AvailabilityViewer = ({ times, timezone, people }: AvailabilityViewerProps
}}
onMouseOver={() => setTempFocus(person.name)}
onMouseOut={() => setTempFocus(undefined)}
- title={Temporal.Instant.fromEpochSeconds(person.created_at).until(Temporal.Now.instant()).toLocaleString()}
+ title={relativeTimeFormat(Temporal.Instant.fromEpochSeconds(person.created_at), i18n.language)}
>{person.name}
)}
diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts
index 5561189..35ef3d5 100644
--- a/frontend/src/utils/index.ts
+++ b/frontend/src/utils/index.ts
@@ -6,3 +6,4 @@ export * from './calculateAvailability'
export * from './calculateRows'
export * from './calculateColumns'
export * from './getWeekdayNames'
+export * from './relativeTimeFormat'
diff --git a/frontend/src/utils/relativeTimeFormat.ts b/frontend/src/utils/relativeTimeFormat.ts
new file mode 100644
index 0000000..0b027a5
--- /dev/null
+++ b/frontend/src/utils/relativeTimeFormat.ts
@@ -0,0 +1,13 @@
+import { Temporal } from '@js-temporal/polyfill'
+
+const units = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'] as const
+
+export const relativeTimeFormat = (instant: Temporal.Instant, locale: string, fmtOptions: Intl.RelativeTimeFormatOptions = { style: 'long' }) => {
+ const fmt = new Intl.RelativeTimeFormat(locale, fmtOptions)
+ const duration = instant.since(Temporal.Now.instant(), { smallestUnit: 'seconds' })
+ .round({ largestUnit: 'years', relativeTo: instant.toZonedDateTimeISO(Temporal.Now.timeZoneId()) })
+
+ // Format to the largest unit
+ const unit = units.find(u => Math.abs(duration[u]) > 0) ?? units[units.length - 1]
+ return fmt.format(duration[unit], unit)
+}