ember-moment
moment.js template helpers for Ember.js
Compatibility
- Ember.js v3.16 or above
- Ember CLI v2.13 or above
- Node.js v10 or above
- ember-auto-import 2.0 or above
Table of Contents
Using Moment.js in Ember Apps & Addons
This addon provides Ember-specific Helpers and a Service that make it convenient to use Moment.js in your templates. If you just want to call Moment.js directly from Javascript, you don't need this addon.
The recommended way to use Moment.js in an Ember app is:
- Add either
moment
or moment-timezone
to your dependencies. - Make sure you have
ember-auto-import
in your dependencies. - Make sure you don't have
ember-cli-moment-shim
in your dependencies (it would add a redundant copy). - Use imports in your Javascript like
import moment from 'moment'
or import moment from 'moment-timezone'
. - Optional but strongly recommended: Configure which locales and timezones will be included in your app by following the instructions below in "Controlling Locale and Timezone Data".
The recommended way to use Moment.js in an Ember addon is:
- Add either
moment
or moment-timezone
to your peerDependencies
. This ensures that your addon and the app must use the same copy. - Also add it to your
devDependencies
so your own test suite satisfies the peerDep. - Make sure you don't depend on
ember-cli-moment-shim
. - Make sure you do depend on
ember-auto-import
.
Moment itself is no longer actively developed and new projects should not add it. You can look at alternative libraries like Luxon, or better yet keep an eye on Temporal which is likely to add moment-like capabilities directly to Javascript quite soon.
Controlling Locale and Timezone Data
Apps should configure their locale and timezone support (which can have a large impact on bundle size) by following Moment's documentation about Webpack:
and passing the resulting webpack configuration to either ember-auto-import or Embroider. For example:
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const MomentTimezoneDataPlugin = require('moment-timezone-data-webpack-plugin');
module.exports = function (defaults) {
let app = new EmberApp(defaults, {
autoImport: {
webpack: {
plugins: [
new MomentLocalesPlugin({
localesToKeep: [],
}),
new MomentTimezoneDataPlugin({
matchCountries: 'US',
}),
],
},
},
});
Installing or Upgrading ember-moment
- First, install Moment.js using the instructions above.
- Then you can install ember-moment:
ember install ember-moment
Compatibility:
-
Ember Octane+ : >= v9 // the default branch
-
Ember Classic : < v9 // the ember-classic branch.
the ember-classic
branch is in maintenance mode, and will only receive bugfixes
Usage
Helpers
moment
{{moment <date>}}
Returns a Moment.
Example
{{moment '12-25-1995' 'MM-DD-YYYY'}} {{!-- Mon Dec 25 1995 00:00:00 GMT-0500 --}}
utc
{{utc <date>}}
{{utc}}
Returns a Moment with utc mode set.
Example
{{utc '2001-10-31T08:24:56'}} {{!-- Wed Oct 31 2001 08:24:56 GMT+0000 --}}
{{utc}} {{!-- current time utc, like Mon Feb 12 2018 20:33:08 GMT+0000 --}}
{{utc (moment '2018-01-01T00:00:00+01:00' 'YYYY-MM-DD HH:mm:ssZ')}} {{!-- Sun Dec 31 2017 23:00:00 GMT+0000 --}}
moment-format
{{moment-format <date> [outputFormat=moment.defaultFormat [<inputFormat>]]}}
Formats a <date>
to an optional outputFormat
from an optional inputFormat
. If the inputFormat
is not provided, the date String
is parsed on a best effort basis. If the outputFormat
is not given the global moment.defaultFormat
is used. Typically, outputFormat
and inputFormat
are given. See momentjs#format
.
NOTE: for all other helpers, the input format string is the second argument.
Example
{{moment-format '12-1995-25' 'MM/DD/YYYY' 'MM-YYYY-DD'}} {{!-- 12/25/1995 --}}
moment-from / moment-from-now
{{moment-from <dateA> [<dateB>] [hideAffix=false]}}
{{moment-from-now <dateA> [hideAffix=false]}}
Parameters | Values |
---|
<dateA> | Any value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...) |
<dateB> | An optional value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...), defaults to now |
hideAffix | An optional Boolean to hide the relative prefix/suffix or not. |
Returns the time between <dateA>
and <dateB>
relative to <dateB>
. See momentjs#from
.
Note that moment-from-now
is just a more verbose moment-from
without dateB
. You don't need to use it anymore.
Examples
{{!-- in January 2018 at time of writing --}}
{{moment-from '2995-12-25'}} {{!-- in 978 years --}}
{{moment-from-now '2995-12-25'}} {{!-- in 978 years --}}
{{moment-from '1995-12-25' '2995-12-25' hideAffix=true}} {{!-- 1000 years --}}
moment-to / moment-to-now
{{moment-to <dateA> [<dateB>] [hideAffix=false]}}
{{moment-to-now <dateA> [hideAffix=false]}}
Parameters | Values |
---|
<dateA> | Any value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...) |
<dateB> | An optional value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...), defaults to now |
hideAffix | An optional Boolean to hide the relative prefix/suffix or not. |
Returns the time between <dateA>
and <dateB>
relative to <dateA>
. See momentjs#to
.
Note that moment-to-now
is just a more verbose moment-to
without dateB
. You don't need to use it anymore.
Examples
{{!-- in January 2018 at time of writing --}}
{{moment-to '2995-12-25'}} {{!-- 978 years ago --}}
{{moment-to '1995-12-25' '2995-12-25'}} {{!-- in 1000 years --}}
{{moment-to-now '1995-12-25' hideAffix=true}} {{!-- 22 years --}}
moment-duration
{{moment-duration <number> [<units>]}}
Parameters | Values |
---|
<number> | Any value(s) interpretable as a duration by moment (typically a Number in milliseconds) |
<units> | An optional String to specify the units of <number> (typically 'seconds' , 'minutes' , 'hours' ...) |
Returns a Duration automatically humanized. See momentjs#duration
.
Examples
{{moment-duration 100}} {{!-- a few seconds --}}
{{moment-duration 24 'hours'}} {{!-- a day --}}
moment-calendar
{{moment-calendar <dateA> [<dateB> [<formatHash>]]}}
Returns the time between <dateA>
and <dateB>
relative to <dateB>
in a way that is different from moment-from
and customizable via <formatHash>
. See momentjs#calendar
.
Examples
{{!-- in January 2018 at time of writing --}}
{{moment-from-now '2018-01-25'}} {{!-- 2 days ago --}}
{{moment-calendar '2018-01-25'}} {{!-- Yesterday at 12:00 AM --}}
moment-diff
{{moment-diff <dateA> <dateB> [precision='milliseconds' [float=false]]}}
Returns the difference in precision
units between <dateA>
and <dateB>
with floating point accuracy if float
is true
. See momentjs#diff
.
Examples
{{moment-diff '2018-01-25' '2018-01-26'}} {{!-- 86400000 --}}
{{moment-diff '2018-01-25' '2018-01-26' precision='years' float=true}} {{!-- 0.0026881720430107525 --}}
moment-add
{{moment-add <date> <number> [precision='milliseconds']}}
Mutates the original moment by adding time. See momentjs#add
.
Examples
{{!-- Add 6 days to a date --}}
{{moment-add '10-19-2019' 6 precision='days'}}
{{!-- Add 6 days to a date --}}
const duration = { days: 6 }
{{moment-add '10-19-2019' duration}}
{{!-- Print a date 6 days from now --}}
{{moment-add 6 precision='days'}}
moment-subtract
{{moment-subtract <date> <number> [precision='milliseconds']}}
Mutates the original moment by removing time. See momentjs#subtract
.
Examples
{{!-- Remove 6 days from a date --}}
{{moment-subtract '10-19-2019' 6 precision='days'}}
{{!-- Remove 6 days from a date --}}
const duration = { days: 6 }
{{moment-subtract '10-19-2019' duration}}
{{!-- Print a date 6 days earlier --}}
{{moment-subtract 6 precision='days'}}
is-before / is-after / is-same / is-same-or-before / is-same-or-after
{{is-before <dateA> [<dateB>] [precision='milliseconds']}}
{{is-after <dateA> [<dateB>] [precision='milliseconds']}}
{{is-same <dateA> [<dateB>] [precision='milliseconds']}}
{{is-same-or-before <dateA> [<dateB>] [precision='milliseconds']}}
{{is-same-or-after <dateA> [<dateB>] [precision='milliseconds']}}
Parameters | Values |
---|
<dateA> | Any value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...) |
<dateB> | An optional value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...). If not given, <dateA> becomes now and <dateB> becomes <dateA> |
precision | An optional String unit of comparison precision, defaults to 'milliseconds' |
Returns a Boolean
that indicates if <dateA>
is respectively before/after/the same/same or before/ same or after <dateB>
to the precision
level. See momentjs#queries
.
Examples
{{is-before '2995-12-25'}} {{!-- false --}}
{{is-before '2018-01-25' '2018-01-26' precision='years'}} {{!-- false --}}
{{is-same-or-after '2018-01-25' '2018-01-26' precision='years'}} {{!-- true --}}
is-between
{{is-between <date> <dateA> [<dateB>] [precision='year' inclusivity='[)']}}
Parameters | Values |
---|
<date> | Any value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...) |
<dateA> | A boundary value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...) |
<dateB> | An optional boundary value(s) interpretable as a date/time by moment (a date String or a Moment or a Date ...). If not given <date> is assigned now, <dateA> is assigned <date> and <dateB> is assigned <dateA> . |
precision | An optional String unit of comparison precision, defaults to 'milliseconds' |
inclusivity | An optional String indicating inclusivity of the boundaries, defaults to () |
Returns a Boolean
that indicates if <date>
is between <dateA>
and <dateB>
to the precision
level and with boundary inclusions specified by inclusivity
. See momentjs#is-between
.
Examples
{{is-between '1995-12-25' '2995-12-25'}} {{!-- true --}}
{{is-between '1995-12-25' '1995-12-25' '2995-12-25' precision='years' inclusivity='()'}} {{!-- true --}}
now
{{now}}
{{moment-format (now) 'MM-DD-YYYY'}}
Returns the present Moment.
Examples
{{!-- date at time of writing }}
{{now}} {{!-- Sat Jan 27 2018 11:59:31 GMT-0500 --}}
{{!-- interval is a common named parameter (see the corresponding section) }}
{{now interval=1000}} {{!-- <current date and updating every 1-second (1000 milliseconds).> --}}
unix
{{unix <timestamp>}}
Parameters | Values |
---|
<timestamp> | An integer Number or String value representing the number of seconds since the Unix Epoch (January 1 1970 12AM UTC) |
Returns a Moment corresponding to the <timestamp>
.
Examples
{{unix '1516586508'}} {{!-- Sun Jan 21 2018 21:01:48 GMT-0500 --}}
{{!-- Warning: Passing a literal integer value does not work --}}
{{unix 1516586508}} {{!-- Invalid date --}}
Common optional named arguments
All helpers accept the following optional named arguments (even though they are not always applicable):
Parameters | Values |
---|
locale | An optional String locale, to override the default global moment.locale |
timeZone | An optional String time zone, defaults to moment.timeZone (the default time zone) |
interval | An optional interval Number of milliseconds when the helper should be recomputed |
allow-empty | An optional Boolean to ignore the Invalid date output when knowingly passing null , undefined , or '' , defaults to false |
Note that interval
does not recompute the value of the helper parameters, unless it is
part of a helper that is a value in which case it is useful for "live" updating as time elapses.
Warning: allow-empty
is currently inconsistent and should not always be trusted.
Examples
{{now interval=1000}} {{!-- <current date and updating every 1-second (1000 milliseconds)> --}}
{{is-before (now) '2018-01-26' interval=60000}} {{!-- if this was true initially, it will always be true despite interval --}}
{{moment-format '' allow-empty=true}} {{!-- <nothing> --}}
Configuration Options
Global Default Output Format
Your application may require a default format other than the default, ISO 8601. For example, you may want dates to fallback on the localized shorthand format L
by default.
module.exports = function() {
return {
moment: {
outputFormat: 'L'
}
}
};
If you need to change the default format during runtime, use the service API. Doing so will cause the moment-format helper instances to re-render with the new default format.
export default Ember.Controller.extend({
moment: Ember.inject.service(),
actions: {
changeDefaultFormat() {
this.set('moment.defaultFormat', 'MM.DD.YYYY');
}
}
})
Global Allow Empty Dates
If null
, undefined
, or an empty string are passed as a date to any of the moment helpers then you will get Invalid Date
in the output. To avoid this issue globally, you can set the option allowEmpty
which all of the helpers respect and will result in nothing being rendered instead of Invalid Date
.
module.exports = function() {
return {
moment: {
allowEmpty: true
}
}
};
Configure default runtime locale/timeZone
Globally set locale
export default Ember.Route.extend({
moment: Ember.inject.service(),
beforeModel() {
this.get('moment').setLocale('es');
}
});
Globally set time zone
export default Ember.Route.extend({
moment: Ember.inject.service(),
beforeModel() {
this.get('moment').setTimeZone('America/Los_Angeles');
}
});
Frequently Asked Questions
Invalid Date
is being rendered into the DOM, how do I avoid this?
An invalid date string is being passed into momentjs and/or the input string format was omitted.
If you are knowingly passing null, undefined, or an empty string and want to ignore the output of Invalid Date
then pass the option allow-empty=true
to the helper (all helpers accept this property)
{{moment-format ''}} {{!-- Invalid date --}}
{{moment-format '' allow-empty=true}} {{!-- <nothing> --}}
Contributing
See the Contributing guide for details.
Docs to add