# For Moment users

Luxon borrows lots of ideas from Moment.js, but there are a lot of differences too. This document clarifies what they are.

## Immutability

Luxon's objects are immutable, whereas Moment's are mutable. For example, in Moment:

    var m1 = moment();
    var m2 = m1.add(1, 'hours');
    m1.valueOf() === m2.valueOf(); //=> true

This happens because `m1` and `m2` are really the same object; `add()` mutated the object to be an hour later. Compare that to Luxon:

    var d1 = DateTime.local();
    var d2 = d1.plus({ hours: 1 });
    d1.valueOf() === d2.valueOf(); //=> false

This happens because the `plus` method returns a new instance, leaving `d1` unmodified. It also means that Luxon doesn't require copy constructors or clone methods.

## Other API style differences

1. Luxon methods often take option objects as their last parameter
2. Luxon has different static methods for object creation (e.g. `fromISO`), as opposed to Moment's one function that dispatches based on the input
3. Luxon parsers are very strict, whereas Moment's are more lenient.
4. Luxon uses getters instead of accessor methods, so `dateTime.year` instead of `dateTime.year()`
5. Luxon centralizes its "setters", like `dateTime.set({year: 2016, month: 4})` instead of `dateTime.year(2016).month(4)` like in Moment.
6. Luxon's Durations are a separate top-level class.
7. Arguments to Luxon's methods are not automatically coerced into Moment instances. E.g. `m.diff('2017-04-01')` would be `dt.diff(DateTime.fromISO('2017-04-01'))`.

## Major functional differences

1. Months in Luxon are 1-indexed instead of 0-indexed like in Moment and the native Date type.
2. Localizations and time zones are implemented by the native Intl API (or a polyfill of it), instead of by the library itself.
3. Luxon has both a Duration type and an Interval type

## DateTime method equivalence

Here's a rough mapping of DateTime methods in Moment to ones in Luxon. I haven't comprehensively documented stuff that's in Luxon but not in Moment, just a few odds and ends that seemed obvious for inclusion; there are more. I've probably missed a few things too.

### Creation

Operation | Moment | Luxon | Notes
--- | --- | --- | ---
Now | `moment()` | `DateTime.local()` |
From ISO | `moment(String)` | `DateTime.fromISO(String)` |
From RFC 2822 | `moment(String)` | `DateTime.fromRFC2822(String)` |
From custom format | `moment(String, String)` | `DateTime.fromString(String, String)` |
From object | `moment(Object)` | `DateTime.fromObject(Object)` |
From timestamp | `moment(Number)` | `DateTime.fromMillis(Number)` |
From JS Date | `moment(Date)` | `DateTime.fromJSDate(Date)` |
From civil time | `moment(Array)` | `DateTime.local(Number...)` | Like `DateTime.local(2016, 12, 25, 10, 30)`
From UTC civil time | `moment.utc(Array)` | `DateTime.utc(Number...)` | Luxon also uses `moment.utc()` to take other arguments. In Luxon, use the appropriate method and pass in the `{ zone: 'utc'}` option
Clone | `moment(Moment)` | N/A | Immutability makes this pointless; just reuse the object
Use the string's offset | `parseZone` | See note | Methods taking strings that can specify offset or zone take a `keepZone` argument

### Getters and setters

#### Basic information getters

Property | Moment | Luxon | Notes
--- | --- | --- | ---
Validity | `isValid()` | `isValid` | See also `invalidReason`
Locale | `locale()` | `locale` |
Zone | `tz()` | `zone` | Moment requires a plugin for this, but not Luxon

#### Unit getters

Property | Moment | Luxon | Notes
--- | --- | --- | ---
Year | `year()` | `year` |
Month | `month()` | `month` |
Day of month | `date()` | `day` |
Day of week | `day()`, `weekday()`, `isoWeekday()` | `weekday` | 1-7, Monday is 1, Sunday is 7, per ISO
Day of year | `dayOfYear()` | `ordinal` |
Hour of day | `hour()` | `hour` |
Minute of hour | `minute()` | `minute` |
Second of minute | `second()` | `second` |
Millisecond of seconds | `millisecond()` | `millisecond` |
Week of ISO week year | `weekYear`, `isoWeekYear` | `weekYear` |
Quarter | `quarter` | None | Just divide the months by 4

#### Programmatic get and set

For programmatic getting and setting, Luxon and Moment are very similar here:

Operation | Moment | Luxon | Notes
--- | --- | --- | ---
get value | `get(String)` | `get(String)` |
set value | `set(String, Number)` | None |
set values | `set(Object)` | `set(Object)` | Like `dt.set({ year: 2016, month: 3 })`

### Transformation

Operation | Moment | Luxon | Notes
--- | --- | --- | ---
Addition | `add(Number, String)` | `plus(Object)` | Like `dt.plus({ months: 3, days: 2 })`
Subtraction | `subtract(Number, String)` | `minus(Object)` | Like `dt.minus({ months: 3, days: 2 })`
Start of unit | `startOf(String)` | `startOf(String)` |
End of unit | `endOf(String)` | `endOf(String)` |
Change unit values | `set(Object)` | `set(Object)` | Like `dt.set({ year: 2016, month: 3 })`
Change time zone | `tz(String)` | `zone(string)` | Luxon doesn't require a plugin
Change zone to utc | `utc()` | `toUTC()` |
Change local zone | `local()` | `toLocal()` |
Change offset | `utcOffset(Number)` | None | Set the zone instead
Change locale | `locale(String)` | `setLocale(String)`

### Query

Question | Moment | Luxon | Notes
--- | --- | --- | ---
Is this time before that time? | `m1.isBefore(m2)` | `dt1 < dt2` | The Moment versions of these take a unit. To do that in Luxon, use `startOf` on both instances.
Is this time after that time? | `m1.isAfter(m2)` | `dt1 > dt2` |
Is this time the same or before that time? | `m1.isSameOrBefore(m2)` | `dt1 <= dt2` |
Is this time the same or after that time? | `m1.isSameOrAfter(m2)` | `dt1 >= dt2` |
Do these two times have the same [unit]? | `m1.isSame(m2, unit)` | `dt1.hasSame(dt2, unit)` |
Is this time between these two times? | `m1.isBetween(m2, m3)` | `Interval.fromDateTimes(dt2, dt3).contains(dt1)` |
Is this time inside a DST | `isDST()` | `isInDST` |
Is this time's year a leap year? | `isInLeapYear()` | `isInLeapYear` |
How many days are in this time's month? | `daysInMonth()` | `daysInMonth` |
How many days are in this time's year? | None | `daysInYear` |
-------------------------------------------- | ------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------

### Output

#### Basics

See the formatting guide for more about the string-outputting methods.

Output | Moment | Luxon | Notes
--- | --- | --- | ---
simple string | `toString()` | `toString()` | Luxon just uses ISO 8601 for this. See Luxon's `toLocaleString()`
full ISO 8601 | `iso()` | `toISO()` |
ISO date only | None | `toISODate()` |
ISO time only | None | `toISOTime()` |
custom format | `format(...)` | `toFormat(...)` |
RFC 2822 |  | `toRFC2822()` |
HTTP date string |  | `toHTTP()` |
JS Date | `toDate()` | `toJSDate()` |
Epoch time | `valueOf()` | `valueOf()` |
Object | `toObject()` | `toObject()` |
Duration | `diff(Moment)` | `diff(DateTime)` | Moment's diff returns a count of milliseconds, but Luxon's returns a Duration. To replicate the Moment behavior, use `dt1.diff(d2).milliseconds`.

#### Humanization

Luxon doesn't support these, and won't until the Relative Time Format proposal lands in browsers.

Operation | Moment | Luxon
--- | --- | ---
Time from now | `fromNow()` | None
Time from other time | `from(Moment)` | None
Time to now | `toNow()` | None
Time to other time | `to(Moment) | None
"Calendar time" | `calendar()` | None

## Durations

Moment Durations and Luxon Durations are broadly similar in purpose and capabilities. The main differences are:

1. Luxon durations have more sophisticated conversion capabilities. They can convert from one set of units to another using `shiftTo`. They can also be configured to use different unit conversions. See Duration Math for more.
2. Luxon does not (yet) have an equivalent of Moment's `humanize` method
3. Like DateTimes, Luxon Durations have separate methods for creating objects from different sources.

See the Duration API docs for more.

## Intervals

Moment doesn't have direct support intervals, which must be provided by plugins like Twix or moment-range. Luxon's Intervals have similar capabilities to theirs, with the exception of the humanization features. See the Interval API docs for more.