Created
September 2, 2023 09:53
-
-
Save DreamTexX/68771bc0413e2d10d4e06988fb31020a to your computer and use it in GitHub Desktop.
A simple svelte component to render a relative time in different languages using only web-apis.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- src/lib/components/utils/LocalizedRelativeTime.svelte --> | |
<script lang="ts"> | |
import { toRelativeLocalDate, toRelativeLocalDateWithUnit } from "$lib/intl/relative-time"; | |
import { onMount } from "svelte"; | |
export let date: Date; | |
export let language: string; | |
let { value, unitValue } = toRelativeLocalDateWithUnit(date, language); | |
let update: NodeJS.Timeout; | |
function runUpdate() { | |
update = setInterval(() => { | |
let intermediateValues = toRelativeLocalDateWithUnit(date, language); | |
value = intermediateValues.value; | |
if (intermediateValues.unitValue > unitValue) { | |
unitValue = intermediateValues.unitValue; | |
clearInterval(update); | |
runUpdate(); | |
} | |
}, unitValue); | |
} | |
onMount(runUpdate); | |
</script> | |
<!-- TODO: consider if it should render a static, localized date when prerendering for SEO --> | |
{value} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// src/lib/intl/relative-time.ts | |
const units: Array<[Intl.RelativeTimeFormatUnit, number]> = [ | |
["year", 24 * 60 * 60 * 1000 * 365], | |
["month", (24 * 60 * 60 * 1000 * 365) / 12], | |
["day", 24 * 60 * 60 * 1000], | |
["hour", 60 * 60 * 1000], | |
["minute", 60 * 1000], | |
["second", 1000] | |
]; | |
export function toRelativeLocalDateWithUnit( | |
date: Date, | |
language: string | |
): { value: string; unit: Intl.RelativeTimeFormatUnit; unitValue: number } { | |
let formatter = new Intl.RelativeTimeFormat(language, { numeric: "auto" }); | |
const elapsed = date.getTime() - new Date().getTime(); | |
for (const [unit, value] of units) { | |
if (Math.abs(elapsed) > value) { | |
return { | |
value: formatter.format(Math.ceil(elapsed / value), unit), | |
unit, | |
unitValue: value | |
}; | |
} | |
} | |
return { | |
value: formatter.format(Math.ceil(elapsed / 1000), "second"), | |
unit: "second", | |
unitValue: 1000 | |
}; | |
} | |
export function toRelativeLocalDate(date: Date, language: string): string { | |
return toRelativeLocalDateWithUnit(date, language).value; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script lang="ts"> | |
import LocalizedRelativeTime from "../utils/LocalizedRelativeTime.svelte"; | |
export let language: string; | |
</script> | |
<div> | |
Component was rendered <LocalizedRelativeTime date={new Date()} {language} /> | |
<br> | |
Komponente wurde <LocalizedRelativeTime date={new Date()} language="de-DE" /> erzeugt. | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment