@thi.ng/date v2.7.47
This project is part of the @thi.ng/umbrella monorepo.
About
Datetime types, relative dates, math, iterators, composable formatters, locales.
Status
STABLE - used in production
Search or submit any issues for this package
Installation
yarn add @thi.ng/dateES module import:
<script type="module" src="https://cdn.skypack.dev/@thi.ng/date"></script>For Node.js REPL:
# with flag only for < v16
node --experimental-repl-await
> const date = await import("@thi.ng/date");Package sizes (gzipped, pre-treeshake): ESM: 5.57 KB
Dependencies
Usage examples
Several demos in this repo's /examples directory are using this package.
A selection:
| Screenshot | Description | Live demo | Source |
|---|---|---|---|
| Heatmap visualization of this mono-repo's commits | Source |
API
TODO - Please see tests and doc strings in source for now...
DateTime
The DateTime class acts as a thin wrapper around UTC epochs/timestamps,
with the constructor supporting coercions and varying granularity/precision
(from years to milliseconds). Default precision is milliseconds.
| Key | Precision |
|---|---|
y | Year |
M | Month |
d | Day |
h | Hour |
m | Minute |
s | Second |
t | Millisecond |
Note: DateTime instances also define the above keys as properties, plus
getters for week-in-year (.w) and quarter (.q).
// create w/ current date (or pass epoch, string, Date or DateTime instances)
const a = dateTime();
// DateTime { y: 2020, M: 8, d: 19, h: 12, m: 17, s: 16, t: 884 }
// provide additional precision (here year only)
const b = dateTime(a, "y");
// or
const b = a.withPrecision("y")
// DateTime { y: 2020, M: 0, d: 1, h: 0, m: 0, s: 0, t: 0 }
a.toString();
// Sat Sep 19 2020 12:17:16 GMT'
a.toISOString()
// '2020-09-19T12:17:16.884Z'
b.toISOString();
// 2020-01-01T00:00:00.000Z
a.isLeapYear()
// true
a.daysInMonth()
// 30
a.dayInYear()
// 263
a.weekInYear()
// 38
a.isAfter(b)
// true\
b.isBefore(a)
// trueMath & comparison
DateTime instances support basic math to derive future/past instances, given an
offset period. Period identifiers are any Precision ID (see above) or w
(week, aka 7 days) or q (quarter, aka 3 months):
const a = dateTime();
// DateTime { y: 2020, M: 8, d: 19, h: 12, m: 17, s: 16, t: 884 }
// create new instance 61 seconds in the future
// any `Period` ID can be used
a.add(61, "s")
// DateTime { y: 2020, M: 8, d: 19, h: 12, m: 18, s: 17, t: 884 }
// ...or 90 days ago
a.add(-90, "d")
// DateTime { y: 2020, M: 5, d: 21, h: 12, m: 17, s: 16, t: 884 }
// ...or 2 quarters (aka 2x 3 months) ahead of time
a.add(2, "q").toISOString()
// "2021-03-19T12:17:16.884Z"
// check for equivalence
a.equiv("2020-09-19T12:17:16.884Z")
// true
// are dates equal (with tolerance of ±100 ms)
a.eqDelta(a.add(99, "t"), 100)
// true
a.compare(a.add(1, "s"))
// -1000
// compute difference between dates (in milliseconds)
difference(a, "1970-01-01") === a.getTime()
// true
difference("2021-02", "2020-02")
// 31622400000
difference("2021-02", "2020-02") / DAY
// 366 (because 2020 was a leap year)Iterators
Several iterators are provided to produce timestamps of various granularities between two given dates. Originally, these were intended for visualization purposes (i.e. as axis tick label generators for @thi.ng/viz).
years()querters()months()weeks()days()hours()minutes()seconds()milliseconds()
[...months("2021-01-03", "2021-07-16")]
// [
// 1609459200000,
// 1612137600000,
// 1614556800000,
// 1617235200000,
// 1619827200000,
// 1622505600000,
// 1625097600000
// ]
[...months("2021-01-03", "2021-07-16")].map((x) => FMT_yyyyMMdd(x))
// [
// '2021-02-01',
// '2021-03-01',
// '2021-04-01',
// '2021-05-01',
// '2021-06-01',
// '2021-07-01'
// ]Relative dates
Parsing
Relative dates can be obtained via
parseRelative()
or relative().
const now = dateTime();
// DateTime { y: 2021, M: 2, d: 21, h: 14, m: 26, s: 0, t: 661 }
// see the linked documentation for all supported formats
parseRelative("2 weeks ago", now);
// DateTime { y: 2021, M: 2, d: 7, h: 14, m: 26, s: 0, t: 661 }
parseRelative("an hour", now);
// DateTime { y: 2021, M: 2, d: 21, h: 15, m: 26, s: 0, t: 661 }
parseRelative("tomorrow", now);
// DateTime { y: 2021, M: 2, d: 22, h: 14, m: 26, s: 0, t: 661 }
parseRelative("-1 month", now)
// DateTime { y: 2021, M: 1, d: 21, h: 14, m: 26, s: 0, t: 661 }Formatting
Dates can be formatted as relative descriptions using
formatRelative()
and
formatRelativeParts().
Both functions use the currently active locale and accept an optional
reference date (default: now).
setLocale(EN_LONG);
formatRelative("2020-06-01", "2021-07-01")
// "1 year ago"
formatRelative("2020-08-01", "2021-07-01")
// "11 months ago"
formatRelative("2021-07-01 13:45", "2021-07-01 12:05")
// "in 2 hours"
formatRelative("2021-07-01 12:23:24", "2021-07-01 12:05")
// "in 18 minutes"
// with default precision (seconds)
formatRelativeParts("2012-12-25 17:59:34", "2021-07-16 12:05")
// "8 years, 6 months, 21 days, 17 hours, 5 minutes, 26 seconds ago"
// with day precision
formatRelativeParts("2012-12-25 17:59:34", "2021-07-16 12:05", "d")
// "8 years, 6 months, 22 days ago"
// with month precision
formatRelativeParts("2012-12-25 17:59:34", "2021-07-16 12:05", "M")
// "8 years, 7 months ago"
formatRelativeParts("2021-07-16", "2021-01-01", "y")
// "in less than 1 year"
// with locale DE_LONG
withLocale(DE_LONG, () => formatRelativeParts("2020-01-01 12:34"))
// "vor 1 Jahr, 6 Monaten, 15 Tagen, 23 Stunden, 38 Minuten, 9 Sekunden"
// obtain the relative parts in raw form
// returns tuple of: [sign, years, months, days, hours, mins, secs, millis]
decomposeDifference("2020-01-01 12:34", Date.now())
// [-1, 1, 6, 15, 23, 38, 9, 703]Date & time formatters
Custom date/time formatters can be assembled via
defFormat(),
using the following partial format identifiers. The MMM and E formatters use
the currently active locale. To escape a formatter and use as a
string literal, prefix the term with \\.
| ID | Description |
|---|---|
yy | Short year (2 digits) |
yyyy | Full year (4 digits) |
M | Unpadded month |
MM | Zero-padded 2-digit month |
MMM | Month name in current locale (e.g. Feb) |
d | Unpadded day of month |
dd | Zero-padded 2-digit day of month |
E | Weekday name in current locale (e.g. Mon) |
w | Unpadded week-in-year (ISO8601) |
ww | Zero-padded 2-digit week-in-year (ISO8601) |
q | Unpadded quarter |
H | Unpadded hour of day (0-23) |
HH | Zero-padded 2-digit hour of day (0-23) |
h | Unpadded hour of day (1-12) |
m | Unpadded minute of hour |
mm | Zero-padded 2-digit minute of hour |
s | Unpadded second of minute |
ss | Zero-padded 2-digit second of minute |
S | Unpadded millisecond of second |
SS | Zero-padded 3-digit millisecond of second |
A | 12-hour AM/PM marker (uppercase) |
a | 12-hour am/pm marker (lowercase) |
Z | Timezone offset in signed ±HH:mm format |
ZZ | Same as Z, but special handling for UTC |
/ED | Locale-specific weekday-day separator |
/DM | Locale-specific day-month separator |
/MY | Locale-specific month-year separator |
/HM | Locale-specific hour-minute separator |
(Format IDs somewhat based on Java's SimpleDateFormat)
The following preset formatters are available:
FMT_ISO_SHORT-"2020-09-13T21:42:07Z"FMT_yyyyMMdd-"2020-09-13"FMT_Mdyyyy-"9/13/2020"FMT_MMMdyyyy-"Sep 13 2020"FMT_dMyyyy-"13/9/2020"FMT_dMMMyyyy-"13 Sep 2020"FMT_yyyyMMdd_HHmmss-20200913-214207FMT_HHmm-"21:42"FMT_hm-"9:42 PM"FMT_HHmmss-"21:42:07"FMT_hms-"9:42:07 PM"
Timecodes
For timebased media applications, the higher-order defTimecode() can be used
to create a formatter for a given FPS (frames / second, in 1..1000 range),
e.g. HH:mm:ss:ff. The returned function takes a single arg (time in
milliseconds) and returns formatted string.
The timecode considers days too, but only includes them in the result if the day
part is non-zero. The 4 separators between each field can be customized via 2nd
arg (default: all :).
a = defTimecode(30);
a(1*HOUR + 2*MINUTE + 3*SECOND + 4*1000/30)
// "01:02:03:04"
a(DAY);
// "01:00:00:00:00"
b = defTimecode(30, ["d ", "h ", "' ", '" ']);
b(Day + HOUR + 2*MINUTE + 3*SECOND + 999)
// "01d 01h 02' 03" 29"Locales
The following locale presets are available by default:
| Preset | Example |
|---|---|
DE_SHORT | 29.6.2021 @ 5:48 |
DE_LONG | Dienstag, 29. Juni 2021 @ 5:48 |
EN_SHORT | 29/06/2021 @ 5.48 am |
EN_LONG | Tuesday 29 June 2021 @ 5.48 am |
ES_LONG | martes 29 junio 2021 @ 5:48 |
FR_LONG | mardi 29 juin 2021 @ 5h 48 |
IT_LONG | martedì 29 giugno 2021 @ 5.48 |
The MMM (month) and E (weekday) formatters make use of the strings provided
by the current LOCALE (default: EN_SHORT) and can be set/changed via the
setLocale() function:
const fmt = defFormat(["E", " ", "d", " ", "MMM", " ", "yyyy"]);
setLocale(EN_SHORT); // default
// {
// months: [
// 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
// 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
// ],
// days: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
// }
fmt(dateTime());
// Sat 19 Sep 2020
setLocale(EN_LONG);
fmt(dateTime());
// Saturday 19 September 2020Use withLocale()
to only temporarily set a locale and execute a function with it, then
automatically restoring the currently active locale.
fmt(dateTime());
// 'Fri 16 Jul 2021'
withLocale(FR_LONG, () => fmt(dateTime()));
// 'vendredi 16 juillet 2021'
fmt(dateTime());
// 'Fri 16 Jul 2021'Authors
Karsten Schmidt
If this project contributes to an academic publication, please cite it as:
@misc{thing-date,
title = "@thi.ng/date",
author = "Karsten Schmidt",
note = "https://thi.ng/date",
year = 2020
}License
© 2020 - 2021 Karsten Schmidt // Apache Software License 2.0
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
10 months ago
10 months ago
11 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago