Written by Amazing Enyichi Agu✏️
Manipulating date and time is an essential feature of JavaScript. JavaScript developers use the built-in Date
constructor to create date objects. In turn, these date objects allow them to perform date and time operations in JavaScript and build related functionalities for their applications.
The code example below creates a Date
object. This object has various methods, like getFullYear()
and setMonth()
, and developers can use these methods to manipulate dates in the language:
const time = new Date();
console.log(time.getFullYear());
// 2024
However, JavaScript encodes dates fundamentally as the number of milliseconds since the Unix epoch (midnight of 1 January 1970), without any time zones attached.
Because of the simplistic way JavaScript dates work (along with other quirks they have), it can be complicated to use native JavaScript dates to build applications that are supposed to account for time zone differences, geographical differences in date formatting, and daylight saving time (DST). To solve some of these problems, libraries like Moment.js became the standard for doing anything extensive with dates.
Today, there are many JavaScript libraries available for handling dates, and they all have their own strengths and weaknesses. In this article, we will learn more about the Tempo library. According to their documentation, it is arguably “the easiest way to work with dates in JavaScript.”
Tempo stands out because it provides correct date formatting for any locale, parsing of date strings — in any format — to date objects, and a simple API. It also doesn’t need additional plugins for full functionality.
To follow this guide, you will need a basic understanding of how to work with dates in JavaScript. By the end, you should understand the capabilities of Tempo and why it might be better than other date manipulation libraries. Let’s get started!
What is Tempo?
Tempo is a TypeScript/JavaScript date library that is used for formatting, parsing, and modifying dates and times. The creator of the library, Justin Schroeder — who is also the creator of FormKit — needed a solution for time zone and formatting issues with JavaScript dates. No other libraries could solve these problems in a manner he deemed fit, so he built Tempo, which was released in February 2024.
Under the hood, Tempo uses the JavaScript Intl.DateTimeFormat
constructor to handle time zones and present locale-aware date formats. It also works with the Date
constructor in JavaScript. Tempo doesn’t create its own custom date objects like a few other libraries do. Because it uses existing JavaScript utilities, the entire library’s size is significantly small.
Tempo features
Tempo has many advantages, including excellent handling of timezone differences, bi-directional parsing of dates (from date string in any format to date object), no need for extra plugins, an easy-to-use API, good documentation, and more. FormKit uses Tempo to implement its datepicker
input functionality.
Uses native JavaScript objects: As we mentioned earlier, Tempo provides functions for working with the native Date
object. It also uses the Intl.DateTimeFormat
constructor to extract time zone data and locale-aware date formats.
Highly tree-shakable: Tree shaking refers to the removal of dead code — code that has no effect on the program. In JavaScript, tree shaking uses import
and export
statements to determine which modules are used in JavaScript files. With Tempo, the production code only includes the imported functions, resulting in better performance.
Versatile parsing techniques: As mentioned earlier, Tempo easily converts date strings in any format to a date object. The default format for parsing is ISO 8601, but specifying the other formats before parsing also works really well. Parsing from any date format is a feature most date libraries lack.
Date modification: Tempo has many functions for modifying dates. You can easily use it to add a day, a month, or a year to a particular date. The library can also easily calculate what the date and time is in another time zone.
Helper functions: Tempo offers a couple of functions that help with handling dates, including sameMinute()
, sameHour()
, isBefore()
, isAfter()
, and isEqual()
. These functions accept an ISO 8601 string or a Date
object and return a Boolean.
How to install Tempo
To install Tempo, all you need is a JavaScript runtime and a package manager. The code below shows how to install using npm, but a similar method applies for Yarn or pnpm:
npm install @formkit/tempo
How to format dates with Tempo
One useful function Tempo exports is format
, which converts a JavaScript date object or an ISO 8601 string into a date format string. By default, the function outputs date strings in whatever locale the user is in, but it can also present dates in other locales if they are specified.
With the format
function, you can set a date display style — i.e., full
, short
, long
:
import { format } from '@formkit/tempo'
const date = new Date()
format(date, 'full')
// Friday, March 15, 2024
format(date, 'full', 'fr')
// vendredi 15 mars 2024
Tempo also uses format tokens, similar to the Day.js library, to display dates:
import { format } from '@formkit/tempo'
const time = new Date()
format(time, 'dddd, MMMM D, YYYY h:mm:ss a', 'it')
// venerdì, marzo 15, 2024 12:04:21 pm
format(time, 'h:mm:ss A', 'en')
// 12:04:21 PM
This is how you can format dates and times according to a specific time zone:
import { format } from '@formkit/tempo'
format({
date: new Date(),
format: 'HH:mm A',
tz: 'Africa/Lagos'
})
// 12:08 PM
How to perform date operations with Tempo
There are several ways to modify dates with Tempo. You can add and remove seconds, minutes, hours, days, weeks, months, and years using the provided functions. These functions accept either an ISO 8601 string or a Date
object, and they return a new Date
object:
import { addDay, addMonth } from '@formkit/tempo'
const testDate = '2020-11-20'
// Add 1 Month
addMonth(testDate)
// Add 3 Months
addMonth(testDate, 3)
// Subtract 5 days
addDay(testDate, -5)
You can also apply a time zone to a date, thereby modifying it. First, obtain the offset of a particular time zone to the date you want to modify, then modify the date with the obtained time zone to get a new Date
object:
import { offset, applyOffset, removeOffset } from '@formkit/tempo'
const testTime = '2020-11-20 03:00'
const londonOffset = offset(testTime, 'Europe/London')
// Applying a timezone offset
applyOffset(testTime, londonOffset)
// Removing a timezone offset
removeOffset(testTime, londonOffset)
Finally, Tempo provides the function tzDate
, which converts an ISO 8601-like string into a Date
object with a time zone applied:
import { tzDate } from '@formkit/tempo'
tzDate('2020-11-20 03:00', 'Africa/Lagos')
Finding the difference between two dates
One task you can perform with Tempo is to find the difference between two dates (or times). Tempo keeps track of time zone information when calculating the difference between two dates.
Because Tempo uses the native Date
object, it is easy to subtract dates from each other like one would do with normal JavaScript:
import { tzDate } from '@formkit/tempo'
const currentTime = tzDate(new Date(), 'Africa/Lagos')
const lastChristmas = tzDate('2023-12-25', 'America/New_York')
function timeDifference(dateA, dateB) {
const millisecondsDiff = Math.abs(dateA - dateB)
const daysDiff = Math.floor(millisecondsDiff / (1000 * 60 * 60 * 24))
return `${daysDiff} days`
}
timeDifference(currentTime, lastChristmas)
// 82 days
Using this method, we can calculate the number of minutes, seconds, weeks, etc., between any two points in time. The function obtains the two date objects, calculates their differences, and displays them, all while taking note of DST and time zone differences.
Date internationalization (i18n) with Tempo
Internationalization is the ability for a program to present information in different languages and for different locations. It is shortened as i18n (18 here is the number of letters between “i” and “n”). Tempo is excellent in its i18n capabilities — in fact, it is one of the core strengths of the library.
In Tempo, one can display dates in any locale using the format
function, which we explored earlier. Tempo can also present date and time in any language, which it does with the help of the JavaScript Intl.DateTimeFormat
constructor. The API for doing all of this is in the Tempo documentation.
Tempo vs. Day.js
Day.js is a lightweight alternative to the now deprecated date and time handling library, Moment.js. It is written in JavaScript and uses a similar API to Moment.js. Day.js is sufficient for date operations such as parsing, manipulation, and display. It is designed for use on both the browser and the Node.js runtime.
Day.js is the most popular date library in JavaScript. At the moment, it has over 45K stars on GitHub and 19.7M npm weekly downloads, as opposed to Tempo, which is newer and has 1.8K stars on GitHub and about 8K downloads on npm.
To work with dates in Day.js, you will need to create a Day.js object. It doesn’t work with the native JavaScript date object like Tempo does. For example, here is how to create an object of the current date and time on Day.js:
const now = dayjs()
The syntax for Day.js mostly relies on method chaining, which is a style the author of Tempo actively avoided when building the library because it can be problematic for tree shaking, and does not offer any particular benefits. Below is an example of this chaining behavior in Day.js:
dayjs('2024-03-18').add(3, 'month').subtract(2, 'year').toString()
Despite this, Day.js offers a few more methods for date customization than Tempo, and it contains many useful helper functions. The downsides of Day.js is that it requires plugins for those extended features. Working with time zones also requires plugins. Those functionalities do not come with the library by default.
Tempo vs. date-fns
date-fns is a JavaScript date-handling library written in TypeScript. It was first released in 2014. date-fns works in both the browser and Node.js. It also supports working with TypeScript and Flow (the JavaScript typechecker). date-fns is very popular, with 33.4K stars on GitHub and 20.5M npm weekly downloads, at the time of writing.
date-fns has a package size of 17.2KB when minified and gzipped, as opposed to Tempo, which is 5.5KB. date-fns supports tree shaking, which means that one simply picks the modules they want and only those modules are added to the production build.
date-fns works with the native JavaScript Date
object — it does not come with its own date object like Day.js. In this sense, it is similar to Tempo. But working with time zones and DST in date-fns requires an additional library: date-fns-tz — it does not come with time zone support by default. The date-fns-tz library uses the JavaScript Intl
API to work with timezones, which is also similar to Tempo.
date-fns has excellent support for i18n. It can display date formats in so many locales. But the downside is that it requires the developer to import whichever locale they need as a separate module, as opposed to Tempo, which doesn’t need locale modules imported as a module or a plugin.
date-fns also supports chaining like Day.js. However, it has the option of using a functional programming style whenever developers use the functions from its fp
submodule. date-fns has a unique formatting style, and the formatting is more extended than Tempo. Despite that, it may take more time getting used to date-fns than Tempo, which has an easier learning curve.
Tempo vs. Luxon
Luxon is another date and time library written in JavaScript. Luxon works on both browsers and Node.js. The author of Luxon, Isaac Cambrion, was also a contributor to Moment.js before it became deprecated. Now, the team behind Moment.js recommends Luxon, calling it “an evolution of Moment.js.” Luxon’s documentation can even be found in GitHub pages for Moment.js.
At the time of this article, Luxon has 14.8K stars on GitHub, and gets 7 million downloads weekly on npm. It is quite popular and widely used in many projects.
Luxon comes with a custom object, DateTime
, which is used to create dates and time. The library does not use the native JavaScript Date
object. For example, this is how to capture the system date in Luxon:
import { DateTime } from 'luxon'
const now = DateTime.now()
Luxon is a very comprehensive library, with many essential features. The library allows for parsing of localized date strings and has many formatting options. For i18n, Luxon uses the native JavaScript Intl
API. It also works very well with different time zones. There are no plugins, extra modules, or extensions that come with Luxon. All the functionality of the library comes from the DateTime
object.
As mentioned earlier, Tempo favors a more functional programming style. Luxon, on the other hand, uses method chaining patterns, similar to Moment.js and Day.js. For example, here is how to format a date in full:
const currentTime = DateTime.now().toFormat("FFFF")
// Tuesday, March 19, 2024 at 12:32:09 PM West Africa Standard Time
When it comes to size, Luxon is the heaviest of all the libraries compared to Tempo in this article. When minified and gzipped, it is 23KB. Tempo beats Luxon in being more lightweight while still handling dates very efficiently.
Comparing the libraries
Below is a table that summarizes the features of the different date and time-handling libraries discussed in this article:
Libraries | Tempo | Day.js | date-fns | Luxon |
---|---|---|---|---|
npm weekly downloads | ~ 8 K | ~ 20 M | ~ 20 M | ~ 7 M |
GitHub stars | 1.9 K | 45.5 K | 33.5 K | 14.8 K |
Package size (Minified + Gzipped) | 5.5 KB | 3 KB | 17.2 KB | 23 KB |
Plugins (or extensions) | No | Yes | Yes | No |
Browser compatibility | Not specified | Yes | Yes | Yes |
Native JavaScript dates | Yes | No | Yes | No |
Release year | 2024 | 2018 | 2014 | 2014 |
Should you use Tempo for your next project?
In this article, we introduced the Tempo library, discussed what it is used for, and covered its features and capabilities, as well as learned a bit about how it works under the hood. We also compared Tempo to other popular JavaScript date libraries like Day.js, date-fns, and Luxon.
Even with the initial pitfalls of JavaScript dates, the ecosystem managed to tackle those challenges with good libraries. Some use the native JavaScript date while others have instead created their own robust tools to make up for the quirks JavaScript dates might have. With the JavaScript Temporal API about to roll out, working with dates and time in JavaScript will only improve.
So, should you use Tempo for your next project? Well, if you want a tool that is easy to understand at a glance, achieves basic tasks with dates, has good parsing and formatting abilities, has good documentation, is lightweight, and highly tree-shakable, then sure — you should use Tempo. It does most of the things we need modern JavaScript date libraries for, and it does them well.
Are you adding new JS libraries to build new features or improve performance? What if they’re doing the opposite?
There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.
LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.
LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.
Build confidently — start monitoring for free.
Top comments (0)