Moment.js Tutorial

Moment.js Tutorial

posted in javascript on • last updated on

Moment.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.


Give yourself a moment

npm install moment


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.


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. Otherwise forgiving 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: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: Week
  • 2019-W10-7: Date with week number
  • --03-10: Date without year
  • 2019-069: Ordinal date

Parse Docs

Common formats


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()


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


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


  • toISOString(): Example: 2019-04-19T11:57:15.094Z. Aliases: toJSON() and JSON.stringify(moment()).
  • toISOString(keepOffset = false): Passing keepOffset = 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 Docs


Accepts a string parameter like “Parse strings” but with some additional options

  • [literal]
  • Mo: 1st -> 12th month
  • Qo: 1st quarter
  • DDDo: 1st -> 365th day

fromNow Docs


moment().fromNow(); // a few seconds ago
moment().fromNow(true); // a few seconds

There is also:


All these methods return a Boolean.

moment.isDate(new Date());

const m = moment();

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


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

Duration Docs

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

Manipulate Docs


const m = moment();
m.add(Number, 'days'); // or just 'd'
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

// setters

// 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

// 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!


i18n Docs

By default en is loaded.

require('moment/locale/fr'); // Averages 3-5kb per locale

// All loaded locales as String[]

// New default locale for all newly created moments

// Getter/Setter jQuery style

Or customize yourself

Special calendars


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
// --> 2019-04-19T17:16:28+02:00

// Keep timezone from input
// --> 2019-04-19T20:16:28+05:00

Setting utcOffset

moment().utcOffset(String | Number, Boolean);
  • First parameter
    • Strings -00:00, +0000 and Z
    • -16 to 16: A number of hours
    • 16- or 16+: A number of minutes
    • Any ISO8601 formatted string
  • Second parameter
    • false (default): Keep the same Universal Time, change the local time.
    • true: Keep the same local time, change the Universal Time.


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)


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


Other interesting reads
  • 8 March 2023 : Added notice about MomentJS being in maintenance mode
Tags: cheat-sheet tutorial