Made in Builder

Made in Builder.io

Live Demo 👉 All Demo, No Pitch: Content & Commerce / Builder.io & Elastic Path on 12/13

×

Developers

Product

Use Cases

Pricing

Developers

Resources

Company

Get StartedLogin

Product

Features

Integrations

Talk to an Expert

Pricing

Blog

Home

Resources

Blog

Forum

Github

Login

Signup

×

Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required

Resources

Blog

Get StartedLogin

‹ Back to blog

Web Development

Fast and Light Relative Time Strings in JS

January 24, 2023

Written By Steve Sewell

Are you ever building something simple in JavaScript and go woah:

Screenshot of an import from 'moment' that it is 19.7kb gzipped

20kb for a simple date transformation??

All I wanted is a pretty output for a relative time. Like time is in 5 minutes or 2 weeks ago or tomorrow . You know, like your calendar can do, and Twitter, and kinda anything that needs to refer to a relative time in a friendly way.

Now, you may think, I got this, and begin doing something like:

Yeah… please don’t. While relative times may seem like a simple problem for a moment, you should begin to realize that relative time strings have a lot of complexities to address, like:

  • Pluralization: we don’t say "1 days ago" or "in 1 minutes"
  • Abbreviation: who even says "1 day ago"? Humans say words like "yesterday", "tomorrow", or "next year"
  • Future vs past: such as how we don’t say "in -2 days", we say "2 days ago"
  • Localization: This is the big one. Not only is translating complex across many languages (including localized differences to the above bullets), if you even built all of that into your function, you would end up with a massive payload of localized rules and variations.

Why do you think moment.js is so large? It’s not because of incompetent developers. It’s because time and date handling across all of the above criteria is simply complex.

So, before you go and try to do something like this:

Just, please, don’t. There is a solution, and it’s built into browsers.

Intl.RelativeTimeFormat to the rescue

When you're in these situations, it's important to remember that the web platform has been evolving a lot, and these days has so many solutions to common problems built-in.

There is where the Intl object has a number of solutions. For our use case today, we want Intl.RelativeTimeFormat

And, as expected, it works beautifully across locales:

To make things more convenient, you can even just pass in the current navigator.language as the first argument as well:

And supported units include: "year""quarter""month""week""day""hour""minute", and "second"

Making it useful

Returning to our original example, what we really want is something that can automatically pick the appropriate unit to use, so it will print "yesterday" for a date that is 1 day ago, and "next year" for a date that is a year from now (as opposed to "in 370 days" or "in 52 weeks" etc).

So, ideally, we’d have just a simple wrapper function like:

Now that we have Intl.RelativeTimeFormat in our toolkit, we can implement this pretty simply. The only real question is what unit we should choose for the given time delta ("hour", "day", etc)

Here is one simple solution in TypeScript:

Thank you to LewisJEllis for this code snippet that is a simplification of my original quick and dirty solution.

Using date-fns

If you don’t want to have to roll your own solution, there is an open source answer for you as well. date-fns is a great utility library for dates in JavaScript, each exported individually in a tree shakeable way.

Built into date-fns is an intlFormatDistance function that is a tiny wrapper over Intl.RelativeTimeFormat and does exactly what we need, and under 2kb.

Screen Shot 2023-01-23 at 4.03.44 PM.png

You can see the source code for it here and compare it to our above example implementation, if you like.

Browser and runtime support

Heres the best part. Intl.RelativeTimeFormat is supported by all major browsers, as well as Node.js and Deno:

Screenshot from the link below (MDN) of the browser support table showing support by all modern browsers

Source: MDN

Explore more of what Intl can do

Now that we’ve got our relative time string solution, let’s quickly peek at a couple other cool constructors on the Intl object, to get a sense of what else it can do.

A couple of my favorites are:

Date formatting with Intl.DateTimeFormat

Intl.DateTimeformat gives you browser native date and time formatting:

Intl.DateTimeFormat is supported by all major browsers, Node.js, and Deno.

Number formatting with Intl.NumberFormat

Intl.NumberFormat gives you browser native number formatting:

Intl.NumberFormat is supported by all major browsers, Node.js, and Deno.

Conclusion

If you’re still using large date handling libraries like moment - modern JavaScript has got you fam, with Intl.RelativeTimeFormat, Intl.DateTimeFormat, and more.

About me

Hi! I'm Steve, CEO of Builder.io.

We make a way to drag + drop with your components to create pages and other CMS content on your site or app, visually.

You can read more about how this can improve your workflow here.

You may find it interesting or useful:

Visually build with your components

Builder.io is a Visual CMS that let's you drag and drop to create content on your site visually, using your components.

Stop drowning in a backlog of requests - build with your whole team instead.

Try it out
Learn more

Share

Twitter
LinkedIn
Facebook

Continue Reading
Web Performance14 MIN
Optimal Images in HTML
WRITTEN BYSteve Sewell
January 26, 2023
web development9 MIN
The Tailwind CSS Drama Your Users Don't Care About
WRITTEN BYYoav Ganbar
January 25, 2023
testing7 MIN
End-to-End Testing With Playwright And Github Actions
WRITTEN BYAdam Bradley
December 1, 2022

Product

Visual CMS

Theme Studio for Shopify

Sign up

Login

Featured Integrations

React

Angular

Next.js

Gatsby

Get In Touch

Chat With Us

Twitter

Linkedin

Careers

© 2020 Builder.io, Inc.

Security

Privacy Policy

Terms of Service

Visually build and optimize digital experiences on any tech stack. No coding required, and developer approved.

Sign up

Log in

DEVELOPERS

Builder for Developers

Developer Docs

Github

JSX Lite

Qwik

INTEGRATIONS

React

Angular

Next.js

Gatsby

PRODUCT

Product features

Pricing

RESOURCES

User Guides

Blog

Forum

Templates

COMPANY

About

Careers 🚀

Visually build and optimize digital experiences on any tech stack. No coding required, and developer approved.
Get Started
Log in

DEVELOPERS

Builder for Developers

Developer Docs

Open Source Projects

Performance Insights

PRODUCT

Features

Pricing

RESOURCES

User Guides

Blog

Community Forum

Templates

Partners

Submit an Idea

INTEGRATIONS

React

Next.js

Gatsby

Angular

Vue

Nuxt

Hydrogen

Salesforce

Shopify

All Integrations

Security

Privacy Policy

Terms of Service

By clicking “Subscribe”, I agree to Builder.io's Terms of Service and Privacy Policy.