Relative times

Last week Phil posted a little update about his excellent site,

If you’re in the habit of visiting the Recently Updated Blogs page, and leaving it open, the times when each blog was updated will now keep up with the relentless passing of time.

Does that make sense? “3 minutes ago” will change to “4 minutes ago” and so on and on and on, until you refresh the page.

I thought that was a nice little addition, and I immediately thought of The Session. There are time elements all over the site with relative times as the text content: 2 minutes ago, 7 hours ago, 1 year ago, and so on. Those strings of text are generated on the server. But I figured it would be nice enhancement to periodically update them in the browser after the page has loaded.

I viewed source to see how Phil was doing it. The code is nice and short, using a library called Day.js with a plug-in for relative time.

“Hang on”, I thought, “isn’t there some web standard for doing this kind of thing?” I had a vague memory of some JavaScript API for formatting dates and times.

Sure enough, we’ve now got the Intl.RelativeTimeFormat object. It’s got browser support across the board.

Here’s the code I wrote.

I’ve got a function that loops through all the time elements with datetime attributes. It compares the current timestamp to that value to get the elapsed time. Then that’s formatted using the format() method and output as innerText.

You need to tell the format() method which units you want to use: seconds, minutes, hours, days, etc. So there’s a little bit of looping to figure out which unit is most appropriate. If the elapsed time is less than a minute, use seconds. If the elapsed time is less than an hour, use minutes. If the elapsed time is less than a day, use hours. You get the idea.

It’s a pity there isn’t some kind of magic unit like “auto” to do this, but it’s not much extra code to figure it out.

Anyway, that function runs periodically using setInterval(). I’ve set it to run every 30 seconds in my gist. On The Session I’ve set it to one minute.

You’ll notice that I’m grabbing all the relevant time elements—using document.querySelector('time[datetime]')—every time the function is run. That may seem inefficient. Couldn’t I just grab them once and then keep them stored as an array? But I want this to work even if the page contents have been updated with Ajax. (Do people even say “Ajax” any more? Get off my lawn, you pesky kids!)

I think I’ve written this code in an abstract way so that you should be able to drop it into any web page. For the calculations to work, you’ll need to either make sure that your datetime attributes are using timezones. Or, if there’s no timezone info, UTC is assumed.

This was a fun little piece of functionality to play around with. Now I know a little more about this Intl.RelativeTimeFormat object. The way I’m using it as a classic example of progressive enhancement. If a browser doesn’t support it, or if my code breaks, it’s no big deal. The funtionality is a little bonus that almost nobody will notice anyway. Just a small delighter …if you’re the kind of person who finds it delightful when relative time strings automatically update.

Have you published a response to this? :


Phil Gyford

@adactio Ooh, nice! Thank you for writing that up. I’ll be delighted to copy that – including a whole library for that one tiny feature seemed a bit overkill.


# Shared by on Monday, August 7th, 2023 at 12:16pm

# Shared by Chris Taylor on Tuesday, August 8th, 2023 at 7:12am

# Shared by Clearleft on Tuesday, August 8th, 2023 at 12:28pm


# Liked by Chee Aun 🤔 on Monday, August 7th, 2023 at 12:16pm

# Liked by on Monday, August 7th, 2023 at 12:16pm

# Liked by greg on Monday, August 7th, 2023 at 12:44pm

# Liked by Large Heydon Collider on Monday, August 7th, 2023 at 1:17pm

# Liked by Chris Taylor on Tuesday, August 8th, 2023 at 7:12am

# Liked by Clearleft on Tuesday, August 8th, 2023 at 12:28pm

# Liked by John Michel on Wednesday, August 9th, 2023 at 3:51am

# Liked by Pratyush Mittal on Wednesday, August 16th, 2023 at 5:03am

Previously on this day

5 years ago I wrote Console methods

Debugging fetch events in service workers.

10 years ago I wrote August in America, day four

Alexandria, Virginia.

19 years ago I wrote Lust

This collection of 1920s erotic photos features one flapper with a mandolin and another with a bouzouki.

19 years ago I wrote Anger

If you’d like to make a difference in the ever-worsening situation in Darfur, please, please, please make a donation (via the secure WorldPay service) to the World Food Program. I’ve made a modest contribution which, by itself, won’t amo

19 years ago I wrote Envy

File this under "Now, why didn’t I think of that?".

19 years ago I wrote Greed

I finally caved in and succumbed to the temptation of owning the style gadget de-siècle. I’ve ordered an iPod.

19 years ago I wrote Gluttony

Richard points out that Jamie Oliver’s website is now written in XHTML and CSS.

19 years ago I wrote Sloth

When I really should be working, the last thing I need to read is this excellent article by Tom Hodgkinson in The Guardian entitled The Virtue Of Idleness, taken from his forthcoming book How To Be Idle:

19 years ago I wrote Pride

It’s that time of year again. Brighton is party-central this weekend. Brighton Pride is an annual event celebrating the town—, sorry, city’s gay and lesbian community. It’s Fun with a capital F and it’s make me proud to live

20 years ago I wrote Wireless Mall

I’ve just made a nifty little discovery: the mall in Sierra Vista has Wi-Fi.

20 years ago I wrote Budd Blog

Brighton web designer, pal and all-round good guy Andy Budd has joined the blogosphere.

21 years ago I wrote Plustech Walking Technology

That is one cool looking machine. Eco friendly, too.

21 years ago I wrote Why I Hate Star Wars

"I thought it would be funny to go dressed up as Spock".