Repository: moment/luxon
Pull request #1116 (2022-01-08 00:56:13)

Add luxon to console in /api-docs
Having `luxon` accessible in the console of https://moment.github.io/luxon/ is super useful to me -- however, it isn't available on /api-docs, where it is arguably even more useful. Many times, I've opened the console to try something in the API docs out, just to find that `luxon` isn't there. (Most of the time, I end up switching tabs back to the homepage to run it in the homepage console.) This PR injects `luxon.js` into /api-docs so it's accessible there.

linux-foundation-easycla[bot]: <a href="https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19772872/47118129/1116/#/?version=2"><img src="https://s3.amazonaws.com/cla-project-logo-prod/cla-not-signed.svg" alt="CLA Not Signed" align="left" height="28" width="328" ></a><br/><br /><ul><li><a href='https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19772872/47118129/1116/#/?version=2' target='_blank'>:x:</a> - Nisala Kalupahana The commit (e4f7246c5cabd25820748ae44efefd12cb88bd4b) is not authorized under a signed CLA. <a href='https://api.easycla.lfx.linuxfoundation.org/v2/repository-provider/github/sign/19772872/47118129/1116/#/?version=2' target='_blank'>Please click here to be authorized</a>. For further assistance with EasyCLA, <a href='https://jira.linuxfoundation.org/servicedesk/customer/portal/4' target='_blank'>please submit a support request ticket</a>.</li></ul>
nkalupahana: @icambron or anyone else, I'd love to get a review on this whenever possible :)

Patch:
diff --git a/package.json b/package.json
index 2b5f26e1..89d0c4c4 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
     "build-global": "babel-node tasks/buildGlobal.js",
     "jest": "jest",
     "test": "jest --coverage",
-    "api-docs": "mkdir -p build && documentation build src/luxon.js -f html -o build/api-docs",
+    "api-docs": "mkdir -p build && documentation build src/luxon.js -f html -o build/api-docs && sed -i.bak 's/<\\/body>/<script src=\"\\/global\\/luxon.js\"><\\/script><script>console.log(\"You can try Luxon right here using the `luxon` global, like `luxon.DateTime.now()`\");<\\/script><\\/body>/g' build/api-docs/index.html && rm build/api-docs/index.html.bak",
     "copy-site": "mkdir -p build && rsync -a docs/ build/docs && rsync -a site/ build",
     "site": "npm run api-docs && npm run copy-site",
     "format": "prettier --write 'src/**/*.js' 'test/**/*.js' 'benchmarks/*.js'",
diff --git a/src/datetime.js b/src/datetime.js
index 46e8e117..47acf7a7 100644
--- a/src/datetime.js
+++ b/src/datetime.js
@@ -1678,17 +1678,20 @@ export default class DateTime {
    * @param {Object} opts - options
    * @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'
+   * @param {boolean} [opts.includeOffsetSpace=true] - include the space between the time and the offset, such as '05:15:16.345 -04:00'
    * @example DateTime.utc().toSQL() //=> '05:15:16.345'
    * @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 } = {}) {
+  toSQLTime({ includeOffset = true, includeZone = false, includeOffsetSpace = true } = {}) {
     let fmt = "HH:mm:ss.SSS";
 
     if (includeZone || includeOffset) {
-      fmt += " ";
+      if (includeOffsetSpace) {
+        fmt += " ";
+      }
       if (includeZone) {
         fmt += "z";
       } else if (includeOffset) {
@@ -1704,6 +1707,7 @@ export default class DateTime {
    * @param {Object} opts - options
    * @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'
+   * @param {boolean} [opts.includeOffsetSpace=true] - include the space between the time and the offset, such as '05:15:16.345 -04:00'
    * @example DateTime.utc(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 Z'
    * @example DateTime.local(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 -04:00'
    * @example DateTime.local(2014, 7, 13).toSQL({ includeOffset: false }) //=> '2014-07-13 00:00:00.000'
@@ -1749,6 +1753,14 @@ export default class DateTime {
   toSeconds() {
     return this.isValid ? this.ts / 1000 : NaN;
   }
+  
+  /**
+   * Returns the epoch seconds (as a whole number) of this DateTime.
+   * @return {number}
+   */
+  toUnixInteger() {
+    return this.isValid ? Math.floor(this.ts / 1000) : NaN;
+  }
 
   /**
    * Returns an ISO 8601 representation of this DateTime appropriate for use in JSON.
diff --git a/src/duration.js b/src/duration.js
index 5db8ddd8..b4bbbafc 100644
--- a/src/duration.js
+++ b/src/duration.js
@@ -766,7 +766,7 @@ export default class Duration {
     if (!this.isValid) return this;
     const negated = {};
     for (const k of Object.keys(this.values)) {
-      negated[k] = -this.values[k];
+      negated[k] = this.values[k] === 0 ? 0 : -this.values[k];
     }
     return clone(this, { values: negated }, true);
   }


Test patch:
diff --git a/test/datetime/diff.test.js b/test/datetime/diff.test.js
index 40bff295..3f0eeba2 100644
--- a/test/datetime/diff.test.js
+++ b/test/datetime/diff.test.js
@@ -146,6 +146,25 @@ test("DateTime#diff sets all its units to 0 if the duration is empty", () => {
   expect(t.diff(t, "days").toObject()).toEqual({ days: 0 });
 });
 
+test("DateTime#diff sets units to 0 if second object is slightly larger", () => {
+  expect(
+    diffObjs(
+      { year: 2017, month: 6, day: 26, hour: 21, minute: 1, second: 2, millisecond: 1 },
+      { year: 2017, month: 6, day: 26, hour: 21, minute: 1, second: 2, millisecond: 2 },
+      ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds"]
+    )
+  ).toEqual({
+    years: 0,
+    months: 0,
+    weeks: 0,
+    days: 0,
+    hours: 0,
+    minutes: 0,
+    seconds: 0,
+    milliseconds: -1,
+  });
+});
+
 test("DateTime#diff puts fractional parts in the lowest order unit", () => {
   expect(
     diffObjs({ year: 2017, month: 7, day: 14 }, { year: 2016, month: 6, day: 16 }, [
diff --git a/test/datetime/format.test.js b/test/datetime/format.test.js
index 2d4dd550..5cc76553 100644
--- a/test/datetime/format.test.js
+++ b/test/datetime/format.test.js
@@ -243,6 +243,12 @@ test("DateTime#toSQLTime() accepts an includeOffset option", () => {
   expect(dt.setZone("America/New_York").toSQLTime({ includeOffset: false })).toBe("05:23:54.123");
 });
 
+test("DateTime#toSQLTime() accepts an includeOffsetSpace option", () => {
+  expect(dt.setZone("America/New_York").toSQLTime({ includeOffsetSpace: false })).toBe(
+    "05:23:54.123-04:00"
+  );
+});
+
 test("DateTime#toSQLTime() accepts an includeZone option", () => {
   expect(dt.toUTC().toSQLTime({ includeZone: true })).toBe("09:23:54.123 UTC");
   expect(dt.setZone("America/New_York").toSQLTime({ includeZone: true })).toBe(
@@ -263,6 +269,12 @@ test("DateTime#toSQL() returns SQL date time", () => {
   expect(dt.setZone("America/New_York").toSQL()).toBe("1982-05-25 05:23:54.123 -04:00");
 });
 
+test("DateTime#toSQL() accepts space option", () => {
+  expect(dt.setZone("America/New_York").toSQL({ includeOffsetSpace: false })).toBe(
+    "1982-05-25 05:23:54.123-04:00"
+  );
+});
+
 test("DateTime#toSQL() accepts an includeOffset option", () => {
   expect(dt.toUTC().toSQL({ includeOffset: false })).toBe("1982-05-25 09:23:54.123");
   expect(dt.setZone("America/New_York").toSQL({ includeOffset: false })).toBe(