Date and time
Loading "Date and Time"
Run locally for transcripts
In our application, we need to display a relative time label, like "1 minute ago", "3 days ago", etc. We've created a
getRelativeTime()
function to achieve that. It takes any given date and calculates how far ago it was compared to Date.now()
, returning a formatted string./**
* Return a relative time string from a given date.
*/
export function getRelativeTime(date: Date): string {
const delta =
Math.floor(Date.now() / 1000) - Math.floor(date.getTime() / 1000)
/**
* Use the standard `Intl.RelativeTimeFormat` API to produce human-friendly relative time strings.
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat
*/
const formatter = new Intl.RelativeTimeFormat('en', { style: 'long' })
switch (true) {
case delta < 60: {
return `Just now`
}
case delta < 3600: {
return formatter.format(-Math.floor(delta / 60), 'minute')
}
case delta < 86_400: {
return formatter.format(-Math.floor(delta / 3600), 'hour')
}
case delta < 2_620_800: {
return formatter.format(-Math.floor(delta / 86_400), 'day')
}
case delta < 31_449_600: {
return formatter.format(-Math.floor(delta / 2_620_800), 'month')
}
default: {
return formatter.format(-Math.floor(delta / 31_449_600), 'year')
}
}
}
We are also using the standardIntl.RelativeTimeFormat()
API to help us format the time: "1 minute ago" but "5 minutes ago". Give it a read if you're not familiar with it!
By using mocking, we can become magicians who can bend time and space! Well, maybe just time, for now. Vitest comes with a built-in
vi.useFakeTimers()
utility to make otherwise unpredictable date and time fixed and given.Since mocking time is such a common use case, Vitest gives you a more comfortable API to work with while also allowing to toggle between the "fake" and the "real" date whenever you need.
To reliably test our
getRelativeTime()
function, we have to freeze the date in our test. For example, by setting it to always be the 1st of June 2024:vi.useFakeTimers()
vi.setSystemTime(new Date('2024-06-01 00:00:00.000Z'))
// Any "new Date()" or "Date.now()" calls past this point
// will resolve to the midnight of the 1st of June 2024.
But this is, of course, not enough. We don't need a specific date but different days to model relative scenarios (1 minute ago, 2 months ago, etc). Loos like each test will exist in its own, separate little universe!
π¨βπΌ Complete the test suite for the
getRelativeTime()
function. Remember that vi.useFakeTimers()
is still a mock and must be treated as such (cleanup?). Verify your solution by running npm test
.