Moment.js Tutorial
posted in javascript on • by Wouter Van Schandevijl • last updated onMoment.js is a legacy project, now in maintenance mode. In most cases, you should choose a different library.
See some alternatives at the end of this post.
Proceed at your own peril
Moment.js is a mutable wrapper with a fluent interface for the native JavaScript date object (property _d
).
Use .toDate()
to convert back to a JavaScript date.
Dates are interpreted as local time. Unless instantiated with moment.utc()
.
const now = moment(); // current local time
const a = moment('2016-01-05');
const b = a.clone().add(1, 'week');
b.format('YYYY-MM-DD HH:mm:ss');
moment/moment : Parse, validate, manipulate, and display dates in javascript.
Install
Give yourself a moment
npm install moment
Parse
Many Moment functions accept a moment-like
argument. Where moment-like is
Moment | String | Number | Date | Array | Object
.
Another date
moment(Date)
and moment(Moment)
== moment().clone()
An array
moment([year, month, day, hour, minute, second, ms])
.
Only year is required.
Mirrors date so month is zero indexed.
moment().toArray()
returns this format.
An object
moment({year: 2010, month: 3, ...})
or just moment({y: 1, M: 0, d: 1, h: 0, m: 0, s: 0, ms: 0})
.
Can provide year
, years
or y
. Accepts numbers or strings. date
is an additional alias for day
.
Note a capital M for months and lowercase m for minutes.
moment().toObject()
returns an object with plural key names (and date
).
A number / Unix timestamp
moment(milliseconds)
.moment.unix(seconds).utc()
. Without.utc()
will create a local date.
Partials
moment('15', 'hh')
== today 15:00:00.000
Parse strings
moment(str)
accepts ISO 8601 dates.
If you’re not using an ISO 8601 date string, provide the format
and turn off forgiving mode
by passing true as the third argument.
Otherwise fallback to new Date(str)
which has varying browser support.
// Forgiving mode (default)
moment('01-01-2016', 'MM/DD/YYYY', false).format();
// --> 2016-01-01T00:00:00-06:00
// Strict mode
moment('01-01-2016', 'MM/DD/YYYY', true).format();
// --> Invalid date
// Forgiving is very forgiving
moment('2016 is a date', 'YYYY-MM-DD').isValid();
// --> true because 2016 was matched
- Also accepts an array for allowing multiple formats. First exact hit matches. Docs mention multiple formats is considerably slower.
- Third parameter true means
strict mode
. Otherwiseforgiving mode
. - Third parameter could also be the locale ex
fr
. The fourth parameter is then the mode.
ISO 8601 formats
Example | Remarks |
---|---|
2019-03-10 | Optionally add only hour, or hour:minute |
2019-03-10T00:04:48+00:00 | Can also use a space instead of T |
2019-03-10T00:04:48Z | |
2019-03-10T00:04:48.123 | Can also use a , (comma) instead of a . (dot) |
20190310T000448Z | All formats also work without separator |
More exotic ISO 8601 formats:
2019-W10
: Week2019-W10-7
: Date with week number--03-10
: Date without year2019-069
: Ordinal date
Common formats
Dates
Format | Description | Remarks |
---|---|---|
YYYY YY | Year: 2019 and 19 | For YY 68 is the pivoting year. Alter with fn moment.parseTwoDigitYear . |
M MM | Month: 1 and 01 | |
D DD | Day: 1 and 01 | |
Do | Day name: 1st | Ordinal determined by moment.locale() |
ddd dddd | Day name: Mon and Monday | Determined by moment.locale() |
MMM MMMM | Month name: Jan and Januari | Determined by moment.locale() |
Times
Format | Description | Remarks |
---|---|---|
H HH | 0..23 hours | |
h a | 1..12 hours with am/pm | |
hh A | 01..12 hours with AM/PM | |
m mm | Minutes | |
s ss | Seconds | |
S SS SSS | Fractional seconds | Parse up to 9 but only top 3 is considered |
Z ZZ | Offset from UTC as +-HH:mm , +-HHmm , or Z |
Locale aware
Format | Example |
---|---|
L | 04/09/1986 |
LL | September 4 1986 |
LLL | September 4 1986 8:30 PM |
LLLL | Thursday, September 4 1986 8:30 PM |
LT | 08:30 PM |
LTS | 08:30:00 PM |
Other
Format | Description |
---|---|
X x | Unix timestamp and Unix ms timestamp |
Q | Quarter (1..4) |
DDD DDDD | Day of year: 1..365 |
W ww | ISO week of year and Locale week of year |
E e | ISO day of week and Locale day of week |
Display
toISOString()
: Example:2019-04-19T11:57:15.094Z
. Aliases:toJSON()
andJSON.stringify(moment())
.toISOString(keepOffset = false)
: PassingkeepOffset = true
:2019-04-19T13:57:15.094+02:00
. Alias:format()
valueOf()
or+moment()
: Unix Timestamp (ms). Like Date.valueOf()..unix()
: Unix Timestamp (s).
format
Accepts a string parameter like “Parse strings” but with some additional options
[literal]
Mo
: 1st -> 12th monthQo
: 1st quarterDDDo
: 1st -> 365th day
fromNow
moment().fromNow(); // a few seconds ago
moment().fromNow(true); // a few seconds
There is also:
moment().from([, Boolean])
moment().toNow()
moment().to(moment-like[, Boolean])
moment.duration(1, 'minutes').humanize()
: “a minute”moment().calendar()
: Last/Next Monday, Yesterday, Today, Tomorrow or elseDD/MM/YYYY
.
Query
All these methods return a Boolean
.
moment.isMoment(m);
moment.isDate(new Date());
const m = moment();
m.isValid();
moment.max(moment(), moment(), ...);
moment.min([moment(), moment()]);
m.isBefore(moment-like = moment(), String = 'milliseconds');
// .isAfter()
// .isSame(), .isSameOrBefore(), .isSameOrAfter()
m.isBetween(moment-like, moment-like, String = 'milliseconds', String = '()');
Last parameter of isBetween
:
()
: Both exclusive (default)[]
: Both inclusive[)
: First inclusive, second exclusive
Difference
const m = moment();
m.diff(moment-like = moment(), String = 'milliseconds', Boolean = false);
// --> Negative result: m is earlier than first argument. Think "m - argument < 0"
m.diff(moment(), 'days');
// --> in days, truncated
m.diff(moment(), 'days', true);
// --> result as floating point
Diff as a Duration
const duration = moment.duration(m.diff(m));
duration.milliseconds(); // amount of milliseconds in the duration
duration.asMilliseconds(); // entire duration in milliseconds
Mutate
const m = moment();
m.add(Number, 'days'); // or just 'd'
m.add(moment.duration());
m.add({days: 1, M: 1});
// Also: .subtract()
m.startOf('day'); // year, second, isoWeek, quarter, ...
// Also: .endOf()
Get + Set
Overloaded getters/setters jQuery style. Both singular and plural names exist. Setters mutate the Moment object. Prefer singular names because plural names tend to get deprecated. 😃 (So far: years, months and dates are deprecated)
const m = moment();
// getters
m.second();
// setters
m.second(0);
// for:
// .milliseconds() .seconds() .minutes() .hours()
// .year() .month() .date()
// .dayOfYear() .quarter()
// .day(Number | String) // day of the week with 0=Sunday and 6=Saturday
// .weekday(Number) // day of the week, locale aware
// .isoWeekday(Number | String) // day of the week with 1=Monday and 7=Sunday
// .weekYear() and .isoWeekYear()
// .week() and .isoWeek() // week of year
// Getters only
// .weeksInYear() and .isoWeeksInYear()
// .daysInMonth()
// .isLeapYear()
// .isDST() // Is Daylight Saving Time
// Chaining: order is important
m.year(1).month(0).date(1);
// get
m.get('minute'); // Also 'minutes' and 'm'
m.get('months'); // Also 'month' and 'M'
// set
m.set('unit', 1);
m.set({years: 1, M: 2, date: 3}); // 'day' doesn't work here!
Locales
By default en
is loaded.
require('moment/locale/fr'); // Averages 3-5kb per locale
// All loaded locales as String[]
moment.locales();
// New default locale for all newly created moments
moment.locale('fr');
// Getter/Setter jQuery style
moment().locale('en');
Special calendars
Timezones
moment(); // --> 2019-04-19T17:16:28+02:00
moment.utc(); // --> 2019-04-19T15:16:28Z
moment.utc() == moment().utc()
moment.utc().local() == moment()
moment().utcOffset(); // 120 (in minutes)
// Converted to local timezone
moment('2019-04-19T20:16:28+05:00');
// --> 2019-04-19T17:16:28+02:00
// Keep timezone from input
moment.parseZone('2019-04-19T20:16:28+05:00');
// --> 2019-04-19T20:16:28+05:00
Setting utcOffset
moment().utcOffset(String | Number, Boolean);
- First parameter
- Strings
-00:00
,+0000
andZ
-16
to16
: A number of hours16-
or16+
: A number of minutes- Any ISO8601 formatted string
- Strings
- Second parameter
false
(default): Keep the same Universal Time, change the local time.true
: Keep the same local time, change the Universal Time.
Plugins
rotaready/moment-range : Fancy date ranges for Moment.js
icambron/twix.js : A date range plugin for moment.js
c-trimm/moment-recur : A momentjs plugin for matching and generating recurring dates.
jsmreese/moment-duration-format : Format function plugin for the Moment Duration object.
jmeas/moment-business : Utilities for Western workweeks (addWeekDays, isWeekDay, isWeekendDay etc)
Alternatives
If your date needs are few, a few helper methods can save you the Moment (50kb) dependency.
There is a reason Date
is not covered in JavaScript: The Good Parts though.
You Don’t Need Moment
you-dont-need/You-Dont-Need-Momentjs : List of functions which you can use to replace moment.js + ESLint Plugin
Replace Moment with a smaller project
moment/moment : This one :)
moment/luxon : A library for working with dates and times in JS (7kb)
date-fns/date-fns : ⌛ Modern JavaScript date utility library ⌛ (13kb). Functional and tree shakeable!
iamkun/dayjs : ⏰ Immutable date library alternative to Moment.js with the same modern API (2kb)
hustcc/timeago.js
:
A tiny library used to format date with *** time ago
statement. eg: ‘3 hours ago’. No dependency & localization & tiny. (2kb)
Steven Levithan
JavaScript Date Format at his “Flagrant Badassery” blog
adds a Date.prototype.format
function. (2kb)
felixge/node-dateformat : A node.js package for Steven Levithan’s excellent dateFormat() function.
Sticking with Date
const pad = value => ('0' + value).slice(-2);
const format = d => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
// --> 2019-04-14 04:14:00
Debugging
moment().invalid(obj)
: Create an ‘Invalid date’.moment().parsingFlags()
: Get details when!isValid()
.moment().invalidAt(): number
: 0=years, 1=months, …, 6=milliseconds.
moment().inspect(): string
==moment("2019-04-19T14:12:35.694")
.moment().creationData()
=={input: string, format: string, locale: Locale, isUTC: boolean, strict: boolean}
.moment.locale('x-pseudo')
- 8 March 2023 : Added notice about MomentJS being in maintenance mode