Repository: moment/luxon
Pull request #786 (2020-09-27 13:45:23)

Merge master into 2.0

jsf-clabot: [![CLA assistant check](https://cla.js.foundation/pull/badge/not_signed)](https://cla.js.foundation/moment/luxon?pullRequest=786) <br/>Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you all sign our [Contributor License Agreement](https://cla.js.foundation/moment/luxon?pullRequest=786) before we can accept your contribution.<br/>**9** out of **11** committers have signed the CLA.<br/><br/>:white_check_mark: icambron<br/>:white_check_mark: downace<br/>:white_check_mark: ryota-ka<br/>:white_check_mark: saltire<br/>:white_check_mark: GillesDebunne<br/>:white_check_mark: jonknowles<br/>:white_check_mark: visualjerk<br/>:white_check_mark: benkelaar<br/>:white_check_mark: anthonkendel<br/>:x: dependabot[bot]<br/>:x: gdebunne

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0055e868..68f94340 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
 # Changelog
 
+## 1.25.0
+
+ * fix fromFormat with Intl formats containing non-breaking spaces
+ * Support higher precisision in ISO milliseconds
+ * Some fixes for 00:30 timezones
+ * Fix some throwOnInvalid for invalid Intervals
+ * Various doc fixes
+ * Fix Interval#isSame for empty intervals
+ * Mark package as side effect-free
+ * Add support for intervals with a large number of seconds
+
+## 1.24.1 (2020-05-04)
+
+ * Remove erroneous `console.log` call
+
 ## 1.24.0 (2020-05-03)
 
  * Update polyfills for pollyfilled build
diff --git a/README.md b/README.md
index feaaeab3..cfa938b7 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 Luxon is a library for working with dates and times in Javascript.
 
 ```js
-DateTime.local().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').toISO();
+DateTime.now().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').toISO();
 ```
 
 ## Features
diff --git a/benchmarks/datetime.js b/benchmarks/datetime.js
index 376737e1..943afc3c 100644
--- a/benchmarks/datetime.js
+++ b/benchmarks/datetime.js
@@ -6,11 +6,11 @@ import Settings from "../src/settings";
 
 const suite = new Benchmark.Suite();
 
-const dt = DateTime.local();
+const dt = DateTime.now();
 
 suite
   .add("DateTime.local", () => {
-    DateTime.local();
+    DateTime.now();
   })
   .add("DateTime.fromObject with locale", () => {
     DateTime.fromObject({ locale: "fr" });
@@ -55,7 +55,7 @@ suite
     dt.toLocaleString();
   })
   .add("DateTime#toRelativeCalendar", () => {
-    dt.toRelativeCalendar({ base: DateTime.local(), locale: "fi" });
+    dt.toRelativeCalendar({ base: DateTime.now(), locale: "fi" });
   })
   .on("cycle", event => {
     console.log(String(event.target));
diff --git a/docs/calendars.md b/docs/calendars.md
index a4e2ee3d..38010d6b 100644
--- a/docs/calendars.md
+++ b/docs/calendars.md
@@ -21,7 +21,7 @@ In practice this is pretty useful; you can show users the date in their preferre
 The output calendar is a property of the DateTime itself. For example:
 
 ```js
-var dtHebrew = DateTime.local().reconfigure({ outputCalendar: 'hebrew' })
+var dtHebrew = DateTime.now().reconfigure({ outputCalendar: 'hebrew' });
 dtHebrew.outputCalendar; //=> 'hebrew'
 dtHebrew.toLocaleString() //=> '4 Tishri 5778'
 ```
diff --git a/docs/errors.md b/docs/errors.md
index e37e7504..88474663 100644
--- a/docs/errors.md
+++ b/docs/errors.md
@@ -31,26 +31,19 @@ But there are other ways to do it:
 
 ```js
 // specify a time zone that doesn't exist
-DateTime.local().setZone("America/Blorp"); // throws
+DateTime.now().setZone("America/Blorp"); // throws
 
-// provide contradictory information (here, this date is not a Wedensday)
+// provide contradictory information (here, this date is not a Wednesday)
 DateTime.fromObject({ year: 2017, month: 5, day: 25, weekday: 3 }).; // throws
 ```
 
-The structure of error is like so:
-
-````js
-{
-  reason: "invalid zone" // this reason
-
 ##InvalidArgumentError
 
 Sometimes Luxon decides that the problem isn't so much the data being wrong, but that the programmer misunderstood the interface. For that, Luxon throws an `InvalidArgumentError`.
 
-
 ```js
-DateTime.local().set({ blorp: 7 }); //=> kerplosion
-````
+DateTime.now().set({ blorp: 7 }); //=> kerplosion
+```
 
 ## Debugging invalid DateTimes
 
@@ -61,7 +54,7 @@ Because DateTimes fail silently, they can be a pain to debug. Luxon has some fea
 Invalid DateTime objects are happy to tell you why they're invalid. `invalidReason` will give you a consistent error code you can use, whereas `invalidExplanation` will spell it out
 
 ```js
-var dt = DateTime.local().setZone("America/Blorp");
+var dt = DateTime.now().setZone("America/Blorp");
 dt.invalidReason; //=>  'unsupported zone'
 dt.invalidExplanation; //=> 'the zone "America/Blorp" is not supported'
 ```
@@ -72,7 +65,7 @@ You can make Luxon throw whenever it creates an invalid DateTime. The message wi
 
 ```js
 Settings.throwOnInvalid = true;
-DateTime.local().setZone("America/Blorp"); //=> Error: Invalid DateTime: unsupported zone: the zone "America/Blorp" is not supported
+DateTime.now().setZone("America/Blorp"); //=> Error: Invalid DateTime: unsupported zone: the zone "America/Blorp" is not supported
 ```
 
 You can of course leave this on in production too, but be sure to try/catch it appropriately.
diff --git a/docs/formatting.md b/docs/formatting.md
index 9adda4b1..43d8e942 100644
--- a/docs/formatting.md
+++ b/docs/formatting.md
@@ -89,6 +89,7 @@ Here's the full set of provided presets using the October 14, 1983 at 13:30:23 a
 | --------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------- | -------------------------------------------------------- |
 | DATE_SHORT                  | short date                                                         | 10/14/1983                                                 | 14/10/1983                                               |
 | DATE_MED                    | abbreviated date                                                   | Oct 14, 1983                                               | 14 oct. 1983                                             |
+| DATE_MED_WITH_WEEKDAY       | abbreviated date with weekday                                      | Fri, Oct 14, 1983                                          | ven. 14 oct. 1983                                        |
 | DATE_FULL                   | full date                                                          | October 14, 1983                                           | 14 octobre 1983                                          |
 | DATE_HUGE                   | full date with weekday                                             | Tuesday, October 14, 1983                                  | vendredi 14 octobre 1983                                 |
 | TIME_SIMPLE                 | time                                                               | 1:30 PM                                                    | 13:30                                                    |
@@ -132,7 +133,7 @@ The supported tokens are described in the table below.
 
 ### Intl
 
-All of the strings (e.g. month names and weekday names) are internationalized by introspecting strings generated by the Intl API. Thus they exact strings you get are implementation-specific.
+All of the strings (e.g. month names and weekday names) are internationalized by introspecting strings generated by the Intl API. Thus the exact strings you get are implementation-specific.
 
 ```js
 DateTime.fromISO("2014-08-06T13:07:04.054")
@@ -145,7 +146,7 @@ DateTime.fromISO("2014-08-06T13:07:04.054")
 You may escape strings using brackets:
 
 ```js
-DateTime.local().toFormat("HH [hours and] mm [minutes]"); //=> '20 hours and 55 minutes'
+DateTime.now().toFormat("HH [hours and] mm [minutes]"); //=> '20 hours and 55 minutes'
 ```
 
 ### Standalone vs format tokens
diff --git a/docs/intl.md b/docs/intl.md
index 7e000ae8..e3f19687 100644
--- a/docs/intl.md
+++ b/docs/intl.md
@@ -3,7 +3,7 @@
 Luxon uses the native Intl API to provide easy-to-use internationalization. A quick example:
 
 ```js
-DateTime.local()
+DateTime.now()
   .setLocale("el")
   .toLocaleString(DateTime.DATE_FULL); //=>  '24 Σεπτεμβρίου 2017'
 ```
@@ -34,13 +34,13 @@ In this case, the specified locale didn't change the how the parsing worked (the
 You can change the locale of a DateTime instance (meaning, create a clone DateTime with a different locale) using `setLocale`:
 
 ```js
-DateTime.local().setLocale("fr").locale; //=> 'fr'
+DateTime.now().setLocale("fr").locale; //=> 'fr'
 ```
 
 `setLocale` is just a convenience for `reconfigure`:
 
 ```js
-DateTime.local().reconfigure({ locale: "fr" }).locale; //=> 'fr'
+DateTime.now().reconfigure({ locale: "fr" }).locale; //=> 'fr'
 ```
 
 ## Default locale
@@ -51,7 +51,7 @@ By default, the `locale` property of a new DateTime or Duration is the system lo
 
 As a result, `DateTime#toLocaleString`, `DateTime#toLocaleParts`, and other human-readable-string methods like `Info.months` will by default generate strings in the user's locale.
 
-However, note that `DateTime.fromFormat` and `DateTime#toFormat` fall back on en-US. That's because these methods are often used to parse or format strings for consumption by APIs that don't care about the user's locale. So we need to pick a locale and stick with it, or the code will break depending on whose browser it runs in. There's an exception, though: `DateTime#toFormat` can take "macro" formats like "D" that produces localized strings as part of a larger string. These *do* default to the system locale because their entire purpose is to be provide localized strings.
+However, note that `DateTime.fromFormat` and `DateTime#toFormat` fall back on en-US. That's because these methods are often used to parse or format strings for consumption by APIs that don't care about the user's locale. So we need to pick a locale and stick with it, or the code will break depending on whose browser it runs in. There's an exception, though: `DateTime#toFormat` can take "macro" formats like "D" that produces localized strings as part of a larger string. These _do_ default to the system locale because their entire purpose is to be provide localized strings.
 
 ### Setting the default
 
@@ -59,7 +59,7 @@ You can set a default locale so that news instances will always be created with
 
 ```js
 Settings.defaultLocale = "fr";
-DateTime.local().locale; //=> 'fr'
+DateTime.now().locale; //=> 'fr'
 ```
 
 Note that this also alters the behavior of `DateTime#toFormat` and `DateTime#fromFormat`.
@@ -69,7 +69,7 @@ Note that this also alters the behavior of `DateTime#toFormat` and `DateTime#fro
 You generally don't want `DateTime#fromFormat` and `DateTime#toFormat` to use the system's locale, since your format won't be sensitive to the locale's string ordering. That's why Luxon doesn't behave that way by default. But if you really want that behavior, you can always do this:
 
 ```js
-Settings.defaultLocale = DateTime.local().resolvedLocaleOpts().locale;
+Settings.defaultLocale = DateTime.now().resolvedLocaleOpts().locale;
 ```
 
 ## Checking what you got
@@ -127,7 +127,7 @@ Info.eras("long", { locale: "fr" }); //=> [ 'avant Jésus-Christ', 'après Jésu
 DateTimes also have a `numberingSystem` setting that lets you control what system of numerals is used in formatting. In general, you shouldn't override the numbering system provided by the locale. For example, no extra work is needed to get Arabic numbers to show up in Arabic-speaking locales:
 
 ```js
-const dt = DateTime.local().setLocale("ar");
+const dt = DateTime.now().setLocale("ar");
 
 dt.resolvedLocaleOpts(); //=> { locale: 'ar',
 //     numberingSystem: 'arab',
@@ -139,7 +139,7 @@ dt.toLocaleString(); //=> '٢٤‏/٩‏/٢٠١٧'
 For this reason, Luxon defaults its own `numberingSystem` property to null, by which it means "let the Intl API decide". However, you can override it if you want. This example is admittedly ridiculous:
 
 ```js
-const dt = DateTime.local().reconfigure({ locale: "it", numberingSystem: "beng" });
+const dt = DateTime.now().reconfigure({ locale: "it", numberingSystem: "beng" });
 dt.toLocaleString(DateTime.DATE_FULL); //=> '২৪ settembre ২০১৭'
 ```
 
diff --git a/docs/math.md b/docs/math.md
index d3815a7e..1a08c9a6 100644
--- a/docs/math.md
+++ b/docs/math.md
@@ -98,10 +98,11 @@ DateTime implements `#valueOf` to return the epoch timestamp, so you can compare
 d1 < d2 // is d1 before d2?
 ```
 
-However, `===` compares object identity (not a useful concept in a library with immutable types) and `#equals` compares both the time and additional metadata, such as the locale and time zone. If you're only interested in checking the equality of the timestamps, you need to coerce them:
+However, be aware that `===` compares object identity, which is not a useful concept in a library with immutable types. Use `#equals` to compare both the time and additional metadata, such as the locale and time zone. If you're only interested in checking the equality of the timestamps, you can use:
 
 ```js
-+d1 === +d2 // are d1 and d2 the same instant in time?
+d1.toMillis() === d2.toMillis() // are d1 and d2 the same instant in time?
++d1 === +d2 // same test, using object coercion
 ```
 
 You may also use `#hasSame` to make more subtle comparisons:
@@ -218,8 +219,8 @@ This is because 12 * 30 != 365. These errors can be annoying, but they can also
 
 ```js
 var dur = Duration.fromObject({ years: 50000 });
-DateTime.local().plus(dur.shiftTo('milliseconds')).year //=> 51984
-DateTime.local().plus(dur).year                         //=> 52017
+DateTime.now().plus(dur.shiftTo('milliseconds')).year //=> 51984
+DateTime.now().plus(dur).year                         //=> 52017
 ```
 
 Those are 33 years apart! So Luxon offers an alternative conversion scheme called "longterm", based on the 400-year calendar cycle:
diff --git a/docs/moment.md b/docs/moment.md
index 4ec84f64..3c4aa663 100644
--- a/docs/moment.md
+++ b/docs/moment.md
@@ -15,7 +15,7 @@ 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:
 
 ```js
-var d1 = DateTime.local();
+var d1 = DateTime.now();
 var d2 = d1.plus({ hours: 1 });
 d1.valueOf() === d2.valueOf(); //=> false
 ```
@@ -47,7 +47,7 @@ Here's a rough mapping of DateTime methods in Moment to ones in Luxon. I haven't
 
 | Operation               | Moment                   | Luxon                                 | Notes                                                                                                                                 |
 | ----------------------- | ------------------------ | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
-| Now                     | `moment()`               | `DateTime.local()`                    |                                                                                                                                       |
+| Now                     | `moment()`               | `DateTime.now()`                      |                                                                                                                                       |
 | From ISO                | `moment(String)`         | `DateTime.fromISO(String)`            |                                                                                                                                       |
 | From RFC 2822           | `moment(String)`         | `DateTime.fromRFC2822(String)`        |                                                                                                                                       |
 | From custom format      | `moment(String, String)` | `DateTime.fromFormat(String, String)` | The format tokens differ between Moment and Luxon, such that the same format string cannot be used between the two.                   |
@@ -149,7 +149,7 @@ See the [formatting guide](formatting.html) for more about the string-outputting
 
 #### Humanization
 
-Luxon has `toRelative` and `toRelativeCalendar`. For internationalization, they use Intl.RelativeTimeFormat, which isn't currently supported by most browsers; in those cases, they fall back to English.
+Luxon has `toRelative` and `toRelativeCalendar`. For internationalization, they use Intl.RelativeTimeFormat (or fall back to English when it is not supported by the browser).
 
 | Operation            | Moment         | Luxon                                         |
 | -------------------- | -------------- | --------------------------------------------- |
@@ -164,7 +164,7 @@ Luxon has `toRelative` and `toRelativeCalendar`. For internationalization, they
 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](math.html#duration-math) for more.
-1.  Luxon does not (yet) have an equivalent of Moment's Duration `humanize` method. Luxon will add that when [Intl.UnitFormat](https://github.com/tc39/proposal-intl-unit-format) is supported by browsers.
+1.  Luxon does not (yet) have an equivalent of Moment's Duration `humanize` method. Luxon will add that when [Unified Intl.NumberFormat](https://github.com/tc39/proposal-unified-intl-numberformat) is supported by browsers.
 1.  Like DateTimes, Luxon Durations have separate methods for creating objects from different sources.
 
 See the [Duration API docs](../class/src/duration.js~Duration.html) for more.
diff --git a/docs/plugin.js b/docs/plugin.js
index c8bccd09..6393ad8b 100644
--- a/docs/plugin.js
+++ b/docs/plugin.js
@@ -10,7 +10,7 @@ exports.onHandleContent = function(ev) {
   // Add Luxon to the page so you can play with it while browsing the docs
   $("body").append("<script src='https://moment.github.io/luxon/global/luxon.js'/>");
   $("body").append(
-    "<script>console.log('You can try Luxon right here using the `luxon` global, like `luxon.DateTime.local()`.')</script>"
+    "<script>console.log('You can try Luxon right here using the `luxon` global, like `luxon.DateTime.now()`.')</script>"
   );
 
   // The little "100% documented" badge was too prominent.
diff --git a/docs/tour.md b/docs/tour.md
index d178e9bb..24a7be82 100644
--- a/docs/tour.md
+++ b/docs/tour.md
@@ -6,23 +6,27 @@ This is going to be a bit brisk, but keep in mind that the API docs are comprehe
 
 ## Your first DateTime
 
-The most important class in Luxon is [DateTime](../class/src/datetime.js~DateTime.html). A DateTime represents a specific millisecond in time, along with a time zone and a locale. Here's one that represents May 15, 2017 at 8:30 in the morning:
+The most important class in Luxon is [DateTime](../class/src/datetime.js~DateTime.html). A DateTime represents a specific millisecond in time, along with a time zone and a locale. Here's one that represents May 15, 2017 at 8:30 in the morning in the local time zone:
 
 ```js
 var dt = DateTime.local(2017, 5, 15, 8, 30);
 ```
 
+[DateTime.local](../class/src/datetime.js~DateTime.html#static-method-local) takes any number of arguments, all the way out to milliseconds. Underneath, this is similar to a Javascript Date object. But we've decorated it with lots of useful methods.
+
+## Creating a DateTime
+
+There are lots of ways to create a DateTime by parsing strings or constructing them out of parts. You've already seen one, `DateTime.local()`, but let's talk about three more.
+
+### Get the current date and time
+
 To get the current time, just do this:
 
 ```js
-var now = DateTime.local();
+var now = DateTime.now();
 ```
 
-[DateTime.local](../class/src/datetime.js~DateTime.html#static-method-local) takes any number of arguments, all the way out to milliseconds. Underneath, this is just a Javascript Date object. But we've decorated it with lots of useful methods.
-
-## Creating a DateTime
-
-There are lots of ways to create a DateTime by parsing strings or constructing them out of parts. You've already seen one, `DateTime.local()`, but let's talk about two more.
+Calling [DateTime.now](../class/src/datetime.js~DateTime.html#static-method-now) is equivalent to calling `local()` with no parameter.
 
 ### Create from an object
 
@@ -55,7 +59,7 @@ Now that we've made some DateTimes, let's see what we can ask of it.
 The first thing we want to see is the DateTime as a string. Luxon returns ISO 8601 strings:
 
 ```js
-DateTime.local().toString() //=> '2017-09-14T03:20:34.091-04:00'
+DateTime.now().toString(); //=> '2017-09-14T03:20:34.091-04:00'
 ```
 
 ### Getting at components
@@ -63,7 +67,7 @@ DateTime.local().toString() //=> '2017-09-14T03:20:34.091-04:00'
 We can get at the components of the time individually through getters. For example:
 
 ```js
-dt = DateTime.local()
+dt = DateTime.now();
 dt.year     //=> 2017
 dt.month    //=> 9
 dt.day      //=> 14
@@ -111,9 +115,9 @@ Luxon objects are immutable. That means that you can't alter them in place, just
 This is easier to show than to tell. All of these calls return new DateTime instances:
 
 ```js
-var dt = DateTime.local();
-dt.plus({hours: 3, minutes: 2});
-dt.minus({days: 7});
+var dt = DateTime.now();
+dt.plus({ hours: 3, minutes: 2 });
+dt.minus({ days: 7 });
 dt.startOf('day');
 dt.endOf('hour');
 ```
@@ -123,7 +127,7 @@ dt.endOf('hour');
 You can create new instances by overriding specific properties:
 
 ```js
-var dt = DateTime.local();
+var dt = DateTime.now();
 dt.set({hour: 3}).hour   //=> 3
 ```
 
@@ -132,12 +136,12 @@ dt.set({hour: 3}).hour   //=> 3
 Luxon provides several different Intl capabilities, but the most important one is in formatting:
 
 ```js
-var dt = DateTime.local();
+var dt = DateTime.now();
 var f = {month: 'long', day: 'numeric'};
 dt.setLocale('fr').toLocaleString(f)      //=> '14 septembre'
 dt.setLocale('en-GB').toLocaleString(f)   //=> '14 September'
 dt.setLocale('en-US').toLocaleString(f)  //=> 'September 14'
- ```
+```
 
 Luxon's Info class can also list months or weekdays for different locales:
 
@@ -151,15 +155,15 @@ Luxon supports time zones. There's a whole [big section](zones) about it. But br
 
 ```js
 DateTime.fromObject({zone: 'America/Los_Angeles'}) // now, but expressed in LA's local time
-DateTime.local().setZone('America/Los_Angeles') // same
+DateTime.now().setZone('America/Los_Angeles'); // same
 ```
 
 Luxon also supports UTC directly:
 
 ```js
 DateTime.utc(2017, 5, 15);
-DateTime.utc();
-DateTime.local().toUTC();
+DateTime.utc(); // now, in UTC time zone
+DateTime.now().toUTC();
 DateTime.utc().toSystemZone();
 ```
 
@@ -168,7 +172,7 @@ DateTime.utc().toSystemZone();
 The Duration class represents a quantity of time such as "2 hours and 7 minutes". You create them like this:
 
 ```js
-var dur = Duration.fromObject({hours: 2, minutes: 7});
+var dur = Duration.fromObject({ hours: 2, minutes: 7 });
 ```
 
 They can be add or subtracted from DateTimes like this:
@@ -199,9 +203,8 @@ You can also format, negate, and normalize them. See it all in the [Duration API
 
 Intervals are a specific period of time, such as "between now and midnight". They're really a wrapper for two DateTimes that form its endpoints. Here's what you can do with them:
 
-
 ```js
-now = DateTime.local();
+now = DateTime.now();
 later = DateTime.local(2020, 10, 12);
 i = Interval.fromDateTimes(now, later);
 
diff --git a/docs/why.md b/docs/why.md
index 3fe7d89e..93ecaa97 100644
--- a/docs/why.md
+++ b/docs/why.md
@@ -10,10 +10,10 @@ I should clarify here that I'm just one of Moment's maintainers; I'm not in char
 
 Luxon started because I had a bunch of ideas on how to improve Moment but kept finding Moment wasn't a good codebase to explore them with. Namely:
 
- * I wanted to try out some ideas that I thought would provide a better, more explicit API but didn't want to break everything in Moment.
- * I had an idea on how to provide out-of-the-box, no-data-files-required support for time zones, but Moment's design made that difficult.
- * I wanted to completely rethink how internationalization worked by using the Intl API that comes packaged in browsers.
- * I wanted to use a modern JS toolchain, which would require a major retrofit to Moment.
+- I wanted to try out some ideas that I thought would provide a better, more explicit API but didn't want to break everything in Moment.
+- I had an idea on how to provide out-of-the-box, no-data-files-required support for time zones, but Moment's design made that difficult.
+- I wanted to completely rethink how internationalization worked by using the Intl API that comes packaged in browsers.
+- I wanted to use a modern JS toolchain, which would require a major retrofit to Moment.
 
 So I decided to write something from scratch, a sort of modernized Moment. It's a combination of all the things I learned maintaining Moment and Twix, plus a bunch of fresh ideas. I worked on it in little slivers of spare time for about two years. But now it's ready to actually use, and the Moment team likes it enough that we pulled it under the organization's umbrella.
 
@@ -21,34 +21,36 @@ So I decided to write something from scratch, a sort of modernized Moment. It's
 
 Luxon is built around a few core ideas:
 
- 1. Keep the basic chainable date wrapper idea from Moment.
- 1. Make all the types immutable.
- 1. Make the API explicit; different methods do different things and have well-defined options.
- 1. Use the Intl API to provide internationalization, including token parsing. Fall back to English if the browser doesn't support those APIs.
- 1. Abuse the Intl API horribly to provide time zone support. Only possible for modern browsers.
- 1. Provide more comprehensive duration support.
- 1. Directly provide interval support.
- 1. Write inline docs for everything.
+1.  Keep the basic chainable date wrapper idea from Moment.
+1.  Make all the types immutable.
+1.  Make the API explicit; different methods do different things and have well-defined options.
+1.  Use the Intl API to provide internationalization, including token parsing. Fall back to English if the browser doesn't support those APIs.
+1.  Abuse the Intl API horribly to provide time zone support. Only possible for modern browsers.
+1.  Provide more comprehensive duration support.
+1.  Directly provide interval support.
+1.  Write inline docs for everything.
 
 These ideas have some big advantages:
 
- 1. It's much easier to understand and debug code that uses Luxon.
- 1. Using native browser capabilities for internationalization leads to a much better behavior and is dramatically easier to maintain.
- 1. Luxon has the best time zone support of any JS date library.
- 1. Luxon's durations are both flexible and easy to use.
- 1. The documentation is very good.
+1.  It's much easier to understand and debug code that uses Luxon.
+1.  Using native browser capabilities for internationalization leads to a much better behavior and is dramatically easier to maintain.
+1.  Luxon has the best time zone support of any JS date library.
+1.  Luxon's durations are both flexible and easy to use.
+1.  The documentation is very good.
 
 They also have some disadvantages:
 
- 1. Using modern browser capabilities means that the fallback behavior introduces complexity for the programmer.
- 1. Never keeping internationalized strings in the code base means that some capabilities have to wait until the browsers provide it.
- 1. Some aspects of the Intl API are browser-dependent, which means Luxon's behavior is too.
+1.  Using modern browser capabilities means that the fallback behavior introduces complexity for the programmer.
+1.  Never keeping internationalized strings in the code base means that some capabilities have to wait until the browsers provide it.
+1.  Some aspects of the Intl API are browser-dependent, which means Luxon's behavior is too.
 
 ## Place in the Moment project
 
 Luxon lives in the Moment project because, basically, we all really like it, and it represents a huge improvement.
 
-But Luxon doesn't quite fulfill Moment's mandate. First, it doesn't provide some of Moment's most commonly-used features, like relative date formatting. These features will [soon](https://github.com/tc39/proposal-intl-relative-time) be added to modern browsers and quickly folded into Luxon, but they aren't there yet. And even when they are, Luxon will only be able to provide that functionality to those newer environments. In fact, none of Luxon's Intl features work as expected on sufficiently outdated browsers, whereas Moment's all work everywhere. That represents a good tradeoff, IMO, but it's clearly a different one than Moment makes. Luxon makes a major break in API conventions. Part of Moment's charm is that you just call `moment()` on basically anything and you get date, whereas Luxon forces you to decide that you want to call `fromISO` or whatever. The upshot of all that is that Luxon feels like a different library; that's why it's not Moment 3.0.
+But Luxon doesn't quite fulfill Moment's mandate. Since it sometimes relies on browsers' implementations of the `Intl` specifications, it doesn't provide some of Moment's most commonly-used features on all browsers. Relative date formatting is for instance not supported in IE11 and Safari (as of August 2020). Luxon's Intl features do not work as expected on sufficiently outdated browsers, whereas Moment's all work everywhere. That represents a good tradeoff, IMO, but it's clearly a different one than Moment makes.
+
+Luxon makes a major break in API conventions. Part of Moment's charm is that you just call `moment()` on basically anything and you get date, whereas Luxon forces you to decide that you want to call `fromISO` or whatever. The upshot of all that is that Luxon feels like a different library; that's why it's not Moment 3.0.
 
 So what is it then? We're not really sure. We're calling it a Moment labs project. Will its ideas get backported into Moment 3? Will it gradually siphon users away from Moment and become the focus of the Moment project? Will the march of modern browsers retire the arguments above and cause us to revisit branding Luxon as Moment? We don't know.
 
@@ -56,4 +58,4 @@ There, now you know as much as I do.
 
 ## Future plans
 
-Luxon is fully usable and I plan to support it indefinitely. It's also largely complete. It will certainly add relative time formatting (and an English-only fallback) when that becomes possible. Luxon will also eventually strip out its fallbacks for missing platform features. But overall I expect the core functionality to stay basically as it is, adding mostly minor tweaks and bugfixes.
+Luxon is fully usable and I plan to support it indefinitely. It's also largely complete. Luxon will eventually strip out its fallbacks for missing platform features. But overall I expect the core functionality to stay basically as it is, adding mostly minor tweaks and bugfixes.
diff --git a/package-lock.json b/package-lock.json
index b4cfd0bf..ad3d762d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "luxon",
-  "version": "1.24.0",
+  "version": "1.24.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -8,17 +8,18 @@
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
       "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
+      "dev": true,
       "requires": {
         "@babel/highlight": "^7.0.0"
       }
     },
     "@babel/compat-data": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.6.tgz",
-      "integrity": "sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.0.tgz",
+      "integrity": "sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.11.1",
+        "browserslist": "^4.9.1",
         "invariant": "^2.2.4",
         "semver": "^5.5.0"
       },
@@ -35,19 +36,19 @@
       }
     },
     "@babel/core": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.6.tgz",
-      "integrity": "sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz",
+      "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.8.3",
-        "@babel/generator": "^7.9.6",
+        "@babel/generator": "^7.9.0",
         "@babel/helper-module-transforms": "^7.9.0",
-        "@babel/helpers": "^7.9.6",
-        "@babel/parser": "^7.9.6",
+        "@babel/helpers": "^7.9.0",
+        "@babel/parser": "^7.9.0",
         "@babel/template": "^7.8.6",
-        "@babel/traverse": "^7.9.6",
-        "@babel/types": "^7.9.6",
+        "@babel/traverse": "^7.9.0",
+        "@babel/types": "^7.9.0",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.1",
@@ -67,29 +68,6 @@
             "@babel/highlight": "^7.8.3"
           }
         },
-        "@babel/generator": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
-          "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.9.6",
-            "jsesc": "^2.5.1",
-            "lodash": "^4.17.13",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/helper-function-name": {
-          "version": "7.9.5",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
-          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-get-function-arity": "^7.8.3",
-            "@babel/template": "^7.8.3",
-            "@babel/types": "^7.9.5"
-          }
-        },
         "@babel/highlight": {
           "version": "7.9.0",
           "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
@@ -101,48 +79,6 @@
             "js-tokens": "^4.0.0"
           }
         },
-        "@babel/parser": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
-          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
-          "dev": true
-        },
-        "@babel/traverse": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
-          "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.9.6",
-            "@babel/helper-function-name": "^7.9.5",
-            "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.9.6",
-            "@babel/types": "^7.9.6",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.13"
-          }
-        },
-        "@babel/types": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.9.5",
-            "lodash": "^4.17.13",
-            "to-fast-properties": "^2.0.0"
-          },
-          "dependencies": {
-            "@babel/helper-validator-identifier": {
-              "version": "7.9.5",
-              "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
-              "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==",
-              "dev": true
-            }
-          }
-        },
         "ansi-styles": {
           "version": "3.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -172,24 +108,12 @@
             "ms": "^2.1.1"
           }
         },
-        "globals": {
-          "version": "11.12.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-          "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-          "dev": true
-        },
         "js-tokens": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
           "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
           "dev": true
         },
-        "jsesc": {
-          "version": "2.5.2",
-          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-          "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-          "dev": true
-        },
         "ms": {
           "version": "2.1.2",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -204,12 +128,6 @@
           "requires": {
             "has-flag": "^3.0.0"
           }
-        },
-        "to-fast-properties": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
-          "dev": true
         }
       }
     },
@@ -253,13 +171,13 @@
       }
     },
     "@babel/helper-compilation-targets": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz",
-      "integrity": "sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw==",
+      "version": "7.8.7",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz",
+      "integrity": "sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==",
       "dev": true,
       "requires": {
-        "@babel/compat-data": "^7.9.6",
-        "browserslist": "^4.11.1",
+        "@babel/compat-data": "^7.8.6",
+        "browserslist": "^4.9.1",
         "invariant": "^2.2.4",
         "levenary": "^1.1.1",
         "semver": "^5.5.0"
@@ -408,379 +326,70 @@
       }
     },
     "@babel/helper-replace-supers": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz",
-      "integrity": "sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA==",
+      "version": "7.8.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz",
+      "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==",
       "dev": true,
       "requires": {
         "@babel/helper-member-expression-to-functions": "^7.8.3",
         "@babel/helper-optimise-call-expression": "^7.8.3",
-        "@babel/traverse": "^7.9.6",
-        "@babel/types": "^7.9.6"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
-          "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.8.3"
-          }
-        },
-        "@babel/generator": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
-          "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.9.6",
-            "jsesc": "^2.5.1",
-            "lodash": "^4.17.13",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/helper-function-name": {
-          "version": "7.9.5",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
-          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-get-function-arity": "^7.8.3",
-            "@babel/template": "^7.8.3",
-            "@babel/types": "^7.9.5"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.9.0",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
-          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.9.0",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/parser": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
-          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
-          "dev": true
-        },
-        "@babel/traverse": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
-          "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.9.6",
-            "@babel/helper-function-name": "^7.9.5",
-            "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.9.6",
-            "@babel/types": "^7.9.6",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.13"
-          }
-        },
-        "@babel/types": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.9.5",
-            "lodash": "^4.17.13",
-            "to-fast-properties": "^2.0.0"
-          },
-          "dependencies": {
-            "@babel/helper-validator-identifier": {
-              "version": "7.9.5",
-              "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
-              "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==",
-              "dev": true
-            }
-          }
-        },
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          }
-        },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "globals": {
-          "version": "11.12.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-          "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-          "dev": true
-        },
-        "js-tokens": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-          "dev": true
-        },
-        "jsesc": {
-          "version": "2.5.2",
-          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-          "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-          "dev": true
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
-        },
-        "to-fast-properties": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
-          "dev": true
-        }
-      }
-    },
-    "@babel/helper-simple-access": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz",
-      "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==",
-      "dev": true,
-      "requires": {
-        "@babel/template": "^7.8.3",
-        "@babel/types": "^7.8.3"
-      }
-    },
-    "@babel/helper-split-export-declaration": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
-      "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "^7.8.3"
-      }
-    },
-    "@babel/helper-validator-identifier": {
-      "version": "7.9.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz",
-      "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==",
-      "dev": true
-    },
-    "@babel/helper-wrap-function": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz",
-      "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-function-name": "^7.8.3",
-        "@babel/template": "^7.8.3",
-        "@babel/traverse": "^7.8.3",
-        "@babel/types": "^7.8.3"
+        "@babel/traverse": "^7.8.6",
+        "@babel/types": "^7.8.6"
       }
-    },
-    "@babel/helpers": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.6.tgz",
-      "integrity": "sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw==",
-      "dev": true,
-      "requires": {
-        "@babel/template": "^7.8.3",
-        "@babel/traverse": "^7.9.6",
-        "@babel/types": "^7.9.6"
-      },
-      "dependencies": {
-        "@babel/code-frame": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
-          "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
-          "dev": true,
-          "requires": {
-            "@babel/highlight": "^7.8.3"
-          }
-        },
-        "@babel/generator": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
-          "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.9.6",
-            "jsesc": "^2.5.1",
-            "lodash": "^4.17.13",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/helper-function-name": {
-          "version": "7.9.5",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
-          "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-get-function-arity": "^7.8.3",
-            "@babel/template": "^7.8.3",
-            "@babel/types": "^7.9.5"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.9.0",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
-          "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.9.0",
-            "chalk": "^2.0.0",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/parser": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
-          "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
-          "dev": true
-        },
-        "@babel/traverse": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
-          "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.9.6",
-            "@babel/helper-function-name": "^7.9.5",
-            "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.9.6",
-            "@babel/types": "^7.9.6",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.13"
-          }
-        },
-        "@babel/types": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-validator-identifier": "^7.9.5",
-            "lodash": "^4.17.13",
-            "to-fast-properties": "^2.0.0"
-          },
-          "dependencies": {
-            "@babel/helper-validator-identifier": {
-              "version": "7.9.5",
-              "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
-              "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==",
-              "dev": true
-            }
-          }
-        },
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          }
-        },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "globals": {
-          "version": "11.12.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-          "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-          "dev": true
-        },
-        "js-tokens": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-          "dev": true
-        },
-        "jsesc": {
-          "version": "2.5.2",
-          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-          "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-          "dev": true
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
-        },
-        "to-fast-properties": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
-          "dev": true
-        }
+    },
+    "@babel/helper-simple-access": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz",
+      "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==",
+      "dev": true,
+      "requires": {
+        "@babel/template": "^7.8.3",
+        "@babel/types": "^7.8.3"
+      }
+    },
+    "@babel/helper-split-export-declaration": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
+      "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.8.3"
+      }
+    },
+    "@babel/helper-validator-identifier": {
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz",
+      "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==",
+      "dev": true
+    },
+    "@babel/helper-wrap-function": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz",
+      "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-function-name": "^7.8.3",
+        "@babel/template": "^7.8.3",
+        "@babel/traverse": "^7.8.3",
+        "@babel/types": "^7.8.3"
+      }
+    },
+    "@babel/helpers": {
+      "version": "7.9.2",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz",
+      "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==",
+      "dev": true,
+      "requires": {
+        "@babel/template": "^7.8.3",
+        "@babel/traverse": "^7.9.0",
+        "@babel/types": "^7.9.0"
       }
     },
     "@babel/highlight": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
       "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+      "dev": true,
       "requires": {
         "chalk": "^2.0.0",
         "esutils": "^2.0.2",
@@ -791,6 +400,7 @@
           "version": "3.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
           "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+          "dev": true,
           "requires": {
             "color-convert": "^1.9.0"
           }
@@ -799,6 +409,7 @@
           "version": "2.4.2",
           "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
           "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
           "requires": {
             "ansi-styles": "^3.2.1",
             "escape-string-regexp": "^1.0.5",
@@ -808,12 +419,14 @@
         "js-tokens": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+          "dev": true
         },
         "supports-color": {
           "version": "5.5.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
           "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "dev": true,
           "requires": {
             "has-flag": "^3.0.0"
           }
@@ -911,9 +524,9 @@
       }
     },
     "@babel/plugin-proposal-object-rest-spread": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz",
-      "integrity": "sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A==",
+      "version": "7.9.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz",
+      "integrity": "sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg==",
       "dev": true,
       "requires": {
         "@babel/helper-plugin-utils": "^7.8.3",
@@ -941,16 +554,6 @@
         "@babel/plugin-syntax-optional-chaining": "^7.8.0"
       }
     },
-    "@babel/plugin-proposal-throw-expressions": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.8.3.tgz",
-      "integrity": "sha512-tH40s9JnoR+r45ZXKWW+PC5xzPQfVJix3pR1D8Ty5l9sn5NnrbZUzw8MtnNxu/Bz7p0imyeSYj9FQVccEymOEg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "^7.8.3",
-        "@babel/plugin-syntax-throw-expressions": "^7.8.3"
-      }
-    },
     "@babel/plugin-proposal-unicode-property-regex": {
       "version": "7.8.8",
       "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz",
@@ -1060,15 +663,6 @@
         "@babel/helper-plugin-utils": "^7.8.0"
       }
     },
-    "@babel/plugin-syntax-throw-expressions": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-throw-expressions/-/plugin-syntax-throw-expressions-7.8.3.tgz",
-      "integrity": "sha512-Mv3shY1i7ZssY4OY+eLZJAmNCwqTcpv2qOKO9x6irELSygfKWVSMXk0igJsA9UhU4hOdw0qMGkjj9TAk4MqzwQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "^7.8.3"
-      }
-    },
     "@babel/plugin-syntax-top-level-await": {
       "version": "7.8.3",
       "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz",
@@ -1151,9 +745,9 @@
           "dev": true
         },
         "@babel/types": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
+          "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
           "dev": true,
           "requires": {
             "@babel/helper-validator-identifier": "^7.9.5",
@@ -1260,38 +854,38 @@
       }
     },
     "@babel/plugin-transform-modules-amd": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz",
-      "integrity": "sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz",
+      "integrity": "sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q==",
       "dev": true,
       "requires": {
         "@babel/helper-module-transforms": "^7.9.0",
         "@babel/helper-plugin-utils": "^7.8.3",
-        "babel-plugin-dynamic-import-node": "^2.3.3"
+        "babel-plugin-dynamic-import-node": "^2.3.0"
       }
     },
     "@babel/plugin-transform-modules-commonjs": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz",
-      "integrity": "sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz",
+      "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==",
       "dev": true,
       "requires": {
         "@babel/helper-module-transforms": "^7.9.0",
         "@babel/helper-plugin-utils": "^7.8.3",
         "@babel/helper-simple-access": "^7.8.3",
-        "babel-plugin-dynamic-import-node": "^2.3.3"
+        "babel-plugin-dynamic-import-node": "^2.3.0"
       }
     },
     "@babel/plugin-transform-modules-systemjs": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz",
-      "integrity": "sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg==",
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz",
+      "integrity": "sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ==",
       "dev": true,
       "requires": {
         "@babel/helper-hoist-variables": "^7.8.3",
         "@babel/helper-module-transforms": "^7.9.0",
         "@babel/helper-plugin-utils": "^7.8.3",
-        "babel-plugin-dynamic-import-node": "^2.3.3"
+        "babel-plugin-dynamic-import-node": "^2.3.0"
       }
     },
     "@babel/plugin-transform-modules-umd": {
@@ -1427,13 +1021,13 @@
       }
     },
     "@babel/preset-env": {
-      "version": "7.9.6",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.6.tgz",
-      "integrity": "sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ==",
+      "version": "7.9.5",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.5.tgz",
+      "integrity": "sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ==",
       "dev": true,
       "requires": {
-        "@babel/compat-data": "^7.9.6",
-        "@babel/helper-compilation-targets": "^7.9.6",
+        "@babel/compat-data": "^7.9.0",
+        "@babel/helper-compilation-targets": "^7.8.7",
         "@babel/helper-module-imports": "^7.8.3",
         "@babel/helper-plugin-utils": "^7.8.3",
         "@babel/plugin-proposal-async-generator-functions": "^7.8.3",
@@ -1441,7 +1035,7 @@
         "@babel/plugin-proposal-json-strings": "^7.8.3",
         "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
         "@babel/plugin-proposal-numeric-separator": "^7.8.3",
-        "@babel/plugin-proposal-object-rest-spread": "^7.9.6",
+        "@babel/plugin-proposal-object-rest-spread": "^7.9.5",
         "@babel/plugin-proposal-optional-catch-binding": "^7.8.3",
         "@babel/plugin-proposal-optional-chaining": "^7.9.0",
         "@babel/plugin-proposal-unicode-property-regex": "^7.8.3",
@@ -1468,9 +1062,9 @@
         "@babel/plugin-transform-function-name": "^7.8.3",
         "@babel/plugin-transform-literals": "^7.8.3",
         "@babel/plugin-transform-member-expression-literals": "^7.8.3",
-        "@babel/plugin-transform-modules-amd": "^7.9.6",
-        "@babel/plugin-transform-modules-commonjs": "^7.9.6",
-        "@babel/plugin-transform-modules-systemjs": "^7.9.6",
+        "@babel/plugin-transform-modules-amd": "^7.9.0",
+        "@babel/plugin-transform-modules-commonjs": "^7.9.0",
+        "@babel/plugin-transform-modules-systemjs": "^7.9.0",
         "@babel/plugin-transform-modules-umd": "^7.9.0",
         "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3",
         "@babel/plugin-transform-new-target": "^7.8.3",
@@ -1486,8 +1080,8 @@
         "@babel/plugin-transform-typeof-symbol": "^7.8.4",
         "@babel/plugin-transform-unicode-regex": "^7.8.3",
         "@babel/preset-modules": "^0.1.3",
-        "@babel/types": "^7.9.6",
-        "browserslist": "^4.11.1",
+        "@babel/types": "^7.9.5",
+        "browserslist": "^4.9.1",
         "core-js-compat": "^3.6.2",
         "invariant": "^2.2.2",
         "levenary": "^1.1.1",
@@ -1501,9 +1095,9 @@
           "dev": true
         },
         "@babel/types": {
-          "version": "7.9.6",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
-          "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
+          "version": "7.9.5",
+          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
+          "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
           "dev": true,
           "requires": {
             "@babel/helper-validator-identifier": "^7.9.5",
@@ -1779,9 +1373,9 @@
       }
     },
     "@comandeer/babel-plugin-banner": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/@comandeer/babel-plugin-banner/-/babel-plugin-banner-5.0.0.tgz",
-      "integrity": "sha512-sR9Go0U6puXoXyW9UgIiIQhRcJ8jVOvGl4BptUiXAtheMs72WcakZ1udh6J0ZOivr3o8jAM+MTCHLP8FZMbVpQ==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/@comandeer/babel-plugin-banner/-/babel-plugin-banner-4.1.0.tgz",
+      "integrity": "sha512-9hKVIN2+maygxkngnXDsZXRZqCYDY4pxIRljJqqJ5A+eJZzW3k/NZj5lixEmStjWFjlPlOHGYBytBehpf0l+hA==",
       "dev": true
     },
     "@istanbuljs/load-nyc-config": {
@@ -2361,14 +1955,22 @@
       }
     },
     "@rollup/pluginutils": {
-      "version": "3.0.10",
-      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.10.tgz",
-      "integrity": "sha512-d44M7t+PjmMrASHbhgpSbVgtL6EFyX7J4mYxwQ/c5eoaE6N2VgCgEcWVzNnwycIloti+/MpwFr8qfw+nRw00sw==",
+      "version": "3.0.9",
+      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.9.tgz",
+      "integrity": "sha512-TLZavlfPAZYI7v33wQh4mTP6zojne14yok3DNSLcjoG/Hirxfkonn6icP5rrNWRn8nZsirJBFFpijVOJzkUHDg==",
       "dev": true,
       "requires": {
         "@types/estree": "0.0.39",
         "estree-walker": "^1.0.1",
-        "picomatch": "^2.2.2"
+        "micromatch": "^4.0.2"
+      },
+      "dependencies": {
+        "@types/estree": {
+          "version": "0.0.39",
+          "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+          "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+          "dev": true
+        }
       }
     },
     "@samverschueren/stream-to-observable": {
@@ -2390,9 +1992,9 @@
       }
     },
     "@tootallnate/once": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.0.0.tgz",
-      "integrity": "sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+      "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
       "dev": true
     },
     "@types/babel__core": {
@@ -2443,9 +2045,9 @@
       "dev": true
     },
     "@types/estree": {
-      "version": "0.0.39",
-      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
-      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+      "version": "0.0.44",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.44.tgz",
+      "integrity": "sha512-iaIVzr+w2ZJ5HkidlZ3EJM8VTZb2MJLCjw3V+505yVts0gRC4UMvjw0d1HPtGqI/HQC/KdsYtayfzl+AXY2R8g==",
       "dev": true
     },
     "@types/istanbul-lib-coverage": {
@@ -2516,9 +2118,9 @@
       }
     },
     "@types/yargs-parser": {
-      "version": "13.1.0",
-      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz",
-      "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==",
+      "version": "15.0.0",
+      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
+      "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==",
       "dev": true
     },
     "abab": {
@@ -2546,9 +2148,9 @@
       }
     },
     "acorn-jsx": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
-      "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz",
+      "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==",
       "dev": true
     },
     "acorn-walk": {
@@ -2558,9 +2160,9 @@
       "dev": true
     },
     "agent-base": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
-      "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz",
+      "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==",
       "dev": true,
       "requires": {
         "debug": "4"
@@ -2729,238 +2331,49 @@
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
-      "dev": true
-    },
-    "atob": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
-      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
-      "dev": true
-    },
-    "aws-sign2": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
-      "dev": true
-    },
-    "babel-code-frame": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
-      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
-      "dev": true,
-      "requires": {
-        "chalk": "^1.1.3",
-        "esutils": "^2.0.2",
-        "js-tokens": "^3.0.2"
-      }
-    },
-    "babel-core": {
-      "version": "7.0.0-bridge.0",
-      "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
-      "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==",
-      "dev": true
-    },
-    "babel-eslint": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
-      "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "^7.0.0",
-        "@babel/parser": "^7.7.0",
-        "@babel/traverse": "^7.7.0",
-        "@babel/types": "^7.7.0",
-        "eslint-visitor-keys": "^1.0.0",
-        "resolve": "^1.12.0"
-      },
-      "dependencies": {
-        "@babel/generator": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
-          "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.8.3",
-            "jsesc": "^2.5.1",
-            "lodash": "^4.17.13",
-            "source-map": "^0.5.0"
-          }
-        },
-        "@babel/helper-function-name": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
-          "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-get-function-arity": "^7.8.3",
-            "@babel/template": "^7.8.3",
-            "@babel/types": "^7.8.3"
-          }
-        },
-        "@babel/helper-get-function-arity": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz",
-          "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.8.3"
-          }
-        },
-        "@babel/helper-split-export-declaration": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
-          "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
-          "dev": true,
-          "requires": {
-            "@babel/types": "^7.8.3"
-          }
-        },
-        "@babel/highlight": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
-          "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
-          "dev": true,
-          "requires": {
-            "chalk": "^2.0.0",
-            "esutils": "^2.0.2",
-            "js-tokens": "^4.0.0"
-          }
-        },
-        "@babel/parser": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
-          "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==",
-          "dev": true
-        },
-        "@babel/template": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
-          "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.8.3",
-            "@babel/parser": "^7.8.3",
-            "@babel/types": "^7.8.3"
-          },
-          "dependencies": {
-            "@babel/code-frame": {
-              "version": "7.8.3",
-              "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
-              "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
-              "dev": true,
-              "requires": {
-                "@babel/highlight": "^7.8.3"
-              }
-            }
-          }
-        },
-        "@babel/traverse": {
-          "version": "7.8.4",
-          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
-          "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
-          "dev": true,
-          "requires": {
-            "@babel/code-frame": "^7.8.3",
-            "@babel/generator": "^7.8.4",
-            "@babel/helper-function-name": "^7.8.3",
-            "@babel/helper-split-export-declaration": "^7.8.3",
-            "@babel/parser": "^7.8.4",
-            "@babel/types": "^7.8.3",
-            "debug": "^4.1.0",
-            "globals": "^11.1.0",
-            "lodash": "^4.17.13"
-          },
-          "dependencies": {
-            "@babel/code-frame": {
-              "version": "7.8.3",
-              "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
-              "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
-              "dev": true,
-              "requires": {
-                "@babel/highlight": "^7.8.3"
-              }
-            }
-          }
-        },
-        "@babel/types": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
-          "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
-          "dev": true,
-          "requires": {
-            "esutils": "^2.0.2",
-            "lodash": "^4.17.13",
-            "to-fast-properties": "^2.0.0"
-          }
-        },
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "^1.9.0"
-          }
-        },
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "^3.2.1",
-            "escape-string-regexp": "^1.0.5",
-            "supports-color": "^5.3.0"
-          }
-        },
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "globals": {
-          "version": "11.12.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-          "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-          "dev": true
-        },
-        "js-tokens": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-          "dev": true
-        },
-        "jsesc": {
-          "version": "2.5.2",
-          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-          "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-          "dev": true
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^3.0.0"
-          }
-        },
-        "to-fast-properties": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
-          "dev": true
-        }
+      "dev": true
+    },
+    "atob": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+      "dev": true
+    },
+    "aws-sign2": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+      "dev": true
+    },
+    "babel-code-frame": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+      "dev": true,
+      "requires": {
+        "chalk": "^1.1.3",
+        "esutils": "^2.0.2",
+        "js-tokens": "^3.0.2"
+      }
+    },
+    "babel-core": {
+      "version": "7.0.0-bridge.0",
+      "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
+      "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==",
+      "dev": true
+    },
+    "babel-eslint": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
+      "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "@babel/parser": "^7.7.0",
+        "@babel/traverse": "^7.7.0",
+        "@babel/types": "^7.7.0",
+        "eslint-visitor-keys": "^1.0.0",
+        "resolve": "^1.12.0"
       }
     },
     "babel-generator": {
@@ -3118,9 +2531,9 @@
       }
     },
     "babel-plugin-dynamic-import-node": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
-      "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz",
+      "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==",
       "dev": true,
       "requires": {
         "object.assign": "^4.1.0"
@@ -3330,17 +2743,6 @@
         "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
         "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
         "@babel/plugin-syntax-optional-chaining": "^7.8.3"
-      },
-      "dependencies": {
-        "@babel/plugin-syntax-optional-chaining": {
-          "version": "7.8.3",
-          "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
-          "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
-          "dev": true,
-          "requires": {
-            "@babel/helper-plugin-utils": "^7.8.0"
-          }
-        }
       }
     },
     "babel-preset-jest": {
@@ -3567,13 +2969,13 @@
       }
     },
     "browserslist": {
-      "version": "4.12.0",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz",
-      "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==",
+      "version": "4.11.1",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz",
+      "integrity": "sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==",
       "dev": true,
       "requires": {
-        "caniuse-lite": "^1.0.30001043",
-        "electron-to-chromium": "^1.3.413",
+        "caniuse-lite": "^1.0.30001038",
+        "electron-to-chromium": "^1.3.390",
         "node-releases": "^1.1.53",
         "pkg-up": "^2.0.0"
       }
@@ -3629,9 +3031,9 @@
       "dev": true
     },
     "caniuse-lite": {
-      "version": "1.0.30001048",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz",
-      "integrity": "sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg==",
+      "version": "1.0.30001041",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001041.tgz",
+      "integrity": "sha512-fqDtRCApddNrQuBxBS7kEiSGdBsgO4wiVw4G/IClfqzfhW45MbTumfN4cuUJGTM0YGFNn97DCXPJ683PS6zwvA==",
       "dev": true
     },
     "capture-exit": {
@@ -3838,9 +3240,9 @@
       "dev": true
     },
     "codecov": {
-      "version": "3.6.5",
-      "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.6.5.tgz",
-      "integrity": "sha512-v48WuDMUug6JXwmmfsMzhCHRnhUf8O3duqXvltaYJKrO1OekZWpB/eH6iIoaxMl8Qli0+u3OxptdsBOYiD7VAQ==",
+      "version": "3.7.1",
+      "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.7.1.tgz",
+      "integrity": "sha512-JHWxyPTkMLLJn9SmKJnwAnvY09kg2Os2+Ux+GG7LwZ9g8gzDDISpIN5wAsH1UBaafA/yGcd3KofMaorE8qd6Lw==",
       "dev": true,
       "requires": {
         "argv": "0.0.2",
@@ -3870,6 +3272,7 @@
       "version": "1.9.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
       "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+      "dev": true,
       "requires": {
         "color-name": "^1.1.1"
       }
@@ -3883,7 +3286,8 @@
     "color-name": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
     },
     "commander": {
       "version": "4.1.1",
@@ -4204,12 +3608,13 @@
       "dev": true
     },
     "doctrine": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+      "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
       "dev": true,
       "requires": {
-        "esutils": "^2.0.2"
+        "esutils": "^2.0.2",
+        "isarray": "^1.0.0"
       }
     },
     "dom-serializer": {
@@ -4284,9 +3689,9 @@
       }
     },
     "electron-to-chromium": {
-      "version": "1.3.427",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.427.tgz",
-      "integrity": "sha512-/rG5G7Opcw68/Yrb4qYkz07h3bESVRJjUl4X/FrKLXzoUJleKm6D7K7rTTz8V5LUWnd+BbTOyxJX2XprRqHD8A==",
+      "version": "1.3.405",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.405.tgz",
+      "integrity": "sha512-D+xkP+hAQY/790DzImC8bI8QJLaArNG4b74bYvkhkK/fli51JmNyUYxwKLSl/8VPGkkXEqKCupSDD05/E5P72w==",
       "dev": true
     },
     "elegant-spinner": {
@@ -4320,6 +3725,7 @@
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
       "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
       "requires": {
         "is-arrayish": "^0.2.1"
       }
@@ -4363,7 +3769,8 @@
     "escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
     },
     "escodegen": {
       "version": "1.9.0",
@@ -4710,14 +4117,13 @@
             "ms": "^2.1.1"
           }
         },
-        "eslint-scope": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
-          "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
+        "doctrine": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+          "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
           "dev": true,
           "requires": {
-            "esrecurse": "^4.1.0",
-            "estraverse": "^4.1.1"
+            "esutils": "^2.0.2"
           }
         },
         "eslint-visitor-keys": {
@@ -4738,6 +4144,16 @@
           "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
           "dev": true
         },
+        "import-fresh": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz",
+          "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==",
+          "dev": true,
+          "requires": {
+            "parent-module": "^1.0.0",
+            "resolve-from": "^4.0.0"
+          }
+        },
         "json-schema-traverse": {
           "version": "0.4.1",
           "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -4825,15 +4241,6 @@
         "pkg-dir": "^2.0.0"
       },
       "dependencies": {
-        "doctrine": {
-          "version": "1.5.0",
-          "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
-          "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
-          "requires": {
-            "esutils": "^2.0.2",
-            "isarray": "^1.0.0"
-          }
-        },
         "find-up": {
           "version": "2.1.0",
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
@@ -4889,9 +4296,9 @@
       }
     },
     "eslint-plugin-babel": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-5.3.0.tgz",
-      "integrity": "sha512-HPuNzSPE75O+SnxHIafbW5QB45r2w78fxqwK3HmjqIUoPfPzVrq6rD+CINU3yzoDSzEhUkX07VUphbF73Lth/w==",
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz",
+      "integrity": "sha512-VsQEr6NH3dj664+EyxJwO4FCYm/00JhYb3Sk3ft8o+fpKuIfQ9TaW6uVUfvwMXHcf/lsnRIoyFPsLMyiWCSL/g==",
       "dev": true,
       "requires": {
         "eslint-rule-composer": "^0.3.0"
@@ -4933,18 +4340,6 @@
         "object.values": "^1.1.0",
         "read-pkg-up": "^2.0.0",
         "resolve": "^1.12.0"
-      },
-      "dependencies": {
-        "doctrine": {
-          "version": "1.5.0",
-          "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
-          "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
-          "dev": true,
-          "requires": {
-            "esutils": "^2.0.2",
-            "isarray": "^1.0.0"
-          }
-        }
       }
     },
     "eslint-plugin-node": {
@@ -4967,6 +4362,21 @@
           "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==",
           "dev": true
         },
+        "path-parse": {
+          "version": "1.0.6",
+          "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+          "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+          "dev": true
+        },
+        "resolve": {
+          "version": "1.12.0",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
+          "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.6"
+          }
+        },
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -5039,37 +4449,39 @@
       "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==",
       "dev": true
     },
+    "eslint-scope": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
+      "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
+      "dev": true,
+      "requires": {
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
+      }
+    },
     "eslint-utils": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
-      "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
+      "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
       "dev": true,
       "requires": {
-        "eslint-visitor-keys": "^1.1.0"
-      },
-      "dependencies": {
-        "eslint-visitor-keys": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
-          "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
-          "dev": true
-        }
+        "eslint-visitor-keys": "^1.0.0"
       }
     },
     "eslint-visitor-keys": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
-      "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
       "dev": true
     },
     "espree": {
-      "version": "6.1.2",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz",
-      "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==",
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.1.tgz",
+      "integrity": "sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==",
       "dev": true,
       "requires": {
-        "acorn": "^7.1.0",
-        "acorn-jsx": "^5.1.0",
+        "acorn": "^7.0.0",
+        "acorn-jsx": "^5.0.2",
         "eslint-visitor-keys": "^1.1.0"
       },
       "dependencies": {
@@ -5126,7 +4538,8 @@
     "esutils": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
-      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+      "dev": true
     },
     "exec-sh": {
       "version": "0.3.4",
@@ -5656,7 +5069,8 @@
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true
     },
     "has-symbols": {
       "version": "1.0.1",
@@ -5925,17 +5339,6 @@
             "p-limit": "^2.2.0"
           }
         },
-        "parse-json": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
-          "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
-          "requires": {
-            "@babel/code-frame": "^7.0.0",
-            "error-ex": "^1.3.1",
-            "json-parse-better-errors": "^1.0.1",
-            "lines-and-columns": "^1.1.6"
-          }
-        },
         "path-exists": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -6137,6 +5540,12 @@
       "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
       "dev": true
     },
+    "indent-string": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+      "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
+      "dev": true
+    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -6275,7 +5684,8 @@
     "is-arrayish": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
     },
     "is-buffer": {
       "version": "1.1.6",
@@ -6434,6 +5844,14 @@
       "dev": true,
       "requires": {
         "@types/estree": "0.0.39"
+      },
+      "dependencies": {
+        "@types/estree": {
+          "version": "0.0.39",
+          "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+          "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+          "dev": true
+        }
       }
     },
     "is-regex": {
@@ -6494,7 +5912,8 @@
     "isarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true
     },
     "isexe": {
       "version": "2.0.0",
@@ -8163,7 +7582,8 @@
     "json-parse-better-errors": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
-      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
     },
     "json-schema": {
       "version": "0.2.3",
@@ -8278,7 +7698,8 @@
     "lines-and-columns": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
-      "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA="
+      "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
+      "dev": true
     },
     "lint-staged": {
       "version": "10.1.3",
@@ -8398,7 +7819,8 @@
         "mimic-fn": {
           "version": "2.1.0",
           "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-          "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
+          "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+          "dev": true
         },
         "ms": {
           "version": "2.1.2",
@@ -8406,12 +7828,6 @@
           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
         },
-        "normalize-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-          "dev": true
-        },
         "npm-run-path": {
           "version": "4.0.1",
           "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -8421,6 +7837,15 @@
             "path-key": "^3.0.0"
           }
         },
+        "onetime": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+          "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+          "dev": true,
+          "requires": {
+            "mimic-fn": "^2.1.0"
+          }
+        },
         "p-finally": {
           "version": "2.0.1",
           "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
@@ -8458,9 +7883,9 @@
           }
         },
         "which": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-2.0.1.tgz",
-          "integrity": "sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w==",
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
           "dev": true,
           "requires": {
             "isexe": "^2.0.0"
@@ -8483,14 +7908,6 @@
         "listr-verbose-renderer": "^0.5.0",
         "p-map": "^2.0.0",
         "rxjs": "^6.3.3"
-      },
-      "dependencies": {
-        "p-map": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
-          "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
-          "dev": true
-        }
       }
     },
     "listr-silent-renderer": {
@@ -8525,12 +7942,6 @@
             "object-assign": "^4.1.0"
           }
         },
-        "indent-string": {
-          "version": "3.2.0",
-          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
-          "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=",
-          "dev": true
-        },
         "log-symbols": {
           "version": "1.0.2",
           "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
@@ -8574,49 +7985,6 @@
             "supports-color": "^5.3.0"
           }
         },
-        "cli-cursor": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
-          "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
-          "dev": true,
-          "requires": {
-            "restore-cursor": "^2.0.0"
-          }
-        },
-        "figures": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
-          "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
-          "dev": true,
-          "requires": {
-            "escape-string-regexp": "^1.0.5"
-          }
-        },
-        "mimic-fn": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-          "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
-          "dev": true
-        },
-        "onetime": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
-          "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
-          "dev": true,
-          "requires": {
-            "mimic-fn": "^1.0.0"
-          }
-        },
-        "restore-cursor": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
-          "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
-          "dev": true,
-          "requires": {
-            "onetime": "^2.0.0",
-            "signal-exit": "^3.0.2"
-          }
-        },
         "supports-color": {
           "version": "5.5.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -8659,9 +8027,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.14",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
-      "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==",
+      "version": "4.17.19",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+      "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
       "dev": true
     },
     "lodash.assignin": {
@@ -8805,40 +8173,6 @@
           "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
           "dev": true
         },
-        "cli-cursor": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
-          "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
-          "dev": true,
-          "requires": {
-            "restore-cursor": "^2.0.0"
-          }
-        },
-        "mimic-fn": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-          "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
-          "dev": true
-        },
-        "onetime": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
-          "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
-          "dev": true,
-          "requires": {
-            "mimic-fn": "^1.0.0"
-          }
-        },
-        "restore-cursor": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
-          "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
-          "dev": true,
-          "requires": {
-            "onetime": "^2.0.0",
-            "signal-exit": "^3.0.2"
-          }
-        },
         "strip-ansi": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@@ -8952,9 +8286,9 @@
       }
     },
     "mimic-fn": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
       "dev": true
     },
     "minimatch": {
@@ -9163,9 +8497,9 @@
       "dev": true
     },
     "nwmatcher": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.3.tgz",
-      "integrity": "sha512-IKdSTiDWCarf2JTS5e9e2+5tPZGdkRJ79XjYV0pzK8Q9BpsFyBq1RGKxzs7Q8UBushGw7m6TzVKz6fcY99iSWw==",
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz",
+      "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==",
       "dev": true,
       "optional": true
     },
@@ -9310,12 +8644,12 @@
       }
     },
     "onetime": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
-      "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
       "dev": true,
       "requires": {
-        "mimic-fn": "^2.1.0"
+        "mimic-fn": "^1.0.0"
       }
     },
     "opencollective-postinstall": {
@@ -9374,6 +8708,12 @@
         "p-limit": "^2.0.0"
       }
     },
+    "p-map": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+      "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+      "dev": true
+    },
     "p-try": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
@@ -9549,9 +8889,9 @@
       }
     },
     "platform": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz",
-      "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==",
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz",
+      "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==",
       "dev": true
     },
     "please-upgrade-node": {
@@ -10066,14 +9406,6 @@
       "dev": true,
       "requires": {
         "lodash": "^4.17.15"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
       }
     },
     "request-promise-native": {
@@ -10145,23 +9477,6 @@
       "requires": {
         "onetime": "^2.0.0",
         "signal-exit": "^3.0.2"
-      },
-      "dependencies": {
-        "mimic-fn": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-          "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
-          "dev": true
-        },
-        "onetime": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
-          "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
-          "dev": true,
-          "requires": {
-            "mimic-fn": "^1.0.0"
-          }
-        }
       }
     },
     "ret": {
@@ -10180,12 +9495,22 @@
       }
     },
     "rollup": {
-      "version": "2.7.6",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.7.6.tgz",
-      "integrity": "sha512-AdHosxHBKyBsdtbT1/AqbWNQ87O4SSxS4N9iMwEpoCDAT6e4Du3uJSy83mp3ckgmCxly5VeXGx0WHsm21Djytg==",
+      "version": "1.32.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.32.1.tgz",
+      "integrity": "sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A==",
       "dev": true,
       "requires": {
-        "fsevents": "~2.1.2"
+        "@types/estree": "*",
+        "@types/node": "*",
+        "acorn": "^7.1.0"
+      },
+      "dependencies": {
+        "acorn": {
+          "version": "7.1.1",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
+          "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
+          "dev": true
+        }
       }
     },
     "rollup-plugin-babel": {
@@ -10199,37 +9524,15 @@
       }
     },
     "rollup-plugin-babel-minify": {
-      "version": "10.0.0",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-babel-minify/-/rollup-plugin-babel-minify-10.0.0.tgz",
-      "integrity": "sha512-tYZOhGtffvGp8VzTrB5u/kPYyIjEEshTPEauOLkshPNx/MvCJVd6PCc2HX4CO0TDH0cBnnGKQ+yQpTERJikK4Q==",
-      "dev": true,
-      "requires": {
-        "@babel/core": "^7.8.7",
-        "@babel/plugin-syntax-dynamic-import": "^7.8.3",
-        "@comandeer/babel-plugin-banner": "^5.0.0",
-        "babel-preset-minify": "^0.5.1",
-        "sourcemap-codec": "^1.4.8"
-      }
-    },
-    "rollup-plugin-commonjs": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz",
-      "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==",
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/rollup-plugin-babel-minify/-/rollup-plugin-babel-minify-6.2.0.tgz",
+      "integrity": "sha512-Ahil4nyB97OSoMTqm8qDyuL8e3NU1juDDdTC3Tuy00DvCLJmuX7OVrfEhGVJtguh/D1aO2t/2pe59/dzT/k4mw==",
       "dev": true,
       "requires": {
-        "estree-walker": "^0.6.1",
-        "is-reference": "^1.1.2",
-        "magic-string": "^0.25.2",
-        "resolve": "^1.11.0",
-        "rollup-pluginutils": "^2.8.1"
-      },
-      "dependencies": {
-        "estree-walker": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
-          "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
-          "dev": true
-        }
+        "@babel/core": "^7.0.0",
+        "@comandeer/babel-plugin-banner": "^4.0.0",
+        "babel-preset-minify": "^0.5.0",
+        "sourcemap-codec": "^1.4.3"
       }
     },
     "rollup-pluginutils": {
@@ -10265,9 +9568,9 @@
       }
     },
     "rxjs": {
-      "version": "6.5.3",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
-      "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
+      "version": "6.4.0",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+      "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
       "dev": true,
       "requires": {
         "tslib": "^1.9.0"
@@ -11259,9 +10562,9 @@
       "dev": true
     },
     "tslib": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-      "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+      "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
       "dev": true
     },
     "tunnel-agent": {
@@ -11311,9 +10614,9 @@
       }
     },
     "uglify-js": {
-      "version": "3.9.2",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.2.tgz",
-      "integrity": "sha512-zGVwKslUAD/EeqOrD1nQaBmXIHl1Vw371we8cvS8I6mYK9rmgX5tv8AAeJdfsQ3Kk5mGax2SVV/AizxdNGhl7Q==",
+      "version": "3.9.0",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.0.tgz",
+      "integrity": "sha512-j5wNQBWaql8gr06dOUrfaohHlscboQZ9B8sNsoK5o4sBjm7Ht9dxSbrMXyktQpA16Acaij8AcoozteaPYZON0g==",
       "dev": true,
       "requires": {
         "commander": "~2.20.3"
diff --git a/package.json b/package.json
index 11816435..1e24cc7e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "luxon",
-  "version": "1.24.0",
+  "version": "1.25.0",
   "description": "Immutable date wrapper",
   "author": "Isaac Cambron",
   "keywords": [
@@ -94,5 +94,6 @@
     "build/global/luxon.min.js.map",
     "src"
   ],
-  "license": "MIT"
+  "license": "MIT",
+  "sideEffects": false
 }
diff --git a/site/demo/demo.js b/site/demo/demo.js
index 439b4b88..7da34928 100644
--- a/site/demo/demo.js
+++ b/site/demo/demo.js
@@ -34,12 +34,12 @@ function demo(luxon) {
     };
 
   example("Info.features()");
-  example("DateTime.local()");
+  example("DateTime.now()");
   example("DateTime.local(2017, 5, 15, 17, 36)");
   example("DateTime.utc(2017, 5, 15, 17, 36)");
-  example("DateTime.local().toUTC()");
+  example("DateTime.now().toUTC()");
   example("DateTime.utc(2017, 5, 15, 17, 36).toSystemZone()");
-  example("DateTime.local().toObject()");
+  example("DateTime.now().toObject()");
   example("DateTime.fromObject({year: 2017, month: 5, day: 15, hour: 17, minute: 36})");
   example(
     "DateTime.fromObject({year: 2017, month: 5, day: 15, hour: 17, minute: 36, zone: 'America/New_York' })"
@@ -47,33 +47,33 @@ function demo(luxon) {
   example(
     "DateTime.fromObject({year: 2017, month: 5, day: 15, hour: 17, minute: 36, zone: 'Asia/Singapore' })"
   );
-  example("DateTime.local().plus({minutes: 15, seconds: 8})");
-  example("DateTime.local().plus({days: 6})");
-  example("DateTime.local().minus({days: 6})");
-  example("DateTime.local().diff(DateTime.local(1982, 5, 25)).milliseconds");
-  example("DateTime.local().diff(DateTime.local(1982, 5, 25), 'days').days");
-  example("DateTime.local().diff(DateTime.local(1982, 5, 25), ['days', 'hours'])");
-  example("DateTime.local().toLocaleString()");
-  example("DateTime.local().setLocale('zh').toLocaleString()");
-  example("DateTime.local().toLocaleString(DateTime.DATE_MED)");
-  example("DateTime.local().setLocale('zh').toLocaleString(DateTime.DATE_MED)");
-  example("DateTime.local().setLocale('fr').toLocaleString(DateTime.DATE_FULL)");
+  example("DateTime.now().plus({minutes: 15, seconds: 8})");
+  example("DateTime.now().plus({days: 6})");
+  example("DateTime.now().minus({days: 6})");
+  example("DateTime.now().diff(DateTime.local(1982, 5, 25)).milliseconds");
+  example("DateTime.now().diff(DateTime.local(1982, 5, 25), 'days').days");
+  example("DateTime.now().diff(DateTime.local(1982, 5, 25), ['days', 'hours'])");
+  example("DateTime.now().toLocaleString()");
+  example("DateTime.now().setLocale('zh').toLocaleString()");
+  example("DateTime.now().toLocaleString(DateTime.DATE_MED)");
+  example("DateTime.now().setLocale('zh').toLocaleString(DateTime.DATE_MED)");
+  example("DateTime.now().setLocale('fr').toLocaleString(DateTime.DATE_FULL)");
   example("DateTime.fromISO('2017-05-15')");
   example("DateTime.fromISO('2017-05-15T17:36')");
   example("DateTime.fromISO('2017-W33-4')");
   example("DateTime.fromISO('2017-W33-4T04:45:32.343')");
   example("DateTime.fromFormat('12-16-2017', 'MM-dd-yyyy')");
-  example("DateTime.local().toFormat('MM-dd-yyyy')");
-  example("DateTime.local().toFormat('MMMM dd, yyyy')");
-  example("DateTime.local().setLocale('fr').toFormat('MMMM dd, yyyy')");
+  example("DateTime.now().toFormat('MM-dd-yyyy')");
+  example("DateTime.now().toFormat('MMMM dd, yyyy')");
+  example("DateTime.now().setLocale('fr').toFormat('MMMM dd, yyyy')");
   example("DateTime.fromFormat('May 25, 1982', 'MMMM dd, yyyy')");
   example("DateTime.fromFormat('mai 25, 1982', 'MMMM dd, yyyy', { locale: 'fr' })");
-  example("DateTime.local().plus({ days: 1 }).toRelativeCalendar()");
-  example("DateTime.local().plus({ days: -1 }).toRelativeCalendar()");
-  example("DateTime.local().plus({ months: 1 }).toRelativeCalendar()");
-  example("DateTime.local().setLocale('fr').plus({ days: 1 }).toRelativeCalendar()");
-  example("DateTime.local().setLocale('fr').plus({ days: -1 }).toRelativeCalendar()");
-  example("DateTime.local().setLocale('fr').plus({ months: 1 }).toRelativeCalendar()");
+  example("DateTime.now().plus({ days: 1 }).toRelativeCalendar()");
+  example("DateTime.now().plus({ days: -1 }).toRelativeCalendar()");
+  example("DateTime.now().plus({ months: 1 }).toRelativeCalendar()");
+  example("DateTime.now().setLocale('fr').plus({ days: 1 }).toRelativeCalendar()");
+  example("DateTime.now().setLocale('fr').plus({ days: -1 }).toRelativeCalendar()");
+  example("DateTime.now().setLocale('fr').plus({ months: 1 }).toRelativeCalendar()");
 
   var all = "<h1>Some Luxon examples</h1>";
   all +=
diff --git a/site/index.html b/site/index.html
index 9f8e8a47..93042b8d 100644
--- a/site/index.html
+++ b/site/index.html
@@ -19,7 +19,7 @@
     <script src="global/luxon.js"></script>
     <script>
       console.log(
-        "You can try Luxon right here using the `luxon` global, like `luxon.DateTime.local()`."
+        "You can try Luxon right here using the `luxon` global, like `luxon.DateTime.now()`."
       );
     </script>
     <style>
@@ -44,10 +44,10 @@
       </p>
 
       <pre>
-                <code>
-DateTime.local().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').toISO();
-                </code>
-            </pre>
+        <code>
+          DateTime.now().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').toISO();
+        </code>
+      </pre>
 
       <div class="section">
         <h2>Features</h2>
@@ -95,7 +95,7 @@ DateTime.local().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').to
                 <p>
                   Exports a global variable called "luxon". Use it like this
                 </p>
-                <pre><code>&lt;script src=&quot;luxon.js&quot;&gt;&lt;/script&gt;<br/>&lt;script&gt;luxon.DateTime.local();&lt;/script&gt;</code></pre>
+                <pre><code>&lt;script src=&quot;luxon.js&quot;&gt;&lt;/script&gt;<br/>&lt;script&gt;luxon.DateTime.now();&lt;/script&gt;</code></pre>
                 <p>
                   See the
                   <a href="docs/manual/install.html">install instructions</a>
@@ -113,7 +113,7 @@ DateTime.local().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').to
               </td>
               <td>
                 <p>Luxon as a Node.js module</p>
-                <pre><code>var { DateTime } = require('luxon');<br/>DateTime.local();</code></pre>
+                <pre><code>var { DateTime } = require('luxon');<br/>DateTime.now();</code></pre>
               </td>
               <td></td>
             </tr>
@@ -129,10 +129,9 @@ DateTime.local().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').to
               </td>
               <td>
                 <p>
-                  Luxon as an AMD module. Use with Require.js, System.js, and so
-                  on.
+                  Luxon as an AMD module. Use with Require.js, System.js, and so on.
                 </p>
-                <pre><code>requirejs(['luxon'], function(luxon) {<br/>  luxon.DateTime.local();<br/>});</code></pre>
+                <pre><code>requirejs(['luxon'], function(luxon) {<br/>  luxon.DateTime.now();<br/>});</code></pre>
               </td>
               <td><a href="demo/requirejs.html">Demo</a></td>
             </tr>
@@ -146,7 +145,7 @@ DateTime.local().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').to
               <td></td>
               <td>
                 <p>Luxon as an ES6 module.</p>
-                <pre><code>import { DateTime } from 'luxon';<br/>DateTime.local();</code></pre>
+                <pre><code>import { DateTime } from 'luxon';<br/>DateTime.now();</code></pre>
               </td>
               <td></td>
             </tr>
diff --git a/src/datetime.js b/src/datetime.js
index feb4a4bd..02144759 100644
--- a/src/datetime.js
+++ b/src/datetime.js
@@ -119,22 +119,23 @@ function objToTS(obj, offset, zone) {
 
 // create a new DT instance by adding a duration, adjusting for DSTs
 function adjustTime(inst, dur) {
-  const keys = Object.keys(dur.values);
-  if (keys.indexOf("milliseconds") === -1) {
-    keys.push("milliseconds");
-  }
-
-  dur = dur.shiftTo(...keys);
-
   const oPre = inst.o,
-    year = inst.c.year + dur.years,
-    month = inst.c.month + dur.months + dur.quarters * 3,
+    year = inst.c.year + Math.trunc(dur.years),
+    month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3,
     c = Object.assign({}, inst.c, {
       year,
       month,
-      day: Math.min(inst.c.day, daysInMonth(year, month)) + dur.days + dur.weeks * 7
+      day:
+        Math.min(inst.c.day, daysInMonth(year, month)) +
+        Math.trunc(dur.days) +
+        Math.trunc(dur.weeks) * 7
     }),
     millisToAdd = Duration.fromObject({
+      years: dur.years - Math.trunc(dur.years),
+      quarters: dur.quarters - Math.trunc(dur.quarters),
+      months: dur.months - Math.trunc(dur.months),
+      weeks: dur.weeks - Math.trunc(dur.weeks),
+      days: dur.days - Math.trunc(dur.days),
       hours: dur.hours,
       minutes: dur.minutes,
       seconds: dur.seconds,
@@ -444,11 +445,22 @@ export default class DateTime {
 
   // CONSTRUCT
 
+  /**
+   * Create a DateTime for the current instant, in the system's time zone.
+   *
+   * Use Settings to override these default values if needed.
+   * @example DateTime.now().toISO() //~> now in the ISO format
+   * @return {DateTime}
+   */
+  static now() {
+    return new DateTime({});
+  }
+
   /**
    * Create a local DateTime
    * @param {number} [year] - The calendar year. If omitted (as in, call `local()` with no arguments), the current time will be used
    * @param {number} [month=1] - The month, 1-indexed
-   * @param {number} [day=1] - The day of the month
+   * @param {number} [day=1] - The day of the month, 1-indexed
    * @param {number} [hour=0] - The hour of the day, in 24-hour time
    * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59
    * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59
@@ -1056,7 +1068,7 @@ export default class DateTime {
 
   /**
    * Get the UTC offset of this DateTime in minutes
-   * @example DateTime.local().offset //=> -240
+   * @example DateTime.now().offset //=> -240
    * @example DateTime.utc().offset //=> 0
    * @type {number}
    */
@@ -1286,12 +1298,12 @@ export default class DateTime {
    *
    * Adding hours, minutes, seconds, or milliseconds increases the timestamp by the right number of milliseconds. Adding days, months, or years shifts the calendar, accounting for DSTs and leap years along the way. Thus, `dt.plus({ hours: 24 })` may result in a different time than `dt.plus({ days: 1 })` if there's a DST shift in between.
    * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
-   * @example DateTime.local().plus(123) //~> in 123 milliseconds
-   * @example DateTime.local().plus({ minutes: 15 }) //~> in 15 minutes
-   * @example DateTime.local().plus({ days: 1 }) //~> this time tomorrow
-   * @example DateTime.local().plus({ days: -1 }) //~> this time yesterday
-   * @example DateTime.local().plus({ hours: 3, minutes: 13 }) //~> in 3 hr, 13 min
-   * @example DateTime.local().plus(Duration.fromObject({ hours: 3, minutes: 13 })) //~> in 3 hr, 13 min
+   * @example DateTime.now().plus(123) //~> in 123 milliseconds
+   * @example DateTime.now().plus({ minutes: 15 }) //~> in 15 minutes
+   * @example DateTime.now().plus({ days: 1 }) //~> this time tomorrow
+   * @example DateTime.now().plus({ days: -1 }) //~> this time yesterday
+   * @example DateTime.now().plus({ hours: 3, minutes: 13 }) //~> in 3 hr, 13 min
+   * @example DateTime.now().plus(Duration.fromObject({ hours: 3, minutes: 13 })) //~> in 3 hr, 13 min
    * @return {DateTime}
    */
   plus(duration) {
@@ -1362,7 +1374,7 @@ export default class DateTime {
 
   /**
    * "Set" this DateTime to the end (meaning the last millisecond) of a unit of time
-   * @param {string} unit - The unit to go to the end of. Can be 'year', 'month', 'day', 'hour', 'minute', 'second', or 'millisecond'.
+   * @param {string} unit - The unit to go to the end of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'.
    * @example DateTime.local(2014, 3, 3).endOf('month').toISO(); //=> '2014-03-31T23:59:59.999-05:00'
    * @example DateTime.local(2014, 3, 3).endOf('year').toISO(); //=> '2014-12-31T23:59:59.999-05:00'
    * @example DateTime.local(2014, 3, 3, 5, 30).endOf('day').toISO(); //=> '2014-03-03T23:59:59.999-05:00'
@@ -1384,10 +1396,10 @@ export default class DateTime {
    * @see https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens
    * @param {string} fmt - the format string
    * @param {Object} opts - opts to override the configuration options
-   * @example DateTime.local().toFormat('yyyy LLL dd') //=> '2017 Apr 22'
-   * @example DateTime.local().setLocale('fr').toFormat('yyyy LLL dd') //=> '2017 avr. 22'
-   * @example DateTime.local().toFormat('yyyy LLL dd', { locale: "fr" }) //=> '2017 avr. 22'
-   * @example DateTime.local().toFormat("HH 'hours and' mm 'minutes'") //=> '20 hours and 55 minutes'
+   * @example DateTime.now().toFormat('yyyy LLL dd') //=> '2017 Apr 22'
+   * @example DateTime.now().setLocale('fr').toFormat('yyyy LLL dd') //=> '2017 avr. 22'
+   * @example DateTime.now().toFormat('yyyy LLL dd', { locale: "fr" }) //=> '2017 avr. 22'
+   * @example DateTime.now().toFormat("HH 'hours and' mm 'minutes'") //=> '20 hours and 55 minutes'
    * @return {string}
    */
   toFormat(fmt, opts = {}) {
@@ -1401,15 +1413,15 @@ export default class DateTime {
    * Defaults to the system's locale if no locale has been specified
    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
    * @param opts {Object} - Intl.DateTimeFormat constructor options and configuration options
-   * @example DateTime.local().toLocaleString(); //=> 4/20/2017
-   * @example DateTime.local().setLocale('en-gb').toLocaleString(); //=> '20/04/2017'
-   * @example DateTime.local().toLocaleString({ locale: 'en-gb' }); //=> '20/04/2017'
-   * @example DateTime.local().toLocaleString(DateTime.DATE_FULL); //=> 'April 20, 2017'
-   * @example DateTime.local().toLocaleString(DateTime.TIME_SIMPLE); //=> '11:32 AM'
-   * @example DateTime.local().toLocaleString(DateTime.DATETIME_SHORT); //=> '4/20/2017, 11:32 AM'
-   * @example DateTime.local().toLocaleString({ weekday: 'long', month: 'long', day: '2-digit' }); //=> 'Thursday, April 20'
-   * @example DateTime.local().toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> 'Thu, Apr 20, 11:27 AM'
-   * @example DateTime.local().toLocaleString({ hour: '2-digit', minute: '2-digit', hour12: false }); //=> '11:32'
+   * @example DateTime.now().toLocaleString(); //=> 4/20/2017
+   * @example DateTime.now().setLocale('en-gb').toLocaleString(); //=> '20/04/2017'
+   * @example DateTime.now().toLocaleString({ locale: 'en-gb' }); //=> '20/04/2017'
+   * @example DateTime.now().toLocaleString(DateTime.DATE_FULL); //=> 'April 20, 2017'
+   * @example DateTime.now().toLocaleString(DateTime.TIME_SIMPLE); //=> '11:32 AM'
+   * @example DateTime.now().toLocaleString(DateTime.DATETIME_SHORT); //=> '4/20/2017, 11:32 AM'
+   * @example DateTime.now().toLocaleString({ weekday: 'long', month: 'long', day: '2-digit' }); //=> 'Thursday, April 20'
+   * @example DateTime.now().toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> 'Thu, Apr 20, 11:27 AM'
+   * @example DateTime.now().toLocaleString({ hour: '2-digit', minute: '2-digit', hour12: false }); //=> '11:32'
    * @return {string}
    */
   toLocaleString(opts = Formats.DATE_SHORT) {
@@ -1421,7 +1433,7 @@ export default class DateTime {
    * Defaults to the system's locale if no locale has been specified
    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/formatToParts
    * @param opts {Object} - Intl.DateTimeFormat constructor options, same as `toLocaleString`.
-   * @example DateTime.local().toLocaleParts(); //=> [
+   * @example DateTime.now().toLocaleParts(); //=> [
    *                                   //=>   { type: 'day', value: '25' },
    *                                   //=>   { type: 'literal', value: '/' },
    *                                   //=>   { type: 'month', value: '05' },
@@ -1441,13 +1453,13 @@ export default class DateTime {
    * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
    * @param {string} [opts.format='extended'] - choose between the basic and extended format
    * @example DateTime.utc(1982, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z'
-   * @example DateTime.local().toISO() //=> '2017-04-22T20:47:05.335-04:00'
-   * @example DateTime.local().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335'
-   * @example DateTime.local().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400'
+   * @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00'
+   * @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335'
+   * @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400'
    * @return {string}
    */
   toISO(opts = {}) {
-    return `${this.toISODate()}T${this.toISOTime(opts)}`;
+    return `${this.toISODate(opts)}T${this.toISOTime(opts)}`;
   }
 
   /**
@@ -1539,9 +1551,9 @@ export default class DateTime {
    * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset.
    * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
    * @example DateTime.utc().toSQL() //=> '05:15:16.345'
-   * @example DateTime.local().toSQL() //=> '05:15:16.345 -04:00'
-   * @example DateTime.local().toSQL({ includeOffset: false }) //=> '05:15:16.345'
-   * @example DateTime.local().toSQL({ includeZone: false }) //=> '05:15:16.345 America/New_York'
+   * @example DateTime.now().toSQL() //=> '05:15:16.345 -04:00'
+   * @example DateTime.now().toSQL({ includeOffset: false }) //=> '05:15:16.345'
+   * @example DateTime.now().toSQL({ includeZone: false }) //=> '05:15:16.345 America/New_York'
    * @return {string}
    */
   toSQLTime({ includeOffset = true, includeZone = false } = {}) {
@@ -1617,7 +1629,7 @@ export default class DateTime {
 
   /**
    * Returns a Javascript object with this DateTime's year, month, day, and so on.
-   * @example DateTime.local().toObject() //=> { year: 2017, month: 4, day: 22, hour: 20, minute: 49, second: 42, millisecond: 268 }
+   * @example DateTime.now().toObject() //=> { year: 2017, month: 4, day: 22, hour: 20, minute: 49, second: 42, millisecond: 268 }
    * @return {Object}
    */
   toObject() {
@@ -1673,7 +1685,7 @@ export default class DateTime {
    * @return {Duration}
    */
   diffNow(unit = "milliseconds", opts = {}) {
-    return this.diff(DateTime.local(), unit, opts);
+    return this.diff(DateTime.now(), unit, opts);
   }
 
   /**
@@ -1689,7 +1701,7 @@ export default class DateTime {
    * Return whether this DateTime is in the same unit of time as another DateTime
    * @param {DateTime} otherDateTime - the other DateTime
    * @param {string} unit - the unit of time to check sameness on
-   * @example DateTime.local().hasSame(otherDT, 'day'); //~> true if both the same calendar day
+   * @example DateTime.now().hasSame(otherDT, 'day'); //~> true if both the same calendar day
    * @return {boolean}
    */
   hasSame(otherDateTime, unit) {
@@ -1720,19 +1732,19 @@ export default class DateTime {
    * Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your
    * platform supports Intl.RelativeTimeFormat. Rounds down by default.
    * @param {Object} options - options that affect the output
-   * @param {DateTime} [options.base=DateTime.local()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
+   * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
    * @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow"
    * @param {string} options.unit - use a specific unit; if omitted, the method will pick the unit. Use one of "years", "quarters", "months", "weeks", "days", "hours", "minutes", or "seconds"
    * @param {boolean} [options.round=true] - whether to round the numbers in the output.
    * @param {boolean} [options.padding=0] - padding in milliseconds. This allows you to round up the result if it fits inside the threshold. Don't use in combination with {round: false} because the decimal output will include the padding.
    * @param {string} options.locale - override the locale of this DateTime
    * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
-   * @example DateTime.local().plus({ days: 1 }).toRelative() //=> "in 1 day"
-   * @example DateTime.local().setLocale("es").toRelative({ days: 1 }) //=> "dentro de 1 día"
-   * @example DateTime.local().plus({ days: 1 }).toRelative({ locale: "fr" }) //=> "dans 23 heures"
-   * @example DateTime.local().minus({ days: 2 }).toRelative() //=> "2 days ago"
-   * @example DateTime.local().minus({ days: 2 }).toRelative({ unit: "hours" }) //=> "48 hours ago"
-   * @example DateTime.local().minus({ hours: 36 }).toRelative({ round: false }) //=> "1.5 days ago"
+   * @example DateTime.now().plus({ days: 1 }).toRelative() //=> "in 1 day"
+   * @example DateTime.now().setLocale("es").toRelative({ days: 1 }) //=> "dentro de 1 día"
+   * @example DateTime.now().plus({ days: 1 }).toRelative({ locale: "fr" }) //=> "dans 23 heures"
+   * @example DateTime.now().minus({ days: 2 }).toRelative() //=> "2 days ago"
+   * @example DateTime.now().minus({ days: 2 }).toRelative({ unit: "hours" }) //=> "48 hours ago"
+   * @example DateTime.now().minus({ hours: 36 }).toRelative({ round: false }) //=> "1.5 days ago"
    */
   toRelative(options = {}) {
     const base = options.base || DateTime.fromObject({}, { zone: this.zone }),
@@ -1751,14 +1763,14 @@ export default class DateTime {
    * Returns a string representation of this date relative to today, such as "yesterday" or "next month".
    * Only internationalizes on platforms that supports Intl.RelativeTimeFormat.
    * @param {Object} options - options that affect the output
-   * @param {DateTime} [options.base=DateTime.local()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
+   * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
    * @param {string} options.locale - override the locale of this DateTime
    * @param {string} options.unit - use a specific unit; if omitted, the method will pick the unit. Use one of "years", "quarters", "months", "weeks", or "days"
    * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
-   * @example DateTime.local().plus({ days: 1 }).toRelativeCalendar() //=> "tomorrow"
-   * @example DateTime.local().setLocale("es").plus({ days: 1 }).toRelative() //=> ""mañana"
-   * @example DateTime.local().plus({ days: 1 }).toRelativeCalendar({ locale: "fr" }) //=> "demain"
-   * @example DateTime.local().minus({ days: 2 }).toRelativeCalendar() //=> "2 days ago"
+   * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar() //=> "tomorrow"
+   * @example DateTime.now().setLocale("es").plus({ days: 1 }).toRelative() //=> ""mañana"
+   * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar({ locale: "fr" }) //=> "demain"
+   * @example DateTime.now().minus({ days: 2 }).toRelativeCalendar() //=> "2 days ago"
    */
   toRelativeCalendar(options = {}) {
     return diffRelative(
@@ -1833,6 +1845,14 @@ export default class DateTime {
     return Formats.DATE_MED;
   }
 
+  /**
+   * {@link DateTime#toLocaleString} format like 'Fri, Oct 14, 1983'
+   * @type {Object}
+   */
+  static get DATE_MED_WITH_WEEKDAY() {
+    return Formats.DATE_MED_WITH_WEEKDAY;
+  }
+
   /**
    * {@link DateTime#toLocaleString} format like 'October 14, 1983'
    * @type {Object}
diff --git a/src/duration.js b/src/duration.js
index cc27a69f..6beae2ad 100644
--- a/src/duration.js
+++ b/src/duration.js
@@ -33,6 +33,7 @@ const lowOrderMatrix = {
   casualMatrix = Object.assign(
     {
       years: {
+        quarters: 4,
         months: 12,
         weeks: 52,
         days: 365,
@@ -47,6 +48,7 @@ const lowOrderMatrix = {
         days: 91,
         hours: 91 * 24,
         minutes: 91 * 24 * 60,
+        seconds: 91 * 24 * 60 * 60,
         milliseconds: 91 * 24 * 60 * 60 * 1000
       },
       months: {
@@ -65,6 +67,7 @@ const lowOrderMatrix = {
   accurateMatrix = Object.assign(
     {
       years: {
+        quarters: 4,
         months: 12,
         weeks: daysInYearAccurate / 7,
         days: daysInYearAccurate,
@@ -542,8 +545,6 @@ export default class Duration {
       vals = this.toObject();
     let lastUnit;
 
-    normalizeValues(this.matrix, vals);
-
     for (const k of orderedUnits) {
       if (units.indexOf(k) >= 0) {
         lastUnit = k;
diff --git a/src/impl/english.js b/src/impl/english.js
index 100d5796..633f5943 100644
--- a/src/impl/english.js
+++ b/src/impl/english.js
@@ -187,6 +187,8 @@ export function formatString(knownFormat) {
       return "M/d/yyyy";
     case stringify(Formats.DATE_MED):
       return "LLL d, yyyy";
+    case stringify(Formats.DATE_MED_WITH_WEEKDAY):
+      return "EEE, LLL d, yyyy";
     case stringify(Formats.DATE_FULL):
       return "LLLL d, yyyy";
     case stringify(Formats.DATE_HUGE):
diff --git a/src/impl/formats.js b/src/impl/formats.js
index 3dfde469..e1a7db3f 100644
--- a/src/impl/formats.js
+++ b/src/impl/formats.js
@@ -18,6 +18,13 @@ export const DATE_MED = {
   day: n
 };
 
+export const DATE_MED_WITH_WEEKDAY = {
+  year: n,
+  month: s,
+  day: n,
+  weekday: s
+};
+
 export const DATE_FULL = {
   year: n,
   month: l,
diff --git a/src/impl/regexParser.js b/src/impl/regexParser.js
index 1ceca9f9..74ba737c 100644
--- a/src/impl/regexParser.js
+++ b/src/impl/regexParser.js
@@ -66,7 +66,7 @@ function simpleParse(...keys) {
 
 // ISO and SQL parsing
 const offsetRegex = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/,
-  isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,9}))?)?)?/,
+  isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/,
   isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${offsetRegex.source}?`),
   isoTimeExtensionRegex = RegExp(`(?:T${isoTimeRegex.source})?`),
   isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/,
@@ -120,7 +120,7 @@ function extractIANAZone(match, cursor) {
 
 // ISO duration parsing
 
-const isoDuration = /^-?P(?:(?:(-?\d{1,9})Y)?(?:(-?\d{1,9})M)?(?:(-?\d{1,9})W)?(?:(-?\d{1,9})D)?(?:T(?:(-?\d{1,9})H)?(?:(-?\d{1,9})M)?(?:(-?\d{1,9})(?:[.,](-?\d{1,9}))?S)?)?)$/;
+const isoDuration = /^-?P(?:(?:(-?\d{1,9})Y)?(?:(-?\d{1,9})M)?(?:(-?\d{1,9})W)?(?:(-?\d{1,9})D)?(?:T(?:(-?\d{1,9})H)?(?:(-?\d{1,9})M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,9}))?S)?)?)$/;
 
 function extractISODuration(match) {
   const [
diff --git a/src/impl/tokenParser.js b/src/impl/tokenParser.js
index 88560ae2..4ca0401c 100644
--- a/src/impl/tokenParser.js
+++ b/src/impl/tokenParser.js
@@ -12,13 +12,21 @@ function intUnit(regex, post = i => i) {
   return { regex, deser: ([s]) => post(parseDigits(s)) };
 }
 
+const NBSP = String.fromCharCode(160);
+const spaceOrNBSP = `( |${NBSP})`;
+const spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, "g");
+
 function fixListRegex(s) {
   // make dots optional and also make them literal
-  return s.replace(/\./, "\\.?");
+  // make space and non breakable space characters interchangeable
+  return s.replace(/\./g, "\\.?").replace(spaceOrNBSPRegExp, spaceOrNBSP);
 }
 
 function stripInsensitivities(s) {
-  return s.replace(/\./, "").toLowerCase();
+  return s
+    .replace(/\./g, "") // ignore dots that were made optional
+    .replace(spaceOrNBSPRegExp, " ") // interchange space and nbsp
+    .toLowerCase();
 }
 
 function oneOf(strings, startIndex) {
diff --git a/src/impl/util.js b/src/impl/util.js
index b007f587..c6321b16 100644
--- a/src/impl/util.js
+++ b/src/impl/util.js
@@ -261,18 +261,17 @@ export function normalizeObject(obj, normalizer) {
 }
 
 export function formatOffset(offset, format) {
-  const hours = Math.trunc(offset / 60),
-    minutes = Math.abs(offset % 60),
-    sign = hours >= 0 && !Object.is(hours, -0) ? "+" : "-",
-    base = `${sign}${Math.abs(hours)}`;
+  const hours = Math.trunc(Math.abs(offset / 60)),
+    minutes = Math.trunc(Math.abs(offset % 60)),
+    sign = offset >= 0 ? "+" : "-";
 
   switch (format) {
     case "short":
-      return `${sign}${padStart(Math.abs(hours), 2)}:${padStart(minutes, 2)}`;
+      return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
     case "narrow":
-      return minutes > 0 ? `${base}:${minutes}` : base;
+      return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
     case "techie":
-      return `${sign}${padStart(Math.abs(hours), 2)}${padStart(minutes, 2)}`;
+      return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
     default:
       throw new RangeError(`Value format ${format} is out of range for property format`);
   }
diff --git a/src/info.js b/src/info.js
index 77e397fd..11c32527 100644
--- a/src/info.js
+++ b/src/info.js
@@ -21,7 +21,7 @@ export default class Info {
     if (!zoneObj.isValid) {
       return false;
     }
-    const proto = DateTime.local()
+    const proto = DateTime.now()
       .setZone(zoneObj)
       .set({ month: 12 });
 
@@ -103,7 +103,7 @@ export default class Info {
   /**
    * Return an array of standalone week names.
    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
-   * @param {string} [length='long'] - the length of the month representation, such as "narrow", "short", "long".
+   * @param {string} [length='long'] - the length of the weekday representation, such as "narrow", "short", "long".
    * @param {Object} opts - options
    * @param {string} [opts.locale] - the locale code
    * @param {string} [opts.numberingSystem=null] - the numbering system
@@ -122,7 +122,7 @@ export default class Info {
    * Format weekdays differ from standalone weekdays in that they're meant to appear next to more date information. In some languages, that
    * changes the string.
    * See {@link Info#weekdays}
-   * @param {string} [length='long'] - the length of the month representation, such as "narrow", "short", "long".
+   * @param {string} [length='long'] - the length of the weekday representation, such as "narrow", "short", "long".
    * @param {Object} opts - options
    * @param {string} [opts.locale=null] - the locale code
    * @param {string} [opts.numberingSystem=null] - the numbering system
diff --git a/src/interval.js b/src/interval.js
index cb23bbcb..35babcfb 100644
--- a/src/interval.js
+++ b/src/interval.js
@@ -26,7 +26,7 @@ function validateStartEnd(start, end) {
  * * **Accessors** Use {@link Interval#start} and {@link Interval#end} to get the start and end.
  * * **Interrogation** To analyze the Interval, use {@link Interval#count}, {@link Interval#length}, {@link Interval#hasSame}, {@link Interval#contains}, {@link Interval#isAfter}, or {@link Interval#isBefore}.
  * * **Transformation** To create other Intervals out of this one, use {@link Interval#set}, {@link Interval#splitAt}, {@link Interval#splitBy}, {@link Interval#divideEqually}, {@link Interval#merge}, {@link Interval#xor}, {@link Interval#union}, {@link Interval#intersection}, or {@link Interval#difference}.
- * * **Comparison** To compare this Interval to another one, use {@link Interval#equals}, {@link Interval#overlaps}, {@link Interval#abutsStart}, {@link Interval#abutsEnd}, {@link Interval#engulfs}
+ * * **Comparison** To compare this Interval to another one, use {@link Interval#equals}, {@link Interval#overlaps}, {@link Interval#abutsStart}, {@link Interval#abutsEnd}, {@link Interval#engulfs}.
  * * **Output** To convert the Interval into other representations, see {@link Interval#toString}, {@link Interval#toISO}, {@link Interval#toISODate}, {@link Interval#toISOTime}, {@link Interval#toFormat}, and {@link Interval#toDuration}.
  */
 export default class Interval {
@@ -44,10 +44,6 @@ export default class Interval {
      * @access private
      */
     this.e = config.end;
-    /**
-     * @access private
-     */
-    this.invalid = config.invalid || null;
     /**
      * @access private
      */
@@ -104,23 +100,26 @@ export default class Interval {
    */
   static fromISO(text, opts) {
     const [s, e] = (text || "").split("/", 2);
-    const realOpts = Object.assign({}, opts, { nullOnInvalid: true });
+    const nullOnInvalidOpts = Object.assign({}, opts, { nullOnInvalid: true });
     if (s && e) {
-      const start = DateTime.fromISO(s, realOpts),
-        end = DateTime.fromISO(e, realOpts);
+      const start = DateTime.fromISO(s, nullOnInvalidOpts);
+      const startIsValid = start !== null;
+
+      const end = DateTime.fromISO(e, nullOnInvalidOpts);
+      const endIsValid = end !== null;
 
-      if (start && end) {
+      if (startIsValid && endIsValid) {
         return Interval.fromDateTimes(start, end);
       }
 
-      if (start) {
-        const dur = Duration.fromISO(e, realOpts);
-        if (dur) {
+      if (startIsValid) {
+        const dur = Duration.fromISO(e, nullOnInvalidOpts);
+        if (dur !== null) {
           return Interval.after(start, dur);
         }
-      } else if (end) {
-        const dur = Duration.fromISO(s, realOpts);
-        if (dur) {
+      } else if (endIsValid) {
+        const dur = Duration.fromISO(s, nullOnInvalidOpts);
+        if (dur !== null) {
           return Interval.before(end, dur);
         }
       }
@@ -181,7 +180,7 @@ export default class Interval {
    * @return {boolean}
    */
   hasSame(unit) {
-    return this.e.minus(1).hasSame(this.s, unit);
+    return this.isEmpty() || this.e.minus(1).hasSame(this.s, unit);
   }
 
   /**


Test patch:
diff --git a/test/datetime/create.test.js b/test/datetime/create.test.js
index c4af3b5e..cbf67e3b 100644
--- a/test/datetime/create.test.js
+++ b/test/datetime/create.test.js
@@ -14,16 +14,47 @@ import Settings from "../../src/settings";
 
 import Helpers from "../helpers";
 
-const withDefaultLocale = Helpers.setUnset("defaultLocale"),
+const withDefaultLocale = Helpers.withDefaultLocale,
   withDefaultNumberingSystem = Helpers.setUnset("defaultNumberingSystem"),
-  withDefaultOutputCalendar = Helpers.setUnset("defaultOutputCalendar");
+  withDefaultOutputCalendar = Helpers.setUnset("defaultOutputCalendar"),
+  withDefaultZone = Helpers.withDefaultZone;
+
+//------
+// .now()
+//------
+test("DateTime.now has today's date", () => {
+  const date = new Date(),
+    now = DateTime.now();
+  expect(now.toJSDate().getDate()).toBe(date.getDate());
+  // The two instants should be a few milliseconds apart
+  expect(Math.abs(now.valueOf() - date.valueOf()) < 1000).toBe(true);
+});
+
+test("DateTime.now accepts the default locale", () => {
+  withDefaultLocale("fr", () => expect(DateTime.now().locale).toBe("fr"));
+});
+
+test("DateTime.now accepts the default numbering system", () => {
+  withDefaultNumberingSystem("beng", () => expect(DateTime.now().numberingSystem).toBe("beng"));
+});
+
+test("DateTime.now accepts the default output calendar", () => {
+  withDefaultOutputCalendar("hebrew", () => expect(DateTime.now().outputCalendar).toBe("hebrew"));
+});
+
+test("DateTime.now accepts the default time zone", () => {
+  withDefaultZone("Europe/Paris", () => expect(DateTime.now().zoneName).toBe("Europe/Paris"));
+});
 
 //------
 // .local()
 //------
 test("DateTime.local() has today's date", () => {
-  const now = DateTime.local();
-  expect(now.toJSDate().getDate()).toBe(new Date().getDate());
+  const date = new Date(),
+    now = DateTime.local();
+  expect(now.toJSDate().getDate()).toBe(date.getDate());
+  // The two instants should be a few milliseconds apart
+  expect(Math.abs(now.valueOf() - date.valueOf()) < 1000).toBe(true);
 });
 
 test("DateTime.local(2017) is the beginning of the year", () => {
@@ -172,7 +203,8 @@ test("DateTime.local does not accept non-integer values", () => {
 });
 
 test("DateTime.local uses the default time zone", () => {
-  Helpers.withDefaultZone("UTC", () => expect(DateTime.local().zoneName).toBe("UTC"));
+  withDefaultZone("UTC", () => expect(DateTime.local().zoneName).toBe("UTC"));
+  withDefaultZone("Europe/Paris", () => expect(DateTime.local().zoneName).toBe("Europe/Paris"));
 });
 
 //------
@@ -537,7 +569,7 @@ test("DateTime.fromObject() returns null with nullOnInvalid option", () => {
 
 test("DateTime.fromObject() defaults high-order values to the current date", () => {
   const dateTime = DateTime.fromObject({}),
-    now = DateTime.local();
+    now = DateTime.now();
 
   expect(dateTime.year).toBe(now.year);
   expect(dateTime.month).toBe(now.month);
@@ -593,7 +625,7 @@ test("DateTime.fromObject() w/weekYears handles skew with Gregorian years", () =
 
 test("DateTime.fromObject() w/weeks defaults high-order values to the current date", () => {
   const dt = DateTime.fromObject({ weekday: 2 }),
-    now = DateTime.local();
+    now = DateTime.now();
 
   expect(dt.weekYear).toBe(now.weekYear);
   expect(dt.weekNumber).toBe(now.weekNumber);
@@ -629,7 +661,7 @@ test("DateTime.fromObject() w/ordinals handles fully specified dates", () => {
 
 test("DateTime.fromObject() w/ordinal defaults to the current year", () => {
   const dt = DateTime.fromObject({ ordinal: 200 }),
-    now = DateTime.local();
+    now = DateTime.now();
   expect(dt.year).toBe(now.year);
   expect(dt.ordinal).toBe(200);
 });
diff --git a/test/datetime/degrade.test.js b/test/datetime/degrade.test.js
index b225333a..7014036a 100644
--- a/test/datetime/degrade.test.js
+++ b/test/datetime/degrade.test.js
@@ -30,6 +30,7 @@ Helpers.withoutIntl("DateTime#toLocaleString supports known configurations", ()
 
   expected.set(DateTime.DATE_SHORT, "8/6/2014");
   expected.set(DateTime.DATE_MED, "Aug 6, 2014");
+  expected.set(DateTime.DATE_MED_WITH_WEEKDAY, "Wed, Aug 6, 2014");
   expected.set(DateTime.DATE_FULL, "August 6, 2014");
   expected.set(DateTime.DATE_HUGE, "Wednesday, August 6, 2014");
   expected.set(DateTime.TIME_SIMPLE, "9:15 AM");
@@ -79,7 +80,7 @@ Helpers.withoutIntl("DateTime#toLocaleString uses English", () => {
 });
 
 Helpers.withoutIntl("DateTime#toLocaleParts returns an empty array", () => {
-  expect(DateTime.local().toLocaleParts()).toEqual([]);
+  expect(DateTime.now().toLocaleParts()).toEqual([]);
 });
 
 Helpers.withoutIntl("DateTime.fromFormat can parse numbers in other locales", () => {
@@ -93,11 +94,11 @@ Helpers.withoutIntl("DateTime.fromFormat can't parse strings from other locales"
 });
 
 Helpers.withoutIntl("using time zones throws", () => {
-  expect(() => DateTime.local().setZone("America/New_York")).toThrow(InvalidZoneError);
+  expect(() => DateTime.now().setZone("America/New_York")).toThrow(InvalidZoneError);
 });
 
 Helpers.withoutIntl("DateTime#zoneName falls back to 'system'", () => {
-  expect(DateTime.local().zoneName).toBe("system");
+  expect(DateTime.now().zoneName).toBe("system");
 });
 
 Helpers.withoutIntl("DateTime#toLocaleString can use fixed-offset zones", () => {
@@ -148,7 +149,7 @@ Helpers.withoutFTP("DateTime.fromFormat can't parse strings from other locales",
 });
 
 Helpers.withoutFTP("setting the time zone still works", () => {
-  expect(DateTime.local().setZone("America/New_York").zoneName).toBe("America/New_York");
+  expect(DateTime.now().setZone("America/New_York").zoneName).toBe("America/New_York");
 });
 
 Helpers.withoutFTP("DateTime#offsetNameLong still works", () => {
@@ -168,7 +169,7 @@ Helpers.withoutFTP("DateTime#offsetNameLong still works", () => {
 });
 
 Helpers.withoutFTP("DateTime#toLocaleParts returns an empty array", () => {
-  expect(DateTime.local().toLocaleParts()).toEqual([]);
+  expect(DateTime.now().toLocaleParts()).toEqual([]);
 });
 
 //------
@@ -197,6 +198,6 @@ Helpers.withoutZones("DateTime#toLocaleParts is unaffected", () => {
   ]);
 });
 
-Helpers.withoutZones("using time zones results throws", () => {
-  expect(() => DateTime.local().setZone("America/New_York")).toThrow(InvalidZoneError);
+Helpers.withoutZones("using time zones throws", () => {
+  expect(() => DateTime.now().setZone("America/New_York")).toThrow(InvalidZoneError);
 });
diff --git a/test/datetime/equality.test.js b/test/datetime/equality.test.js
index b26fc9cc..4309eec8 100644
--- a/test/datetime/equality.test.js
+++ b/test/datetime/equality.test.js
@@ -3,7 +3,7 @@
 import { DateTime } from "../../src/luxon";
 
 test("equals self", () => {
-  const l = DateTime.local();
+  const l = DateTime.now();
   expect(l.equals(l)).toBe(true);
 });
 
diff --git a/test/datetime/format.test.js b/test/datetime/format.test.js
index 8fbef25a..5bc786cf 100644
--- a/test/datetime/format.test.js
+++ b/test/datetime/format.test.js
@@ -33,9 +33,33 @@ test("DateTime#toISO() shows 'Z' for UTC", () => {
   expect(dt.toISO()).toBe("1982-05-25T09:23:54.123Z");
 });
 
-test("DateTime#toISO() shows the offset", () => {
+test("DateTime#toISO() shows the offset, unless explicitely asked", () => {
   const offsetted = dt.toUTC(-6 * 60);
   expect(offsetted.toISO()).toBe("1982-05-25T03:23:54.123-06:00");
+  expect(offsetted.toISO({ includeOffset: false })).toBe("1982-05-25T03:23:54.123");
+});
+
+test("DateTime#toISO() supports the 'basic' format", () => {
+  expect(dt.toISO({ format: "basic" })).toBe("19820525T092354.123Z");
+});
+
+test("DateTime#toISO() suppresses [milli]seconds", () => {
+  const noZeroMilliseconds = { suppressMilliseconds: true };
+  expect(dt.toISO(noZeroMilliseconds)).toBe("1982-05-25T09:23:54.123Z");
+  expect(dt.set({ millisecond: 0 }).toISO(noZeroMilliseconds)).toBe("1982-05-25T09:23:54Z");
+
+  const noZeroSeconds = { suppressSeconds: true, suppressMilliseconds: true };
+  expect(dt.set({ millisecond: 0 }).toISO(noZeroSeconds)).toBe("1982-05-25T09:23:54Z");
+  expect(dt.set({ seconds: 0, milliseconds: 0 }).toISO(noZeroSeconds)).toBe("1982-05-25T09:23Z");
+});
+
+// #724, Firefox specific issue, offset prints as '-05:50.60000000000002'
+test("DateTime#toISO() rounds fractional timezone minute offsets", () => {
+  expect(
+    DateTime.fromMillis(-62090696591000)
+      .setZone("America/Chicago")
+      .toISO()
+  ).toBe("0002-06-04T10:26:13.000-05:50");
 });
 
 //------
@@ -273,7 +297,7 @@ test("DateTime#toLocaleString uses locale-appropriate time formats", () => {
 //------
 
 test("DateTime#resolvedLocaleOpts returns a thing", () => {
-  const res = DateTime.local().resolvedLocaleOpts();
+  const res = DateTime.now().resolvedLocaleOpts();
 
   expect(res.outputCalendar).toBeDefined();
   expect(res.locale).toBeDefined();
@@ -281,7 +305,7 @@ test("DateTime#resolvedLocaleOpts returns a thing", () => {
 });
 
 test("DateTime#resolvedLocaleOpts reflects changes to the locale", () => {
-  const res = DateTime.local()
+  const res = DateTime.now()
     .reconfigure({
       locale: "be",
       numberingSystem: "mong",
@@ -295,7 +319,7 @@ test("DateTime#resolvedLocaleOpts reflects changes to the locale", () => {
 });
 
 test("DateTime#resolvedLocaleOpts can override with options", () => {
-  const res = DateTime.local().resolvedLocaleOpts({
+  const res = DateTime.now().resolvedLocaleOpts({
     locale: "be",
     numberingSystem: "mong",
     outputCalendar: "coptic"
diff --git a/test/datetime/getters.test.js b/test/datetime/getters.test.js
index a69f9402..589a0ebb 100644
--- a/test/datetime/getters.test.js
+++ b/test/datetime/getters.test.js
@@ -132,7 +132,7 @@ test("DateTime#get can retrieve any unit", () => {
 // locale
 //------
 test("DateTime#locale returns the locale", () => {
-  const dt = DateTime.local().reconfigure({ locale: "be" });
+  const dt = DateTime.now().reconfigure({ locale: "be" });
   expect(dt.locale).toBe("be");
 });
 
diff --git a/test/datetime/math.test.js b/test/datetime/math.test.js
index 260490dd..5a6e9e19 100644
--- a/test/datetime/math.test.js
+++ b/test/datetime/math.test.js
@@ -70,6 +70,16 @@ test("DateTime#plus({ hours: 24 }) gains an hour to spring forward", () => {
   expect(later.hour).toBe(11);
 });
 
+// #669
+test("DateTime#plus({ days:0, hours: 24 }) gains an hour to spring forward", () => {
+  const i = DateTime.fromISO("2016-03-12T10:00", {
+      zone: "America/Los_Angeles"
+    }),
+    later = i.plus({ days: 0, hours: 24 });
+  expect(later.day).toBe(13);
+  expect(later.hour).toBe(11);
+});
+
 test("DateTime#plus(Duration) adds the right amount of time", () => {
   const i = DateTime.fromISO("2016-03-12T10:13"),
     later = i.plus(Duration.fromObject({ day: 1, hour: 3, minute: 28 }));
@@ -114,14 +124,26 @@ test("DateTime#plus handles fractional days", () => {
   );
 });
 
-test("DateTime#plus handles fractional months", () => {
+test("DateTime#plus handles fractional large units", () => {
+  const units = ["weeks", "months", "quarters", "years"];
+
   const d = DateTime.fromISO("2016-01-31T10:00");
-  expect(d.plus({ months: 8.7 })).toEqual(
-    d.plus({
-      months: 8,
-      milliseconds: Duration.fromObject({ months: 0.7 }).shiftTo("milliseconds")
-    })
-  );
+  for (const unit of units) {
+    expect(d.plus({ [unit]: 8.7 })).toEqual(
+      d.plus({
+        [unit]: 8,
+        milliseconds: Duration.fromObject({ [unit]: 0.7 }).as("milliseconds")
+      })
+    );
+  }
+});
+
+// #645
+test("DateTime#plus supports positive and negative duration units", () => {
+  const d = DateTime.fromISO("2020-01-08T12:34");
+  expect(d.plus({ months: 1, days: -1 })).toEqual(d.plus({ months: 1 }).plus({ days: -1 }));
+  expect(d.plus({ years: 4, days: -1 })).toEqual(d.plus({ years: 4 }).plus({ days: -1 }));
+  expect(d.plus({ years: 0.5, days: -1.5 })).toEqual(d.plus({ years: 0.5 }).plus({ days: -1.5 }));
 });
 
 //------
@@ -189,13 +211,27 @@ test("DateTime#minus handles fractional days", () => {
   );
 });
 
-test("DateTime#minus handles fractional months", () => {
+test("DateTime#minus handles fractional large units", () => {
+  const units = ["weeks", "months", "quarters", "years"];
+
   const d = DateTime.fromISO("2016-01-31T10:00");
-  expect(d.minus({ months: 8.7 })).toEqual(
-    d.minus({
-      months: 8,
-      milliseconds: Duration.fromObject({ months: 0.7 }).shiftTo("milliseconds")
-    })
+  for (const unit of units) {
+    expect(d.minus({ [unit]: 8.7 })).toEqual(
+      d.minus({
+        [unit]: 8,
+        milliseconds: Duration.fromObject({ [unit]: 0.7 }).as("milliseconds")
+      })
+    );
+  }
+});
+
+// #645
+test("DateTime#minus supports positive and negative duration units", () => {
+  const d = DateTime.fromISO("2020-01-08T12:34");
+  expect(d.minus({ months: 1, days: -1 })).toEqual(d.minus({ months: 1 }).minus({ days: -1 }));
+  expect(d.minus({ years: 4, days: -1 })).toEqual(d.minus({ years: 4 }).minus({ days: -1 }));
+  expect(d.minus({ years: 0.5, days: -1.5 })).toEqual(
+    d.minus({ years: 0.5 }).minus({ days: -1.5 })
   );
 });
 
diff --git a/test/datetime/misc.test.js b/test/datetime/misc.test.js
index 3b724709..4ab123e5 100644
--- a/test/datetime/misc.test.js
+++ b/test/datetime/misc.test.js
@@ -8,14 +8,14 @@ import { DateTime } from "../../src/luxon";
 //------
 
 test("DateTime#hasSame() can use milliseconds for exact comparisons", () => {
-  const dt = DateTime.local();
+  const dt = DateTime.now();
   expect(dt.hasSame(dt, "millisecond")).toBe(true);
   expect(dt.hasSame(dt.reconfigure({ locale: "fr" }), "millisecond")).toBe(true);
   expect(dt.hasSame(dt.plus({ milliseconds: 1 }), "millisecond")).toBe(false);
 });
 
 test("DateTime#hasSame() checks the unit", () => {
-  const dt = DateTime.local();
+  const dt = DateTime.now();
   expect(dt.hasSame(dt, "day")).toBe(true);
   expect(dt.hasSame(dt.startOf("day"), "day")).toBe(true);
   expect(dt.hasSame(dt.plus({ days: 1 }), "days")).toBe(false);
@@ -26,7 +26,7 @@ test("DateTime#hasSame() checks the unit", () => {
 //------
 
 test("DateTime#until() creates an Interval", () => {
-  const dt = DateTime.local(),
+  const dt = DateTime.now(),
     other = dt.plus({ days: 1 }),
     i = dt.until(other);
 
diff --git a/test/datetime/proto.test.js b/test/datetime/proto.test.js
index d61508ed..1fbfea3a 100644
--- a/test/datetime/proto.test.js
+++ b/test/datetime/proto.test.js
@@ -3,7 +3,7 @@
 import { DateTime } from "../../src/luxon";
 
 test("DateTime prototype properties should not throw when accessed", () => {
-  const d = DateTime.local();
+  const d = DateTime.now();
   expect(() =>
     Object.getOwnPropertyNames(d.__proto__).forEach(name => d.__proto__[name])
   ).not.toThrow();
diff --git a/test/datetime/regexParse.test.js b/test/datetime/regexParse.test.js
index ba762ffd..a0a74183 100644
--- a/test/datetime/regexParse.test.js
+++ b/test/datetime/regexParse.test.js
@@ -328,6 +328,17 @@ test("DateTime.fromISO() accepts year-month-dayThour:minute:second.millisecond",
     millisecond: 999
   });
 
+  // Support up to 20 digits
+  isSame("2016-05-25T09:24:15.12345678901234567890123456789", {
+    year: 2016,
+    month: 5,
+    day: 25,
+    hour: 9,
+    minute: 24,
+    second: 15,
+    millisecond: 123
+  });
+
   isSame("2016-05-25T09:24:15.1", {
     year: 2016,
     month: 5,
@@ -430,7 +441,7 @@ test("DateTime.fromISO() accepts year-ordinalTtime", () => {
 });
 
 test("DateTime.fromISO() accepts hour:minute:second.millisecond", () => {
-  const { year, month, day } = DateTime.local();
+  const { year, month, day } = DateTime.now();
   isSame("09:24:15.123", {
     year,
     month,
@@ -443,7 +454,7 @@ test("DateTime.fromISO() accepts hour:minute:second.millisecond", () => {
 });
 
 test("DateTime.fromISO() accepts hour:minute:second,millisecond", () => {
-  const { year, month, day } = DateTime.local();
+  const { year, month, day } = DateTime.now();
   isSame("09:24:15,123", {
     year,
     month,
@@ -456,7 +467,7 @@ test("DateTime.fromISO() accepts hour:minute:second,millisecond", () => {
 });
 
 test("DateTime.fromISO() accepts hour:minute:second", () => {
-  const { year, month, day } = DateTime.local();
+  const { year, month, day } = DateTime.now();
   isSame("09:24:15", {
     year,
     month,
@@ -469,7 +480,7 @@ test("DateTime.fromISO() accepts hour:minute:second", () => {
 });
 
 test("DateTime.fromISO() accepts hour:minute", () => {
-  const { year, month, day } = DateTime.local();
+  const { year, month, day } = DateTime.now();
   isSame("09:24", {
     year,
     month,
@@ -482,7 +493,7 @@ test("DateTime.fromISO() accepts hour:minute", () => {
 });
 
 test("DateTime.fromISO() accepts hour:minute", () => {
-  const { year, month, day } = DateTime.local();
+  const { year, month, day } = DateTime.now();
   isSame("09:24", {
     year,
     month,
diff --git a/test/datetime/relative.test.js b/test/datetime/relative.test.js
index 6be6afef..d2f067c1 100644
--- a/test/datetime/relative.test.js
+++ b/test/datetime/relative.test.js
@@ -102,14 +102,13 @@ test("DateTime#toRelativeCalendar uses the calendar", () => {
   expect(end.toRelativeCalendar({ base })).toBe("tomorrow");
 });
 
-// with current behavior, this fails the last day of the month
-// test("DateTime#toRelativeCalendar picks the correct unit with no options", () => {
-//   expect(
-//     DateTime.local()
-//       .plus({ days: 1 })
-//       .toRelativeCalendar()
-//   ).toBe("tomorrow");
-// });
+test("DateTime#toRelativeCalendar picks the correct unit with no options", () => {
+  const now = DateTime.now();
+  const isLastDayOfMonth = now.endOf("month").day === now.day;
+  expect(now.plus({ days: 1 }).toRelativeCalendar()).toBe(
+    isLastDayOfMonth ? "next month" : "tomorrow"
+  );
+});
 
 test("DateTime#toRelativeCalendar works down through the units", () => {
   const base = DateTime.fromObject({ year: 1983, month: 10, day: 14, hour: 12 });
@@ -154,7 +153,7 @@ Helpers.withoutRTF("DateTime#toRelativeCalendar falls back to English", () => {
 });
 
 test("DateTime#toRelativeCalendar works down through the units for different zone than default", () => {
-  const target = DateTime.local().setZone(`UTC+3`),
+  const target = DateTime.now().setZone(`UTC+3`),
     target1 = target.plus({ days: 1 }),
     target2 = target1.plus({ days: 1 }),
     target3 = target2.plus({ days: 1 }),
@@ -167,7 +166,7 @@ test("DateTime#toRelativeCalendar works down through the units for different zon
 });
 
 test("DateTime#toRelative works down through the units for different zone than default", () => {
-  const base = DateTime.local().setZone(`UTC+3`);
+  const base = DateTime.now().setZone(`UTC+3`);
 
   expect(base.plus({ minutes: 65 }).toRelative()).toBe("in 1 hour");
   expect(base.plus({ minutes: 165 }).toRelative()).toBe("in 2 hours");
diff --git a/test/datetime/tokenParse.test.js b/test/datetime/tokenParse.test.js
index 5558ffe0..f22ecc6d 100644
--- a/test/datetime/tokenParse.test.js
+++ b/test/datetime/tokenParse.test.js
@@ -6,6 +6,7 @@ import {
   MismatchedWeekdayError,
   UnitOutOfRangeError
 } from "../../src/errors";
+import Helpers from "../helpers";
 
 //------
 // .fromFormat
@@ -21,7 +22,7 @@ test("DateTime.fromFormat() parses basic times", () => {
   expect(i.millisecond).toBe(445);
 });
 
-test("DateTime.fromFormat() parses with variable-length inpus", () => {
+test("DateTime.fromFormat() parses with variable-length input", () => {
   let i = DateTime.fromFormat("1982/05/03 09:07:05.004", "y/M/d H:m:s.S");
   expect(i.year).toBe(1982);
   expect(i.month).toBe(5);
@@ -71,6 +72,41 @@ test("DateTime.fromFormat() throws if you specify meridiem with 24-hour time", (
   expect(() => DateTime.fromFormat("930PM", "Hmma")).toThrow(ConflictingSpecificationError);
 });
 
+// #714
+test("DateTime.fromFormat() makes dots optional and handles non breakable spaces", () => {
+  function parseMeridiem(input, isAM) {
+    const d = DateTime.fromFormat(input, "hh:mm a");
+    expect(d.hour).toBe(isAM ? 10 : 22);
+    expect(d.minute).toBe(45);
+    expect(d.second).toBe(0);
+  }
+
+  Helpers.withDefaultLocale("es-ES", () => {
+    // Meridiem for this locale is "a. m." or "p. m.", with a non breakable space
+    parseMeridiem("10:45 a. m.", true);
+    parseMeridiem("10:45 a. m", true);
+    parseMeridiem("10:45 a m.", true);
+    parseMeridiem("10:45 a m", true);
+
+    parseMeridiem("10:45 p. m.", false);
+    parseMeridiem("10:45 p. m", false);
+    parseMeridiem("10:45 p m.", false);
+    parseMeridiem("10:45 p m", false);
+
+    const nbsp = String.fromCharCode(160);
+
+    parseMeridiem(`10:45 a.${nbsp}m.`, true);
+    parseMeridiem(`10:45 a.${nbsp}m`, true);
+    parseMeridiem(`10:45 a${nbsp}m.`, true);
+    parseMeridiem(`10:45 a${nbsp}m`, true);
+
+    parseMeridiem(`10:45 p.${nbsp}m.`, false);
+    parseMeridiem(`10:45 p.${nbsp}m`, false);
+    parseMeridiem(`10:45 p${nbsp}m.`, false);
+    parseMeridiem(`10:45 p${nbsp}m`, false);
+  });
+});
+
 test("DateTime.fromFormat() parses variable-digit years", () => {
   expect(() => DateTime.fromFormat("", "y")).toThrow(UnparsableStringError);
   expect(DateTime.fromFormat("2", "y").year).toBe(2);
@@ -301,7 +337,7 @@ test("DateTime.fromFormat() validates weekday names", () => {
 
 test("DateTime.fromFormat() defaults weekday to this week", () => {
   const d = DateTime.fromFormat("Monday", "EEEE"),
-    now = DateTime.local();
+    now = DateTime.now();
   expect(d.weekYear).toBe(now.weekYear);
   expect(d.weekNumber).toBe(now.weekNumber);
   expect(d.weekday).toBe(1);
@@ -357,7 +393,7 @@ test("DateTime.fromFormat() accepts weekYear by itself", () => {
 });
 
 test("DateTime.fromFormat() accepts weekNumber by itself", () => {
-  const now = DateTime.local();
+  const now = DateTime.now();
 
   let d = DateTime.fromFormat("17", "WW");
   expect(d.weekYear).toBe(now.weekYear);
@@ -379,7 +415,7 @@ test("DateTime.fromFormat() accepts weekYear/weekNumber/weekday", () => {
 
 test("DateTime.fromFormat() allows regex content", () => {
   const d = DateTime.fromFormat("Monday", "EEEE"),
-    now = DateTime.local();
+    now = DateTime.now();
   expect(d.weekYear).toBe(now.weekYear);
   expect(d.weekNumber).toBe(now.weekNumber);
   expect(d.weekday).toBe(1);
diff --git a/test/datetime/typecheck.test.js b/test/datetime/typecheck.test.js
index 9872da23..3958a4c8 100644
--- a/test/datetime/typecheck.test.js
+++ b/test/datetime/typecheck.test.js
@@ -5,7 +5,7 @@ import { DateTime } from "../../src/luxon";
 // #isDateTime()
 //------
 test("DateTime#isDateTime return true for valid DateTime", () => {
-  const dt = DateTime.local();
+  const dt = DateTime.now();
   expect(DateTime.isDateTime(dt)).toBe(true);
 });
 
diff --git a/test/datetime/zone.test.js b/test/datetime/zone.test.js
index fcf1655d..cb8dd067 100644
--- a/test/datetime/zone.test.js
+++ b/test/datetime/zone.test.js
@@ -248,10 +248,8 @@ test("Etc/GMT zones work even though V8 does not support them", () => {
 //------
 
 test("The local zone does local stuff", () => {
-  if (DateTime.local().zoneName === "America/New_York") {
-    expect(DateTime.local(2016, 8, 6).offsetNameLong).toBe("Eastern Daylight Time");
-    expect(DateTime.local(2016, 8, 6).offsetNameShort).toBe("EDT");
-  }
+  expect(DateTime.local(2016, 8, 6).offsetNameLong).toBe("Eastern Daylight Time");
+  expect(DateTime.local(2016, 8, 6).offsetNameShort).toBe("EDT");
 });
 
 test("Setting the default zone results in a different creation zone", () => {
diff --git a/test/duration/parse.test.js b/test/duration/parse.test.js
index 68e12c6b..5efd584e 100644
--- a/test/duration/parse.test.js
+++ b/test/duration/parse.test.js
@@ -18,6 +18,7 @@ test("Duration.fromISO can parse a variety of ISO formats", () => {
   check("P1YT34000S", { years: 1, seconds: 34000 });
   check("P1W1DT13H23M34S", { weeks: 1, days: 1, hours: 13, minutes: 23, seconds: 34 });
   check("P2W", { weeks: 2 });
+  check("PT10000000000000000000.999S", { seconds: 10000000000000000000, milliseconds: 999 });
 });
 
 test("Duration.fromISO can parse mixed or negative durations", () => {
diff --git a/test/duration/units.test.js b/test/duration/units.test.js
index 4338a1f3..29a090bc 100644
--- a/test/duration/units.test.js
+++ b/test/duration/units.test.js
@@ -49,7 +49,7 @@ test("Duration#shiftTo without any units no-ops", () => {
   expect(dur.toObject()).toEqual({ years: 3 });
 });
 
-test("Duration#shifTo accumulates when rolling up", () => {
+test("Duration#shiftTo accumulates when rolling up", () => {
   expect(
     Duration.fromObject({ minutes: 59, seconds: 183 })
       .shiftTo("hours", "minutes", "seconds")
@@ -57,7 +57,7 @@ test("Duration#shifTo accumulates when rolling up", () => {
   ).toEqual({ hours: 1, minutes: 2, seconds: 3 });
 });
 
-test("Duration#shifTo keeps unecessary higher-order negative units 0", () => {
+test("Duration#shiftTo keeps unnecessary higher-order negative units 0", () => {
   expect(
     Duration.fromObject({ milliseconds: -100 })
       .shiftTo("hours", "minutes", "seconds")
@@ -65,6 +65,16 @@ test("Duration#shifTo keeps unecessary higher-order negative units 0", () => {
   ).toEqual({ hours: 0, minutes: 0, seconds: -0.1 });
 });
 
+test("Duration#shiftTo does not normalize values", () => {
+  // Normalizing would convert to { quarters: 4, months: 1, days: 10 }
+  // which would be converted back to 404 days instead
+  expect(
+    Duration.fromObject({ quarters: 0, months: 0, days: 400 })
+      .shiftTo("days")
+      .toObject()
+  ).toEqual({ days: 400 });
+});
+
 //------
 // #normalize()
 //-------
@@ -110,6 +120,34 @@ test("Duration#normalize handles the full grid partially negative durations", ()
   });
 });
 
+test("Duration#normalize can convert all unit pairs", () => {
+  const units = [
+    "years",
+    "quarters",
+    "months",
+    "weeks",
+    "days",
+    "hours",
+    "minutes",
+    "seconds",
+    "milliseconds"
+  ];
+
+  for (let i = 0; i < units.length; i++) {
+    for (let j = i + 1; j < units.length; j++) {
+      const duration = Duration.fromObject({ [units[i]]: 1, [units[j]]: 2 });
+      const normalizedDuration = duration.normalize().toObject();
+      expect(normalizedDuration[units[i]]).not.toBe(NaN);
+      expect(normalizedDuration[units[j]]).not.toBe(NaN);
+
+      const accurateDuration = duration.reconfigure({ conversionAccuracy: "longterm" });
+      const normalizedAccurateDuration = accurateDuration.normalize().toObject();
+      expect(normalizedAccurateDuration[units[i]]).not.toBe(NaN);
+      expect(normalizedAccurateDuration[units[j]]).not.toBe(NaN);
+    }
+  }
+});
+
 //------
 // #as()
 //-------
diff --git a/test/interval/create.test.js b/test/interval/create.test.js
index 8e951a33..ef4c326c 100644
--- a/test/interval/create.test.js
+++ b/test/interval/create.test.js
@@ -46,7 +46,7 @@ test("Interval.fromDateTimes rejects missing or invalid arguments", () => {
   expect(() => Interval.fromDateTimes(validDate.plus({ days: 1 }), validDate)).toThrow(
     InvalidArgumentError
   );
-  expect(() => Interval.fromDateTimes(DateTime.local(), true)).toThrow(InvalidArgumentError);
+  expect(() => Interval.fromDateTimes(DateTime.now(), true)).toThrow(InvalidArgumentError);
 });
 
 test("Interval.fromDateTimes throws with start date coming after end date", () => {
diff --git a/test/interval/info.test.js b/test/interval/info.test.js
index 69d1724c..198e7410 100644
--- a/test/interval/info.test.js
+++ b/test/interval/info.test.js
@@ -9,7 +9,7 @@ const fromISOs = (s, e) => DateTime.fromISO(s).until(DateTime.fromISO(e));
 // #length()
 //-------
 test("Interval#length defaults to milliseconds", () => {
-  const n = DateTime.local(),
+  const n = DateTime.now(),
     d = n.until(n.plus({ minutes: 1 }));
   expect(d.length()).toBe(60 * 1000);
 });
diff --git a/test/interval/parse.test.js b/test/interval/parse.test.js
index 3040cb48..b3384eb5 100644
--- a/test/interval/parse.test.js
+++ b/test/interval/parse.test.js
@@ -2,6 +2,9 @@
 
 import { Interval } from "../../src/luxon";
 import { UnparsableStringError } from "../../src/errors";
+import Helpers from "../helpers";
+
+const withThrowOnInvalid = Helpers.setUnset("throwOnInvalid");
 
 //------
 // .fromISO()
@@ -116,6 +119,17 @@ test("Interval.fromISO accepts a zone argument", () => {
   expect(durDate.start.zoneName).toBe("Europe/Paris");
 });
 
+// #728
+test("Interval.fromISO works with Settings.throwOnInvalid", () => {
+  withThrowOnInvalid(true, () => {
+    const dateDur = Interval.fromISO("2020-06-22T17:30:00.000+02:00/PT5H30M");
+    expect(dateDur.length("minutes")).toBe(330);
+
+    const durDate = Interval.fromISO("PT5H30M/2020-06-22T17:30:00.000+02:00");
+    expect(durDate.length("minutes")).toBe(330);
+  });
+});
+
 const badInputs = [
   null,
   "",
diff --git a/test/interval/typecheck.test.js b/test/interval/typecheck.test.js
index 2173ef76..f0b3f6d6 100644
--- a/test/interval/typecheck.test.js
+++ b/test/interval/typecheck.test.js
@@ -6,7 +6,7 @@ import { Interval, DateTime } from "../../src/luxon";
 // #isInterval
 //-------
 test("Interval.isInterval return true for valid duration", () => {
-  const int = Interval.fromDateTimes(DateTime.local(), DateTime.local());
+  const int = Interval.fromDateTimes(DateTime.now(), DateTime.now());
   expect(Interval.isInterval(int)).toBe(true);
 });
 
diff --git a/test/zones/fixedOffset.test.js b/test/zones/fixedOffset.test.js
index 8ae5b631..82df958d 100644
--- a/test/zones/fixedOffset.test.js
+++ b/test/zones/fixedOffset.test.js
@@ -53,6 +53,16 @@ test("FixedOffsetZone.formatOffset is consistent despite the provided timestamp"
   expect(zone.formatOffset(1552280400, "techie")).toBe("-0500");
 });
 
+test("FixedOffsetZone.formatOffset prints the correct sign before the offset", () => {
+  expect(FixedOffsetZone.instance(-300).formatOffset(0, "short")).toBe("-05:00");
+  expect(FixedOffsetZone.instance(-30).formatOffset(0, "short")).toBe("-00:30");
+  // Note the negative zero results in a + sign
+  expect(FixedOffsetZone.instance(-0).formatOffset(0, "short")).toBe("+00:00");
+  expect(FixedOffsetZone.instance(0).formatOffset(0, "short")).toBe("+00:00");
+  expect(FixedOffsetZone.instance(30).formatOffset(0, "short")).toBe("+00:30");
+  expect(FixedOffsetZone.instance(300).formatOffset(0, "short")).toBe("+05:00");
+});
+
 test("FixedOffsetZone.equals requires both zones to be fixed", () => {
   expect(FixedOffsetZone.utcInstance.equals(IANAZone.create("UTC"))).toBe(false);
 });