Repository: moment/luxon
Pull request #976 (2021-07-08 01:18:58)

Add support for formatting and parsing tokens `uu` and `uuu`
These are the same as Moment's `SS` and `S` tokens, respectively.

Moment's [implementation](https://github.com/moment/moment/blob/e96809208c9d1b1bbe22d605e76985770024de42/src/lib/units/millisecond.js#L19-L25).

This is for Issue #965. ~~I'm not sure about how to add the support for `DateTime.fromFormat` though.~~


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8bd2b3a7..6b0db13c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,12 @@
 # Changelog
 
+## 2.0.2 (2021-08-08)
+
+Fix locale defaulting
+
 ## 2.0.0 (2021-07-3)
 
-See upgrading.md
+See [Upgrading section](https://github.com/moment/luxon#upgrading-to-20) in README.md
 
 ## 1.28.0 (2021-07-03)
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 96554b31..b01cdc70 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,7 @@ Once you're sure your bugfix or feature makes sense for Luxon, make sure you tak
 1.  Be sure you run `npm run format` before you commit. Note this will modify your source files to line up with the style guidelines.
 1.  Make sure you add or ESDoc annotations appropriately. You can run `npm run docs` to generate the HTML for them. They land in the `build/docs` directory. This also builds the markdown files in `/docs` into the guide on the Luxon website.
 1.  To test Luxon in your browser, run `npm run site` and then open `build/demo/global.html`. You can access Luxon classes in the console like `window.luxon.DateTime`.
-1.  To test in Node, run `npm run build` and then run something like `var DateTime = require('./build/cjs/luxon').DateTime`.
+1.  To test in Node, run `npm run build` and then run something like `var DateTime = require('./build/cjs-browser/luxon').DateTime`.
 
 Luxon uses [Husky](https://github.com/typicode/husky) to run the formatter on your code as a pre-commit hook. You should still run `npm run format` yourself to catch other issues, but this hook will help prevent you from failing the build with a trivial formatting error.
 
diff --git a/docs/formatting.md b/docs/formatting.md
index d5b9aec1..7eb1dd61 100644
--- a/docs/formatting.md
+++ b/docs/formatting.md
@@ -85,28 +85,29 @@ dt.toLocaleString(newFormat); //=>  'Thursday, 4/20/2017'
 
 Here's the full set of provided presets using the October 14, 1983 at `13:30:23` as an example.
 
-| Name                        | Description                                                        | Example in en_US                                           | Example in fr                                            |
-| --------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------- | -------------------------------------------------------- |
-| DATE_SHORT                  | short date                                                         | 10/14/1983                                                 | 14/10/1983                                               |
-| DATE_MED                    | abbreviated date                                                   | Oct 14, 1983                                               | 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                                                    |
-| TIME_WITH_SECONDS           | time with seconds                                                  | 1:30:23 PM                                                 | 13:30:23                                                 |
-| TIME_WITH_SHORT_OFFSET      | time with seconds and abbreviated named offset                     | 1:30:23 PM EDT                                             | 13:30:23 UTC−4                                           |
-| TIME_WITH_LONG_OFFSET       | time with seconds and full named offset                            | 1:30:23 PM Eastern Daylight Time                           | 13:30:23 heure d’été de l’Est                            |
-| TIME_24_SIMPLE              | 24-hour time                                                       | 13:30                                                      | 13:30                                                    |
-| TIME_24_WITH_SECONDS        | 24-hour time with seconds                                          | 13:30:23                                                   | 13:30:23                                                 |
-| TIME_24_WITH_SHORT_OFFSET   | 24-hour time with seconds and abbreviated named offset             | 13:30:23 EDT                                               | 13:30:23 UTC−4                                           |
-| TIME_24_WITH_LONG_OFFSET    | 24-hour time with seconds and full named offset                    | 13:30:23 Eastern Daylight Time                             | 13:30:23 heure d’été de l’Est                            |
-| DATETIME_SHORT              | short date & time                                                  | 10/14/1983, 1:30 PM                                        | 14/10/1983 à 13:30                                       |
-| DATETIME_MED                | abbreviated date & time                                            | Oct 14, 1983, 1:30 PM                                      | 14 oct. 1983 à 13:30                                     |
-| DATETIME_FULL               | full date and time with abbreviated named offset                   | October 14, 1983, 1:30 PM EDT                              | 14 octobre 1983 à 13:30 UTC−4                            |
-| DATETIME_HUGE               | full date and time with weekday and full named offset              | Friday, October 14, 1983, 1:30 PM Eastern Daylight Time    | vendredi 14 octobre 1983 à 13:30 heure d’été de l’Est    |
-| DATETIME_SHORT_WITH_SECONDS | short date & time with seconds                                     | 10/14/1983, 1:30:23 PM                                     | 14/10/1983 à 13:30:23                                    |
-| DATETIME_MED_WITH_SECONDS   | abbreviated date & time with seconds                               | Oct 14, 1983, 1:30:23 PM                                   | 14 oct. 1983 à 13:30:23                                  |
-| DATETIME_FULL_WITH_SECONDS  | full date and time with abbreviated named offset with seconds      | October 14, 1983, 1:30:23 PM EDT                           | 14 octobre 1983 à 13:30:23 UTC−4                         |
-| DATETIME_HUGE_WITH_SECONDS  | full date and time with weekday and full named offset with seconds | Friday, October 14, 1983, 1:30:23 PM Eastern Daylight Time | vendredi 14 octobre 1983 à 13:30:23 heure d’été de l’Est |
+| Name                         | Description                                                        | Example in en_US                                             | Example in fr                                              |
+| ---------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------ | ---------------------------------------------------------- |
+| `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 abbreviated 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                                             | `Friday, October 14, 1983`                                   | `vendredi 14 octobre 1983`                                 |
+| `TIME_SIMPLE`                | time                                                               | `1:30 PM`                                                    | `13:30`                                                    |
+| `TIME_WITH_SECONDS`          | time with seconds                                                  | `1:30:23 PM`                                                 | `13:30:23`                                                 |
+| `TIME_WITH_SHORT_OFFSET`     | time with seconds and abbreviated named offset                     | `1:30:23 PM EDT`                                             | `13:30:23 UTC−4`                                           |
+| `TIME_WITH_LONG_OFFSET`      | time with seconds and full named offset                            | `1:30:23 PM Eastern Daylight Time`                           | `13:30:23 heure d’été de l’Est`                            |
+| `TIME_24_SIMPLE`             | 24-hour time                                                       | `13:30`                                                      | `13:30`                                                    |
+| `TIME_24_WITH_SECONDS`       | 24-hour time with seconds                                          | `13:30:23`                                                   | `13:30:23`                                                 |
+| `TIME_24_WITH_SHORT_OFFSET`  | 24-hour time with seconds and abbreviated named offset             | `13:30:23 EDT`                                               | `13:30:23 UTC−4`                                           |
+| `TIME_24_WITH_LONG_OFFSET`   | 24-hour time with seconds and full named offset                    | `13:30:23 Eastern Daylight Time`                             | `13:30:23 heure d’été de l’Est`                            |
+| `DATETIME_SHORT`             | short date & time                                                  | `10/14/1983, 1:30 PM`                                        | `14/10/1983 à 13:30`                                       |
+| `DATETIME_MED`               | abbreviated date & time                                            | `Oct 14, 1983, 1:30 PM`                                      | `14 oct. 1983 à 13:30`                                     |
+| `DATETIME_FULL`              | full date and time with abbreviated named offset                   | `October 14, 1983, 1:30 PM EDT`                              | `14 octobre 1983 à 13:30 UTC−4`                            |
+| `DATETIME_HUGE`              | full date and time with weekday and full named offset              | `Friday, October 14, 1983, 1:30 PM Eastern Daylight Time`    | `vendredi 14 octobre 1983 à 13:30 heure d’été de l’Est`    |
+| `DATETIME_SHORT_WITH_SECONDS`| short date & time with seconds                                     | `10/14/1983, 1:30:23 PM`                                     | `14/10/1983 à 13:30:23`                                    |
+| `DATETIME_MED_WITH_SECONDS`  | abbreviated date & time with seconds                               | `Oct 14, 1983, 1:30:23 PM`                                   | `14 oct. 1983 à 13:30:23`                                  |
+| `DATETIME_FULL_WITH_SECONDS` | full date and time with abbreviated named offset with seconds      | `October 14, 1983, 1:30:23 PM EDT`                           | `14 octobre 1983 à 13:30:23 UTC−4`                         |
+| `DATETIME_HUGE_WITH_SECONDS` | full date and time with weekday and full named offset with seconds | `Friday, October 14, 1983, 1:30:23 PM Eastern Daylight Time` | `vendredi 14 octobre 1983 à 13:30:23 heure d’été de l’Est` |
 
 ### Intl
 
@@ -179,6 +180,8 @@ The macro options available correspond one-to-one with the preset formats define
 | S                |              | millisecond, no padding                                        | `54`                                                          |
 | SSS              |              | millisecond, padded to 3                                       | `054`                                                         |
 | u                |              | fractional seconds, functionally identical to SSS              | `054`                                                         |
+| uu               |              | fractional seconds, between 0 and 99, padded to 2              | `05`                                                          |
+| uuu              |              | fractional seconds, between 0 and 9                            | `0`                                                           |
 | s                |              | second, no padding                                             | `4`                                                           |
 | ss               |              | second, padded to 2 padding                                    | `04`                                                          |
 | m                |              | minute, no padding                                             | `7`                                                           |
diff --git a/docs/home.md b/docs/home.md
index 15c62e90..8f39699c 100644
--- a/docs/home.md
+++ b/docs/home.md
@@ -21,9 +21,9 @@ DateTime.now().setZone('America/New_York').minus({weeks:1}).endOf('day').toISO()
  
 ### Getting started
  
-  * [Demo](../demo/global.html ':ignore')
+  * [Demo](https://moment.github.io/luxon/demo/global.html ':ignore')
   * Read the [quick tour](tour.md)
   * Browse the topic docs on the left
   * Read the [api docs](api-docs/index.html ':ignore')
 
-Logo by [John Dalziel](https://github.com/crashposition)
\ No newline at end of file
+Logo by [John Dalziel](https://github.com/crashposition)
diff --git a/docs/install.md b/docs/install.md
index c9ae3a47..9771cc4e 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -21,9 +21,9 @@ You may wish to alias the classes you use:
 var DateTime = luxon.DateTime;
 ```
 
-## Node
+## Node.js
 
-Supports Node 6+. Install via NPM:
+Supports Node.js 6+. Install via NPM:
 
 ```
 npm install --save luxon
@@ -35,12 +35,12 @@ const { DateTime } = require("luxon");
 
 If you want to work with locales, you need ICU support:
 
- 1. **For Node 13+, it comes built-in, no action necessary**
- 2. For older Nodes (only 12 is supported), you need to install it yourself:
-    1. Install a build of Node with full ICU baked in, such as via nvm: nvm install <version> -s --with-intl=full-icu --download=all or brew: brew install node --with-full-icu
-    2. Install the ICU data externally and point Node to it. The instructions on how to do that are below.
+ 1. **For Node.js 13+, it comes built-in, no action necessary**
+ 2. For older versions of Node.js (only 12 is supported), you need to install it yourself:
+    1. Install a build of Node.js with full ICU baked in, such as via nvm: nvm install <version> -s --with-intl=full-icu --download=all or brew: brew install node --with-full-icu
+    2. Install the ICU data externally and point Node.js to it. The instructions on how to do that are below.
 
-The instructions for using full-icu as a package are a little confusing. Node can't automatically discover that you've installed it, so you need to tell it where to find the data, like this:
+The instructions for using full-icu as a package are a little confusing. Node.js can't automatically discover that you've installed it, so you need to tell it where to find the data, like this:
 
 ```
 npm install full-icu
diff --git a/docs/math.md b/docs/math.md
index 0366af5f..2dd72e8f 100644
--- a/docs/math.md
+++ b/docs/math.md
@@ -211,7 +211,7 @@ These are always true and you can roll them up and down with consistency (e.g. `
 These should match your intuition and for most purposes they work well. But they're not just wrong; they're not even self-consistent:
 
 ```js
-dur.shiftTo('months').shiftTo('days').as('years') //=> 0.9863013698630136
+Duration.fromObject({ years:1 }).shiftTo('months').shiftTo('days').as('years') //=> 0.9863013698630136
 ```
 
 This is because 12 * 30 != 365. These errors can be annoying, but they can also cause significant issues if the errors accumulate:
diff --git a/docs/matrix.md b/docs/matrix.md
index 0bbefde0..5b19ab7a 100644
--- a/docs/matrix.md
+++ b/docs/matrix.md
@@ -29,7 +29,7 @@ Luxon, there's only one partially-supported feature, so this is currently pretty
 older browsers, so there were nuanced feature caveats. Newer versions will add more caveats as new browser capabilities
 become available and Luxon takes advantage of them if they're present.)
 
-1.  **Relative time formatting**. Luxon's support for relative time formatting (e.g. `DateTime#toRelative` and `DateTime#toRelativeCalendar`) depends on Intl.RelativeTimeFormat, which is currently only available in Chrome and Firefox. Luxon will fall back to using English if that capability is missing.
+1.  **Relative time formatting**. Luxon's support for relative time formatting (e.g. `DateTime#toRelative` and `DateTime#toRelativeCalendar`) depends on Intl.RelativeTimeFormat. Luxon will fall back to using English if that capability is missing.
 
 If the browser lacks these capabilities, Luxon tries its best:
 
diff --git a/docs/moment.md b/docs/moment.md
index e41d443d..524fef64 100644
--- a/docs/moment.md
+++ b/docs/moment.md
@@ -27,7 +27,7 @@ This happens because the `plus` method returns a new instance, leaving `d1` unmo
 1. Months in Luxon are 1-indexed instead of 0-indexed like in Moment and the native Date type.
 1. Localizations and time zones are implemented by the native Intl API (or a polyfill of it), instead of by the library itself.
 1. Luxon has both a Duration type and an Interval type. The Interval type is like Twix.
-1. Luxon lacks the relative time features of Moment and won't support it until the required [facilities](https://github.com/tc39/proposal-intl-relative-time) are provided by the browser.
+1. Luxon only supports [relative time features](#humanization) if the required [Intl.RelativeTimeFormat](https://github.com/tc39/proposal-intl-relative-time) APIs are provided by the browser or polyfills.
 
 ## Other API style differences
 
diff --git a/docs/parsing.md b/docs/parsing.md
index d971732f..5540f63a 100644
--- a/docs/parsing.md
+++ b/docs/parsing.md
@@ -83,7 +83,7 @@ Both methods accept the same options, which allow you to specify a timezone, cal
 
 ### JS Date Object
 
-A native JS `Date` object can be converted into a `DateTime` using [fromJSDate](../class/src/datetime.js~DateTime.html#static-method-fromJSDate).
+A native JS `Date` object can be converted into a `DateTime` using `DateTime.fromJSDate`.
 
 An optional `zone` parameter can be provided to set the zone on the resulting object.
 
@@ -177,13 +177,15 @@ Because Luxon was able to parse the string without difficulty, the output is a l
 
 ### Table of tokens
 
-(Examples below given for `2014-08-06T13:07:04.054` considered as a local time in America/New_York). Note that many tokens supported by the [formatter](formatting.md) are **not** supported by the parser. That includes all the "macro" formats like "D" for "localized numeric date".
+(Examples below given for `2014-08-06T13:07:04.054` considered as a local time in America/New_York). Note that many tokens supported by the [formatter](formatting.md) are **not** supported by the parser.
 
 | Standalone token | Format token | Description                                                    | Example                     |
 | ---------------- | ------------ | -------------------------------------------------------------- | --------------------------- |
 | S                |              | millisecond, no padding                                        | `54`                        |
 | SSS              |              | millisecond, padded to 3                                       | `054`                       |
 | u                |              | fractional seconds, (5 is a half second, 54 is slightly more)  | `54`                        |
+| uu               |              | fractional seconds, (one or two digits)                        | `05`                        |
+| uuu              |              | fractional seconds, (only one digit)                           | `5`                         |
 | s                |              | second, no padding                                             | `4`                         |
 | ss               |              | second, padded to 2 padding                                    | `04`                        |
 | m                |              | minute, no padding                                             | `7`                         |
diff --git a/docs/upgrading.md b/docs/upgrading.md
index 58109a96..189ab9fe 100644
--- a/docs/upgrading.md
+++ b/docs/upgrading.md
@@ -73,10 +73,12 @@ Settings.defaultZone = IANAZone.create("America/New_York"); // or a Zone instanc
 Settings.defaultZone //=> a Zone instance
 ```
 
+The most significant breaking change here is that `Settings.defaultZoneName` no longer exists.
+
 #### Other breaking changes
 
  * `DateTime#toObject` no longer accepts an `includeConfig` option
- * `resolvedLocalOpts` is now `resolvedLocaleOptions`
+ * `resolvedLocaleOpts` is now `resolvedLocaleOptions`
  * `Zone#universal` is now `Zone#isUniversal`
 
 ### Non-breaking changes
@@ -88,4 +90,4 @@ Settings.defaultZone //=> a Zone instance
 We originally had more ambitious plans for Luxon 2.0: a port to Typescript, an overhaul of error handling, and lots of other changes.
 The problem is that we're very busy, and in the meantime browsers have evolved quickly, the mistakes in our API bothered a lot
 of developers, and our need to support old environments made Luxon more difficult to change. So we made a basic set of changes
-to give us some operating room. And hopefully someday we'll get back to those more ambitious plans.
\ No newline at end of file
+to give us some operating room. And hopefully someday we'll get back to those more ambitious plans.
diff --git a/docs/zones.md b/docs/zones.md
index c003c12c..1d62fc20 100644
--- a/docs/zones.md
+++ b/docs/zones.md
@@ -15,7 +15,7 @@ All those things will make it less likely you ever need to work explicitly with
 
 ## Terminology
 
-Bear with me here. Time zones are pain in the ass. Luxon has lots of tools to deal with them, but there's no getting around the fact that they're complicated. The terminology for time zones and offsets isn't well-established. But let's try to impose some order:
+Bear with me here. Time zones are a pain in the ass. Luxon has lots of tools to deal with them, but there's no getting around the fact that they're complicated. The terminology for time zones and offsets isn't well-established. But let's try to impose some order:
 
 1.  An **offset** is a difference between the local time and the UTC time, such as +5 (hours) or -12:30. They may be expressed directly in minutes, or in hours, or in a combination of minutes and hours. Here we'll use hours.
 1.  A **time zone** is a set of rules, associated with a geographical location, that determines the local offset from UTC at any given time. The best way to identify a zone is by its IANA string, such as "America/New_York". That zone says something to the effect of "The offset is -5, except between March and November, when it's -4".
@@ -36,7 +36,7 @@ If all this seems too terse, check out these articles. The terminology in them i
 
 Luxon's DateTime class supports zones directly. By default, a date created in Luxon is "in" the local time zone of the machine it's running on. By "in" we mean that the DateTime has, as one of its properties, an associated zone.
 
-It's important to remember that a DateTime represents a specific instant in time and that instant has an unambiguous meaning independent of what time zone you're in; the zone is really piece of social metadata that affects how humans interact with the time, rather than a fact about the passing of time itself. Of course, Luxon is a library for humans, so that social metadata affects Luxon's behavior too. It just doesn't change _what time it is_.
+It's important to remember that a DateTime represents a specific instant in time and that instant has an unambiguous meaning independent of what time zone you're in; the zone is really a piece of social metadata that affects how humans interact with the time, rather than a fact about the passing of time itself. Of course, Luxon is a library for humans, so that social metadata affects Luxon's behavior too. It just doesn't change _what time it is_.
 
 Specifically, a DateTime's zone affects its behavior in these ways:
 
@@ -104,7 +104,7 @@ Note two things:
 1.  The date and time specified in the string was interpreted as a Parisian local time (i.e. it's the time that corresponds to what would be called 9:10 _there_).
 2.  The resulting DateTime object is in Europe/Paris.
 
-Those are conceptually independent (i.e. Luxon could have converted the time to the system zone), but it practice it's more convenient for the same option to govern both.
+Those are conceptually independent (i.e. Luxon could have converted the time to the system zone), but in practice it's more convenient for the same option to govern both.
 
 In addition, one static method, `utc()`, specifically interprets the input as being specified in UTC. It also returns a DateTime in UTC:
 
diff --git a/jest.config.js b/jest.config.js
index 5dc75e2d..b3558377 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -2,5 +2,5 @@ module.exports = {
   testEnvironment: "node",
   roots: ["test"],
   coverageDirectory: "build/coverage",
-  collectCoverageFrom: ["src/**/*.js", "!src/zone.js"]
+  collectCoverageFrom: ["src/**/*.js", "!src/zone.js"],
 };
diff --git a/package-lock.json b/package-lock.json
index d7c8cffa..41428ff9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,11 +1,11 @@
 {
   "name": "luxon",
-  "version": "2.0.0",
+  "version": "2.0.1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
-      "version": "2.0.0",
+      "version": "2.0.1",
       "license": "MIT",
       "devDependencies": {
         "@babel/core": "^7.14.6",
diff --git a/package.json b/package.json
index 478fb123..3820f426 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "luxon",
-  "version": "2.0.0",
+  "version": "2.0.2",
   "description": "Immutable date wrapper",
   "author": "Isaac Cambron",
   "keywords": [
diff --git a/scripts/repl b/scripts/repl
index 68cb8fc0..d19850fa 100755
--- a/scripts/repl
+++ b/scripts/repl
@@ -1,2 +1,2 @@
 #!/bin/bash
-NODE_ICU_DATA="$(pwd)/node_modules/full-icu" LANG=en_US.utf8 node -i -r "./scripts/bootstrap.js"
+LANG=en-US.utf8 node -i -r "./scripts/bootstrap.js"
diff --git a/site/docs/_coverpage.md b/site/docs/_coverpage.md
index bb482d14..22a3a169 100644
--- a/site/docs/_coverpage.md
+++ b/site/docs/_coverpage.md
@@ -2,7 +2,7 @@
 
 # Luxon <small>2.x</small>
 
-> A powerful, modern, and friendly wrapper for Javascript dates and times.
+> A powerful, modern, and friendly wrapper for JavaScript dates and times.
 
  * DateTimes, Durations, and Intervals
  * Immutable, chainable, unambiguous API.
diff --git a/src/datetime.js b/src/datetime.js
index 44510111..c476e0aa 100644
--- a/src/datetime.js
+++ b/src/datetime.js
@@ -167,8 +167,6 @@ function parseDataToDateTime(parsed, parsedZone, opts, format, text) {
       inst = DateTime.fromObject(parsed, {
         ...opts,
         zone: interpretationZone,
-        // setZone is a valid option in the calling methods, but not in fromObject
-        setZone: undefined,
       });
     return setZone ? inst : inst.setZone(zone);
   } else {
@@ -391,13 +389,13 @@ function lastOpts(argList) {
  *
  * Here is a brief overview of the most commonly used functionality it provides:
  *
- * * **Creation**: To create a DateTime from its components, use one of its factory class methods: {@link local}, {@link utc}, and (most flexibly) {@link fromObject}. To create one from a standard string format, use {@link fromISO}, {@link fromHTTP}, and {@link fromRFC2822}. To create one from a custom string format, use {@link fromFormat}. To create one from a native JS date, use {@link fromJSDate}.
- * * **Gregorian calendar and time**: To examine the Gregorian properties of a DateTime individually (i.e as opposed to collectively through {@link toObject}), use the {@link year}, {@link month},
- * {@link day}, {@link hour}, {@link minute}, {@link second}, {@link millisecond} accessors.
- * * **Week calendar**: For ISO week calendar attributes, see the {@link weekYear}, {@link weekNumber}, and {@link weekday} accessors.
- * * **Configuration** See the {@link locale} and {@link numberingSystem} accessors.
- * * **Transformation**: To transform the DateTime into other DateTimes, use {@link set}, {@link reconfigure}, {@link setZone}, {@link setLocale}, {@link plus}, {@link minus}, {@link endOf}, {@link startOf}, {@link toUTC}, and {@link toLocal}.
- * * **Output**: To convert the DateTime to other representations, use the {@link toRelative}, {@link toRelativeCalendar}, {@link toJSON}, {@link toISO}, {@link toHTTP}, {@link toObject}, {@link toRFC2822}, {@link toString}, {@link toLocaleString}, {@link toFormat}, {@link toMillis} and {@link toJSDate}.
+ * * **Creation**: To create a DateTime from its components, use one of its factory class methods: {@link DateTime.local}, {@link DateTime.utc}, and (most flexibly) {@link DateTime.fromObject}. To create one from a standard string format, use {@link DateTime.fromISO}, {@link DateTime.fromHTTP}, and {@link DateTime.fromRFC2822}. To create one from a custom string format, use {@link DateTime.fromFormat}. To create one from a native JS date, use {@link DateTime.fromJSDate}.
+ * * **Gregorian calendar and time**: To examine the Gregorian properties of a DateTime individually (i.e as opposed to collectively through {@link DateTime#toObject}), use the {@link DateTime#year}, {@link DateTime#month},
+ * {@link DateTime#day}, {@link DateTime#hour}, {@link DateTime#minute}, {@link DateTime#second}, {@link DateTime#millisecond} accessors.
+ * * **Week calendar**: For ISO week calendar attributes, see the {@link DateTime#weekYear}, {@link DateTime#weekNumber}, and {@link DateTime#weekday} accessors.
+ * * **Configuration** See the {@link DateTime#locale} and {@link DateTime#numberingSystem} accessors.
+ * * **Transformation**: To transform the DateTime into other DateTimes, use {@link DateTime#set}, {@link DateTime#reconfigure}, {@link DateTime#setZone}, {@link DateTime#setLocale}, {@link DateTime.plus}, {@link DateTime#minus}, {@link DateTime#endOf}, {@link DateTime#startOf}, {@link DateTime#toUTC}, and {@link DateTime#toLocal}.
+ * * **Output**: To convert the DateTime to other representations, use the {@link DateTime#toRelative}, {@link DateTime#toRelativeCalendar}, {@link DateTime#toJSON}, {@link DateTime#toISO}, {@link DateTime#toHTTP}, {@link DateTime#toObject}, {@link DateTime#toRFC2822}, {@link DateTime#toString}, {@link DateTime#toLocaleString}, {@link DateTime#toFormat}, {@link DateTime#toMillis} and {@link DateTime#toJSDate}.
  *
  * There's plenty others documented below. In addition, for more information on subtler topics like internationalization, time zones, alternative calendars, validity, and so on, see the external documentation.
  */
@@ -489,7 +487,7 @@ export default class DateTime {
    * @example DateTime.local({ zone: "America/New_York" })      //~> now, in US east coast time
    * @example DateTime.local(2017)                              //~> 2017-01-01T00:00:00
    * @example DateTime.local(2017, 3)                           //~> 2017-03-01T00:00:00
-   * @example DateTime.local(2017, 3, 12, { locale: "fr")       //~> 2017-03-12T00:00:00, with a French locale
+   * @example DateTime.local(2017, 3, 12, { locale: "fr" })     //~> 2017-03-12T00:00:00, with a French locale
    * @example DateTime.local(2017, 3, 12, 5)                    //~> 2017-03-12T05:00:00
    * @example DateTime.local(2017, 3, 12, 5, { zone: "utc" })   //~> 2017-03-12T05:00:00, in UTC
    * @example DateTime.local(2017, 3, 12, 5, 45)                //~> 2017-03-12T05:45:00
@@ -516,15 +514,15 @@ export default class DateTime {
    * @param {string} [options.locale] - a locale to set on the resulting DateTime instance
    * @param {string} [options.outputCalendar] - the output calendar to set on the resulting DateTime instance
    * @param {string} [options.numberingSystem] - the numbering system to set on the resulting DateTime instance
-   * @example DateTime.utc()                                            //~> now
-   * @example DateTime.utc(2017)                                        //~> 2017-01-01T00:00:00Z
-   * @example DateTime.utc(2017, 3)                                     //~> 2017-03-01T00:00:00Z
-   * @example DateTime.utc(2017, 3, 12)                                 //~> 2017-03-12T00:00:00Z
-   * @example DateTime.utc(2017, 3, 12, 5)                              //~> 2017-03-12T05:00:00Z
-   * @example DateTime.utc(2017, 3, 12, 5, 45)                          //~> 2017-03-12T05:45:00Z
-   * @example DateTime.utc(2017, 3, 12, 5, 45, { locale: "fr" } )       //~> 2017-03-12T05:45:00Z with a French locale
-   * @example DateTime.utc(2017, 3, 12, 5, 45, 10)                      //~> 2017-03-12T05:45:10Z
-   * @example DateTime.utc(2017, 3, 12, 5, 45, 10, 765, { locale: "fr") //~> 2017-03-12T05:45:10.765Z with a French locale
+   * @example DateTime.utc()                                              //~> now
+   * @example DateTime.utc(2017)                                          //~> 2017-01-01T00:00:00Z
+   * @example DateTime.utc(2017, 3)                                       //~> 2017-03-01T00:00:00Z
+   * @example DateTime.utc(2017, 3, 12)                                   //~> 2017-03-12T00:00:00Z
+   * @example DateTime.utc(2017, 3, 12, 5)                                //~> 2017-03-12T05:00:00Z
+   * @example DateTime.utc(2017, 3, 12, 5, 45)                            //~> 2017-03-12T05:45:00Z
+   * @example DateTime.utc(2017, 3, 12, 5, 45, { locale: "fr" })          //~> 2017-03-12T05:45:00Z with a French locale
+   * @example DateTime.utc(2017, 3, 12, 5, 45, 10)                        //~> 2017-03-12T05:45:10Z
+   * @example DateTime.utc(2017, 3, 12, 5, 45, 10, 765, { locale: "fr" }) //~> 2017-03-12T05:45:10.765Z with a French locale
    * @return {DateTime}
    */
   static utc() {
@@ -633,7 +631,7 @@ export default class DateTime {
    * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }) //~> today at 10:26:06
    * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'utc' }),
    * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'local' })
-   * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { }zone: 'America/New_York' })
+   * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'America/New_York' })
    * @example DateTime.fromObject({ weekYear: 2016, weekNumber: 2, weekday: 3 }).toISODate() //=> '2016-01-13'
    * @return {DateTime}
    */
@@ -801,7 +799,7 @@ export default class DateTime {
 
   /**
    * Create a DateTime from an input string and format string.
-   * Defaults to en-US if no locale has been specified, regardless of the system's locale. For a table of tokens and their interpretations, see [here](/#/parsing?id=table-of-tokens).
+   * Defaults to en-US if no locale has been specified, regardless of the system's locale. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/parsing?id=table-of-tokens).
    * @param {string} text - the string to parse
    * @param {string} fmt - the format the string is expected to be in (see the link below for the formats)
    * @param {Object} opts - options to affect the creation
@@ -1250,7 +1248,7 @@ export default class DateTime {
   /**
    * "Set" the DateTime's zone to UTC. Returns a newly-constructed DateTime.
    *
-   * Equivalent to {@link setZone}('utc')
+   * Equivalent to {@link DateTime.setZone}('utc')
    * @param {number} [offset=0] - optionally, an offset from UTC in minutes
    * @param {Object} [opts={}] - options to pass to `setZone()`
    * @return {DateTime}
@@ -1272,8 +1270,8 @@ export default class DateTime {
   /**
    * "Set" the DateTime's zone to specified zone. Returns a newly-constructed DateTime.
    *
-   * By default, the setter keeps the underlying time the same (as in, the same timestamp), but the new instance will report different local times and consider DSTs when making computations, as with {@link plus}. You may wish to use {@link toLocal} and {@link toUTC} which provide simple convenience wrappers for commonly used zones.
-   * @param {string|Zone} [zone='local'] - a zone identifier. As a string, that can be any IANA zone supported by the host environment, or a fixed-offset name of the form 'UTC+3', or the strings 'local' or 'utc'. You may also supply an instance of a {@link Zone} class.
+   * By default, the setter keeps the underlying time the same (as in, the same timestamp), but the new instance will report different local times and consider DSTs when making computations, as with {@link DateTime.plus}. You may wish to use {@link DateTime.toLocal} and {@link DateTime.toUTC} which provide simple convenience wrappers for commonly used zones.
+   * @param {string|Zone} [zone='local'] - a zone identifier. As a string, that can be any IANA zone supported by the host environment, or a fixed-offset name of the form 'UTC+3', or the strings 'local' or 'utc'. You may also supply an instance of a {@link DateTime.Zone} class.
    * @param {Object} opts - options
    * @param {boolean} [opts.keepLocalTime=false] - If true, adjust the underlying time so that the local time stays the same, but in the target zone. You should rarely need this.
    * @return {DateTime}
@@ -1318,7 +1316,7 @@ export default class DateTime {
 
   /**
    * "Set" the values of specified units. Returns a newly-constructed DateTime.
-   * You can only set units with this method; for "setting" metadata, see {@link reconfigure} and {@link setZone}.
+   * You can only set units with this method; for "setting" metadata, see {@link DateTime.reconfigure} and {@link DateTime.setZone}.
    * @param {Object} values - a mapping of units to numbers
    * @example dt.set({ year: 2017 })
    * @example dt.set({ hour: 8, minute: 30 })
@@ -1390,7 +1388,7 @@ export default class DateTime {
 
   /**
    * Subtract a period of time to this DateTime and return the resulting DateTime
-   * See {@link plus}
+   * See {@link DateTime.plus}
    * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
    @return {DateTime}
   */
@@ -1474,7 +1472,7 @@ export default class DateTime {
 
   /**
    * Returns a string representation of this DateTime formatted according to the specified format string.
-   * **You may not want this.** See {@link toLocaleString} for a more flexible formatting tool. For a table of tokens and their interpretations, see [here](/#/formatting?id=table-of-tokens).
+   * **You may not want this.** See {@link DateTime.toLocaleString} for a more flexible formatting tool. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/formatting?id=table-of-tokens).
    * Defaults to en-US if no locale has been specified, regardless of the system's locale.
    * @param {string} fmt - the format string
    * @param {Object} opts - opts to override the configuration options on this DateTime
@@ -1689,7 +1687,7 @@ export default class DateTime {
   }
 
   /**
-   * Returns the epoch milliseconds of this DateTime. Alias of {@link toMillis}
+   * Returns the epoch milliseconds of this DateTime. Alias of {@link DateTime.toMillis}
    * @return {number}
    */
   valueOf() {
@@ -1791,7 +1789,7 @@ export default class DateTime {
 
   /**
    * Return the difference between this DateTime and right now.
-   * See {@link diff}
+   * See {@link DateTime.diff}
    * @param {string|string[]} [unit=['milliseconds']] - the unit or units units (such as 'hours' or 'days') to include in the duration
    * @param {Object} opts - options that affect the creation of the Duration
    * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
@@ -1813,7 +1811,7 @@ export default class DateTime {
   /**
    * Return whether this DateTime is in the same unit of time as another DateTime.
    * Higher-order units must also be identical for this function to return `true`.
-   * Note that time zones are **ignored** in this comparison, which compares the **local** calendar time. Use {@link setZone} to convert one of the dates if needed.
+   * Note that time zones are **ignored** in this comparison, which compares the **local** calendar time. Use {@link DateTime.setZone} to convert one of the dates if needed.
    * @param {DateTime} otherDateTime - the other DateTime
    * @param {string} unit - the unit of time to check sameness on
    * @example DateTime.now().hasSame(otherDT, 'day'); //~> true if otherDT is in the same current calendar day
@@ -1957,7 +1955,7 @@ export default class DateTime {
   // FORMAT PRESETS
 
   /**
-   * {@link toLocaleString} format like 10/14/1983
+   * {@link DateTime.toLocaleString} format like 10/14/1983
    * @type {Object}
    */
   static get DATE_SHORT() {
@@ -1965,7 +1963,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'Oct 14, 1983'
+   * {@link DateTime.toLocaleString} format like 'Oct 14, 1983'
    * @type {Object}
    */
   static get DATE_MED() {
@@ -1973,7 +1971,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'Fri, Oct 14, 1983'
+   * {@link DateTime.toLocaleString} format like 'Fri, Oct 14, 1983'
    * @type {Object}
    */
   static get DATE_MED_WITH_WEEKDAY() {
@@ -1981,7 +1979,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'October 14, 1983'
+   * {@link DateTime.toLocaleString} format like 'October 14, 1983'
    * @type {Object}
    */
   static get DATE_FULL() {
@@ -1989,7 +1987,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'Tuesday, October 14, 1983'
+   * {@link DateTime.toLocaleString} format like 'Tuesday, October 14, 1983'
    * @type {Object}
    */
   static get DATE_HUGE() {
@@ -1997,7 +1995,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '09:30 AM'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like '09:30 AM'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get TIME_SIMPLE() {
@@ -2005,7 +2003,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '09:30:23 AM'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like '09:30:23 AM'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get TIME_WITH_SECONDS() {
@@ -2013,7 +2011,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '09:30:23 AM EDT'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like '09:30:23 AM EDT'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get TIME_WITH_SHORT_OFFSET() {
@@ -2021,7 +2019,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '09:30:23 AM Eastern Daylight Time'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like '09:30:23 AM Eastern Daylight Time'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get TIME_WITH_LONG_OFFSET() {
@@ -2029,7 +2027,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '09:30', always 24-hour.
+   * {@link DateTime.toLocaleString} format like '09:30', always 24-hour.
    * @type {Object}
    */
   static get TIME_24_SIMPLE() {
@@ -2037,7 +2035,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '09:30:23', always 24-hour.
+   * {@link DateTime.toLocaleString} format like '09:30:23', always 24-hour.
    * @type {Object}
    */
   static get TIME_24_WITH_SECONDS() {
@@ -2045,7 +2043,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '09:30:23 EDT', always 24-hour.
+   * {@link DateTime.toLocaleString} format like '09:30:23 EDT', always 24-hour.
    * @type {Object}
    */
   static get TIME_24_WITH_SHORT_OFFSET() {
@@ -2053,7 +2051,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '09:30:23 Eastern Daylight Time', always 24-hour.
+   * {@link DateTime.toLocaleString} format like '09:30:23 Eastern Daylight Time', always 24-hour.
    * @type {Object}
    */
   static get TIME_24_WITH_LONG_OFFSET() {
@@ -2061,7 +2059,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '10/14/1983, 9:30 AM'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like '10/14/1983, 9:30 AM'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_SHORT() {
@@ -2069,7 +2067,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like '10/14/1983, 9:30:33 AM'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like '10/14/1983, 9:30:33 AM'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_SHORT_WITH_SECONDS() {
@@ -2077,7 +2075,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'Oct 14, 1983, 9:30 AM'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like 'Oct 14, 1983, 9:30 AM'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_MED() {
@@ -2085,7 +2083,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'Oct 14, 1983, 9:30:33 AM'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like 'Oct 14, 1983, 9:30:33 AM'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_MED_WITH_SECONDS() {
@@ -2093,7 +2091,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'Fri, 14 Oct 1983, 9:30 AM'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like 'Fri, 14 Oct 1983, 9:30 AM'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_MED_WITH_WEEKDAY() {
@@ -2101,7 +2099,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'October 14, 1983, 9:30 AM EDT'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like 'October 14, 1983, 9:30 AM EDT'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_FULL() {
@@ -2109,7 +2107,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'October 14, 1983, 9:30:33 AM EDT'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like 'October 14, 1983, 9:30:33 AM EDT'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_FULL_WITH_SECONDS() {
@@ -2117,7 +2115,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'Friday, October 14, 1983, 9:30 AM Eastern Daylight Time'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like 'Friday, October 14, 1983, 9:30 AM Eastern Daylight Time'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_HUGE() {
@@ -2125,7 +2123,7 @@ export default class DateTime {
   }
 
   /**
-   * {@link toLocaleString} format like 'Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time'. Only 12-hour if the locale is.
+   * {@link DateTime.toLocaleString} format like 'Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time'. Only 12-hour if the locale is.
    * @type {Object}
    */
   static get DATETIME_HUGE_WITH_SECONDS() {
diff --git a/src/duration.js b/src/duration.js
index 9a530170..0def3d89 100644
--- a/src/duration.js
+++ b/src/duration.js
@@ -557,8 +557,8 @@ export default class Duration {
   /**
    * Scale this Duration by the specified amount. Return a newly-constructed Duration.
    * @param {function} fn - The function to apply to each unit. Arity is 1 or 2: the value of the unit and, optionally, the unit name. Must return a number.
-   * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnit(x => x * 2) //=> { hours: 2, minutes: 60 }
-   * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnit((x, u) => u === "hour" ? x * 2 : x) //=> { hours: 2, minutes: 30 }
+   * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits(x => x * 2) //=> { hours: 2, minutes: 60 }
+   * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits((x, u) => u === "hour" ? x * 2 : x) //=> { hours: 2, minutes: 30 }
    * @return {Duration}
    */
   mapUnits(fn) {
diff --git a/src/impl/formatter.js b/src/impl/formatter.js
index 4463781a..38200c85 100644
--- a/src/impl/formatter.js
+++ b/src/impl/formatter.js
@@ -179,6 +179,11 @@ export default class Formatter {
             return this.num(dt.second);
           case "ss":
             return this.num(dt.second, 2);
+          // fractional seconds
+          case "uu":
+            return this.num(Math.floor(dt.millisecond / 10), 2);
+          case "uuu":
+            return this.num(Math.floor(dt.millisecond / 100));
           // minutes
           case "m":
             return this.num(dt.minute);
diff --git a/src/impl/locale.js b/src/impl/locale.js
index 8ca69d29..633b1f97 100644
--- a/src/impl/locale.js
+++ b/src/impl/locale.js
@@ -43,7 +43,7 @@ function systemLocale() {
   if (sysLocaleCache) {
     return sysLocaleCache;
   } else {
-    sysLocaleCache = "en-US";
+    sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale;
     return sysLocaleCache;
   }
 }
@@ -265,11 +265,11 @@ export default class Locale {
   }
 
   static create(locale, numberingSystem, outputCalendar, defaultToEN = false) {
-    const specifiedLocale = locale || Settings.defaultLocale,
-      // the system locale is useful for human readable strings but annoying for parsing/formatting known formats
-      localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale()),
-      numberingSystemR = numberingSystem || Settings.defaultNumberingSystem,
-      outputCalendarR = outputCalendar || Settings.defaultOutputCalendar;
+    const specifiedLocale = locale || Settings.defaultLocale;
+    // the system locale is useful for human readable strings but annoying for parsing/formatting known formats
+    const localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale());
+    const numberingSystemR = numberingSystem || Settings.defaultNumberingSystem;
+    const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar;
     return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale);
   }
 
diff --git a/src/impl/tokenParser.js b/src/impl/tokenParser.js
index 6b31541d..e5a1270e 100644
--- a/src/impl/tokenParser.js
+++ b/src/impl/tokenParser.js
@@ -141,6 +141,10 @@ function unitForToken(token, loc) {
           return intUnit(three);
         case "u":
           return simple(oneToNine);
+        case "uu":
+          return simple(oneOrTwo);
+        case "uuu":
+          return intUnit(one);
         // meridiem
         case "a":
           return oneOf(loc.meridiems(), 0);
diff --git a/src/info.js b/src/info.js
index b0fdf297..4d92035b 100644
--- a/src/info.js
+++ b/src/info.js
@@ -157,13 +157,10 @@ export default class Info {
 
   /**
    * Return the set of available features in this environment.
-   * Some features of Luxon are not available in all environments. For example, on older browsers, timezone support is not available. Use this function to figure out if that's the case.
+   * Some features of Luxon are not available in all environments. For example, on older browsers, relative time formatting support is not available. Use this function to figure out if that's the case.
    * Keys:
-   * * `zones`: whether this environment supports IANA timezones
-   * * `intlTokens`: whether this environment supports internationalized token-based formatting/parsing
-   * * `intl`: whether this environment supports general internationalization
    * * `relative`: whether this environment supports relative time formatting
-   * @example Info.features() //=> { intl: true, intlTokens: false, zones: true, relative: false }
+   * @example Info.features() //=> { relative: false }
    * @return {Object}
    */
   static features() {
diff --git a/src/luxon.js b/src/luxon.js
index 76acdae4..173ca1e3 100644
--- a/src/luxon.js
+++ b/src/luxon.js
@@ -9,7 +9,7 @@ import InvalidZone from "./zones/invalidZone.js";
 import SystemZone from "./zones/systemZone.js";
 import Settings from "./settings.js";
 
-const VERSION = "2.0.0";
+const VERSION = "2.0.2";
 
 export {
   VERSION,
diff --git a/src/zones/IANAZone.js b/src/zones/IANAZone.js
index 960c3fc6..5975598a 100644
--- a/src/zones/IANAZone.js
+++ b/src/zones/IANAZone.js
@@ -97,6 +97,9 @@ export default class IANAZone extends Zone {
    * @return {boolean}
    */
   static isValidZone(zone) {
+    if (!zone) {
+      return false;
+    }
     try {
       new Intl.DateTimeFormat("en-US", { timeZone: zone }).format();
       return true;


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index c29f8f80..a2694ceb 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -18,7 +18,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [15.x]
+        node-version: [16.x]
 
     steps:
     - uses: actions/checkout@v2
diff --git a/test/datetime/toFormat.test.js b/test/datetime/toFormat.test.js
index 1d76e384..116a71e5 100644
--- a/test/datetime/toFormat.test.js
+++ b/test/datetime/toFormat.test.js
@@ -35,6 +35,18 @@ test("DateTime#toFormat('u') returns fractional seconds", () => {
   expect(dt.set({ millisecond: 80 }).toFormat("u")).toBe("080"); // I think this is OK
 });
 
+test("DateTime#toFormat('uu') returns fractional seconds as two digits", () => {
+  expect(dt.toFormat("uu")).toBe("12");
+  expect(dt.set({ millisecond: 82 }).toFormat("uu")).toBe("08");
+  expect(dt.set({ millisecond: 789 }).toFormat("uu")).toBe("78");
+});
+
+test("DateTime#toFormat('uuu') returns fractional seconds as one digit", () => {
+  expect(dt.toFormat("uuu")).toBe("1");
+  expect(dt.set({ millisecond: 82 }).toFormat("uuu")).toBe("0");
+  expect(dt.set({ millisecond: 789 }).toFormat("uuu")).toBe("7");
+});
+
 test("DateTime#toFormat('S') returns the millisecond", () => {
   expect(dt.toFormat("S")).toBe("123");
   expect(dt.reconfigure({ locale: "bn" }).toFormat("S")).toBe("১২৩");
diff --git a/test/datetime/tokenParse.test.js b/test/datetime/tokenParse.test.js
index 08708fc2..c2f3a15d 100644
--- a/test/datetime/tokenParse.test.js
+++ b/test/datetime/tokenParse.test.js
@@ -171,6 +171,14 @@ test("DateTime.fromFormat() parses fractional seconds", () => {
   expect(DateTime.fromFormat("003", "u").millisecond).toBe(3);
   expect(DateTime.fromFormat("1234", "u").millisecond).toBe(123);
   expect(DateTime.fromFormat("1235", "u").millisecond).toBe(123);
+
+  expect(DateTime.fromFormat("1", "uu").millisecond).toBe(100);
+  expect(DateTime.fromFormat("12", "uu").millisecond).toBe(120);
+  expect(DateTime.fromFormat("02", "uu").millisecond).toBe(20);
+  expect(DateTime.fromFormat("-33", "uu").isValid).toBe(false);
+
+  expect(DateTime.fromFormat("1", "uuu").millisecond).toBe(100);
+  expect(DateTime.fromFormat("-2", "uuu").isValid).toBe(false);
 });
 
 test("DateTime.fromFormat() parses weekdays", () => {
diff --git a/test/zones/IANA.test.js b/test/zones/IANA.test.js
index 81d9138e..62b420ce 100644
--- a/test/zones/IANA.test.js
+++ b/test/zones/IANA.test.js
@@ -29,6 +29,9 @@ test("IANAZone.isValidZone", () => {
   expect(IANAZone.isValidZone("Fantasia/Castle")).toBe(false);
   expect(IANAZone.isValidZone("Sport~~blorp")).toBe(false);
   expect(IANAZone.isValidZone("")).toBe(false);
+  expect(IANAZone.isValidZone(undefined)).toBe(false);
+  expect(IANAZone.isValidZone(null)).toBe(false);
+  expect(IANAZone.isValidZone(4)).toBe(false);
 });
 
 test("IANAZone.parseGMTOffset returns a number for a valid input", () => {