Get a datetime attribute for HTML <time> (and other elements).
It covers the whole WHATWG specification in 4 functions:
datetime()for a specific moment (641 B compressed);datetimeTz()for a specific moment in a given timezone (903 B);duration()for a duration (284 B);tzOffset()for a timezone offset (332 B).
Additionally, a DateTime class (710 B) and some other functions are provided.
The package is lightweight (~ 1.37 KB compressed for import *), tree-shakeable, typed and tested.
- Summary usage
 - Installation
 - Usage
datetime()to express a moment at different levels of precision:- date
 - time and UTC time
 - datetime and UTC datetime
 - alternative to the UTC syntax with 
utc() - datetime separator
 
tzOffset()to express a timezone offsetdatetimeTz()to express a moment with a specific timezone offsetduration()to expressing a duration
 - The 
DateTimeclass - Other functions
daysBetween()to get the number of days between two datesweekNumber()to get the week number (in the year) of a date
 - Various:
 
import * from 'datetime-attribute'
const now = new Date()
datetime(now)                   // '2021-03-14'
datetime(now, 'time')           // '10:29'
datetimeTz(now, 'datetime', -7) // '2021-03-14T10:29-07:00'
utc(now, 'time')                // '09:29Z'
tzOffset(-9, -30) // '-09:30' (Marquesas Islands)
duration({ d: 4, h: 3, m: 17 }) // 'P4DT3H17M'
const importantMeeting = new DateTime(2021, 12, 17, 19, 00) // 17/11
const meetingWeek = importantMeeting.getWeek() // 46
importantMeeting.setWeek(meetingWeek + 1) // meeting now on 24/11
importantMeeting.to('week')        // 2021W47
importantMeeting.to('datetime')    // 2021-11-24T19:00
daysBetween(now, importantMeeting) // 248Install the package:
npm install datetime-attribute
Then, import the functions you need in your script:
// if you only need `datetime` and `duration`
import { datetime, duration } from 'datetime-attribute'
// if you need everything
import * from 'datetime-attribute'Not using a package manager? Download the package files in your project and take the files in /src.
datetime() accepts two optional arguments: a Date object, and a precision keywords.
import { datetime } from 'datetime-attribute'
const now = new Date() // We’re 14 March 2021 and it’s 10:29 in Brussels.
datetime(now)             // '2021-03-14'
datetime(now, 'datetime') // '2021-03-14T10:29'Without argument, it defaults to today:
datetime() // today formatted in YYYY-mm-dd
datetime((new Date()), 'day') // sameBy default, datetime() precision is day, resulting in a YYYY-mm-dd
output. Many other values are available.
| precision | example output | description | 
|---|---|---|
day | 
2021-03-14 | 
the default, fitting a calendar | 
year | 
2021 | 
only the year | 
yearless | 
03-14 | 
a day in a month | 
month | 
2021-03 | 
a month in a year | 
week | 
2021W10 | 
the week number (ISO-8601 spec) and its year | 
Time:
| precision | example output | description | 
|---|---|---|
time | 
10:29 | 
hours and minutes, like most clocks | 
second | 
10:29:00 | 
time with precision up to seconds | 
ms | 
10:29:00.000 | 
time with precision up to milliseconds | 
To get UTC time, add  utc to the time keyword:
| precision | example output | description | 
|---|---|---|
time utc | 
09:29Z | 
time, shifted to UTC time | 
second utc | 
09:29:00Z | 
second, shifted to UTC time | 
ms utc | 
09:29:00.000Z | 
ms, shifted to UTC time | 
Datetime:
| precision | example output | description | 
|---|---|---|
datetime | 
2021-03-14T10:29 | 
a local datetime (= date + time separated by T) | 
datetime second | 
2021-03-14T10:29:00 | 
time with precision up to seconds | 
datetime ms | 
2021-03-14T10:29:00.000 | 
time with precision up to milliseconds | 
To get UTC datetime, add  utc to the datetime keyword:
| precision | example output | description | 
|---|---|---|
datetime utc | 
2021-03-14T09:29Z | 
datetime, shifted to UTC time | 
datetime second utc | 
2021-03-14T09:29:00Z | 
datetime second, shifted to UTC time | 
datetime ms utc | 
2021-03-14T09:29:00.000Z | 
datetime ms, shifted to UTC time | 
💡 Instead of adding  utc to a time or datetime keyword, you can use utc(date, precision), which has datetime as default precision:
import { datetime, utc } from 'datetime-attribute'
const now =  new  Date()  // We’re 14 March 2021 and it’s 10:29 in Brussels.
// These are the same:
utc(now, 'time') // `09:29Z`
datetime(now, 'time utc') // `09:29Z`
// These are the same:
utc(now)             // `2021-03-14T09:29Z`
utc(now, 'datetime') // `2021-03-14T09:29Z`
datetime(now, 'datetime utc') // `2021-03-14T09:29Z`Per spec, the separator between date and time can be T (default) or   (1 space).
To change the separator globally, use setTimeSeparator:
import { setTimeSeparator } from 'datetime-attribute'
setTimeSeparator(' ')
// All next datetime functions will follow the new setting.
datetime(now) // `2021-03-14 10:29`
// Switch back to the default.
setTimeSeparator('T') // or `setTimeSeparator()`Setting the separator to a space can be useful to deal with MySQL or MariaDB DATETIME column.
Timezone offsets are a comparison against UTC time. For example, +01:00 means “one hour ahead of UTC time” and -05:00 means “five hours behind UTC time”.
tzOffset() accepts three optional arguments for hours, minutes, and compliance to real-world boundaries. Without argument, the local timezone offset is returned (and may differ based on daylight saving time).
import { tzOffset } from 'datetime-attribute'
tzOffset(3)      // '+03:00' (Moscow)
tzOffset(-9, -30) // '-09:30' (Marquesas Islands)
tzOffset(-9.5)   // '-09:30' (same with 1 parameter)
tzOffset(5, -30) // '+04:30' (Afghanistan)
tzOffset(5, 30)  // '+05:30' (India)
tzOffset(0)      //      'Z' (Ghana; 'Z' is equal to '+00:00')
// in Belgium
tzOffset()       // '+01:00'
tzOffset()       // '+02:00' (under daylight saving time)Per spec, the separator between hours and minutes is optional. The allowed values are:
- (default) a colon caracter (
:); - an empty string.
 
To change the separator globally, use setTzSeparator:
import { setTzSeparator } from 'datetime-attribute'
setTzSeparator('')
// All next timezone-related functions will follow the new setting.
tzOffset(3)       // '+0300'
tzOffset(-9, -30)  // '-0930'
// Switch back to the default.
setTzSeparator(':')The timezone offset will always be adjusted to fit in the spec range (from -23:59 to +23:59). This means tzOffset(44) will output +20:00 instead of +44:00.
However, timezone offsets of countries in the world are all between -12:00 and +14:00. If you want tzOffset(44) to output -04:00 (instead of +20:00) so that it matches real-world boundaries, give it a third parameter (default: false):
tzOffset(44) // '+20:00'
tzOffset(44, 0, true) // '-04:00'To change the behaviour globally, use setTzInRealWorldRange:
import { setTzInRealWorldRange } from 'datetime-attribute'
setTzInRealWorldRange(true)
// All next timezone-related functions will follow the new setting.
tzOffset(20)       // '-04:00'
tzOffset(-14, -30) // '+09:30'
// Switch back to the default.
setTzInRealWorldRange(false) // or setTzInRealWorldRange()Curious about timezones? Have a look at the timezone map and the daylight saving time chaos.
If you need both timezone configuration functions described in the previous section (setTzSeparator for the hours-minutes separator and setTzInRealWorldRange for timezones boundaries), you can directly use setTzConfig():
import { setTzConfig } from 'datetime-attribute'
setTzConfig({
  inRealWorldRange: false, // see `setTzInRealWorldRange`
  separator: ':', // see `setTzSeparator`
})
// Switch back to the default.
setTzConfig()As datetime() doesn’t care about timezones, you can use datetimeTz() when you need to be explicit about the timezone of a moment.
💡 datetimeTz() is basically a concatenation of datetime(date, precision) and tzOffset(hours, minutes), so be sure to read about them.
It accepts the same 5 parameters, all optional:
datetimeTz(date, precision, offsetHours, offsetMinutes, inRealWorldRange)- A date object (default: 
new Date()) - A precision keywords among:
timesecondmsdatetime(default)datetime seconddatetime ms
 - Hours offset like in 
tzOffset() - Minutes offset like in 
tzOffset() - Boundaries of the timezone offset like in 
tzOffset() 
When hours and minutes are not specified, the local timezone offset is used.
import { datetime, datetimeTz } from 'datetime-attribute'
const now = new Date() // We’re 2 April 2021 and it’s 23:51 in Brussels.
datetime(now)   // '2021-04-02'
datetimeTz(now) // '2021-04-02T23:51+02:00'
datetime(now, 'time')           // '23:51'
datetime(now, 'time utc')       // '21:51Z' (same as previous, converted to UTC)
datetimeTz(now, 'time', 0)      // '23:51Z' (datetimeTz does not convert)
datetimeTz(now, 'time')         // '23:51+02:00' (fall back on local timezone)
datetimeTz(now, 'time', 9)      // '23:51+09:00'
datetimeTz(now, 'time', -3, 30) // '23:51-03:30'
datetimeTz(now, 'time', -14, 0, true) // '23:51+10:00'datetimeTz() does not convert your moment to another timezone: it only adds the wanted timezone to the moment. Its purpose is to generate a valid datetime attribute saying “here’s a moment, it has this [hours, minutes and] timezone offset”.
Let’s take this sentence and its HTML:
When I’m in Brussels, I wake up at 8 o’clock every day.
<p>When I’m in Brussels, I wake up <time datetime="08:00+02:00">at 8 o’clock</time> every day.</p>Here’s how you can get the datetime attribute fitting this sentence:
// const awakeningAt = new Date(…) // a Date object with 08:00 as time
datetimeTz(awakeningAt, 'time', 2) // '08:00+02:00'duration() requires an object with entries for different levels of durations, from seconds to weeks. It also accepts a second parameter to control the conversion of units overflow (default: true).
import { duration } from 'datetime-attribute'
const countdownBeforeBigParty = {
  w: 3,   //     3 weeks
  d: 5,   //     5 days
  h: 10,  //    10 hours
  m: 43,  //    43 minutes
  s: 2.61 // 2.610 seconds
}
duration(countdownBeforeBigParty) // 'P3W5DT10H43M2'All object keys are optional:
duration({ h: 17 }) // 'PT17H'Values exceeding a unit are converted to upper units:
duration({ h: 31, m: 63, s: 175 }) // 'P1DT8H5M55S'If you don’t need this behaviour, pass false as second parameter (default value: true).
duration({ m: 175 }) // 'PT2H55M'
duration({ m: 175 }, false) // 'PT175M'The DateTime class extends the native Date object with methods allowing you to interact with the week number or to output a datetime string.
Its constructor remains the same as the Date one.
import { DateTime } from 'datetime-attribute'
// One of the many ways to instantiate a `Date`, and this `DateTime`.
const summer = new DateTime(2021, 5, 21) // June 21, 2021Returns the week of the year, giving the same output as weekNumber().
const summer = new DateTime(2021, 5, 21) // June 21, 2021
summer.getWeek() // 25Shifts the date to the provided week, while preserving its initial day. In other words, if the initial date is a Friday, then the shifted date remains a Friday.
const summer = new DateTime(2021, 5, 21) // June 21, 2021
summer.setWeek(26) // shifts the date to June 28, 2021
summer.getWeek() // now it’s 26Returns a datetime attribute. DateTime.to() accepts the same precision keywords as datetime().
const summer = new DateTime(2021, 5, 21) // June 21, 2021
summer.to('month') // 2021-06
summer.to('yearless') // 06-21
summer.to('datetime second') // 2021-06-21T00:00:00Under the hood, the core features of datetime-attribute uses additional functions that you can also import individually.
Calculate the difference between 2 dates in days, discarding the time of day. It subtracts the first Date object from the second one.
import { daysBetween } from 'datetime-attribute'
const january1st2021 = new Date(2021, 0, 1, 10, 10, 12)
const january11th = new Date(2021, 0, 11, 10, 10, 12)
const january19th = new Date(2021, 0, 19, 10, 10, 12)
daysBetween(january1st2021, january11th) // 10
daysBetween(january19th, january11th) // -8(110 B)
Get the week number as defined by the WHATWG, following the ISO-8601 specs:
- a week starts on Monday;
 - the first week of the year includes a Thursday;
 - week numbers go from 1 to 53.
 
It accepts a Date object.
import { weekNumber } from 'datetime-attribute'
const january1st2021 = new Date(2021, 0, 1, 10, 10, 12)
const january11th = new Date(2021, 0, 11, 10, 10, 12)
const togoIndependanceDay = new Date(1960, 3, 27)
weekNumber(togoIndependanceDay) // 17
weekNumber(january1st2021) // 53: it’s a Friday!
weekNumber(january11th) // 2(183 B)
See CHANGELOG.md or the releases.
datetime-attribute is provided as module for modern browsers usage with standard JavaScript syntax:
- it is up to you to transpile it for legacy browsers;
 - you can’t import it using 
require('datetime-attribute'); - if you don’t transpile it, 
DateTimerequires support forclassfields (Safari 14.0) startingv1.32.0. 
<time> is not alone! Other elements can benefit from datetime-attribute:
<input>of the following types:date,datetime-local,month,week,time: check theirmin,max,value,datalistattributes.<del>and<ins>accept adatetimeattribute.- Microdata types: DateTime and Time properties.
 - Open Graph dates properties: 
release_date,published_time,modified_timeandexpiration_time. - The browser WebExtensions history search API.
 
See the security policy.
See the contributing guidelines.
The datetime-attribute package is open-sourced software licensed under the DWTFYWTPL.