diff --git a/src/datetime.js b/src/datetime.js index 902790945..f70950b7d 100644 --- a/src/datetime.js +++ b/src/datetime.js @@ -218,23 +218,32 @@ function toISOTime( suppressSeconds, suppressMilliseconds, includeOffset, - extendedZone + extendedZone, + truncateMilliseconds, ) { let c = padStart(o.c.hour); + + const includeMilliseconds = + (o.c.millisecond !== 0 && !truncateMilliseconds) || + ((o.c.second !== 0 || !suppressSeconds) && !suppressMilliseconds && !truncateMilliseconds); + + const includeSeconds = includeMilliseconds || o.c.second !== 0 || !suppressSeconds; + if (extended) { c += ":"; c += padStart(o.c.minute); - if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) { + + if (includeSeconds) { c += ":"; } } else { c += padStart(o.c.minute); } - if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) { + if (includeSeconds) { c += padStart(o.c.second); - if (o.c.millisecond !== 0 || !suppressMilliseconds) { + if (includeMilliseconds) { c += "."; c += padStart(o.c.millisecond, 3); } @@ -1627,11 +1636,12 @@ export default class DateTime { /** * Returns an ISO 8601-compliant string representation of this DateTime * @param {Object} opts - options - * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 + * @param {string} [opts.format='extended'] - choose between the basic and extended format * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 + * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 + * @param {boolean} [opts.truncateMilliseconds=false] - truncate the milliseconds from the format, irrespective of their value * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' * @param {boolean} [opts.extendedZone=false] - add the time zone format extension - * @param {string} [opts.format='extended'] - choose between the basic and extended format * @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z' * @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00' * @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335' @@ -1644,6 +1654,7 @@ export default class DateTime { suppressMilliseconds = false, includeOffset = true, extendedZone = false, + truncateMilliseconds = false, } = {}) { if (!this.isValid) { return null; @@ -1653,7 +1664,15 @@ export default class DateTime { let c = toISODate(this, ext); c += "T"; - c += toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone); + c += toISOTime( + this, + ext, + suppressSeconds, + suppressMilliseconds, + includeOffset, + extendedZone, + truncateMilliseconds, + ); return c; } @@ -1704,6 +1723,7 @@ export default class DateTime { includePrefix = false, extendedZone = false, format = "extended", + truncateMilliseconds = false, } = {}) { if (!this.isValid) { return null; @@ -1718,7 +1738,8 @@ export default class DateTime { suppressSeconds, suppressMilliseconds, includeOffset, - extendedZone + extendedZone, + truncateMilliseconds, ) ); } diff --git a/test/datetime/format.test.js b/test/datetime/format.test.js index 66ef19e5b..589c448c2 100644 --- a/test/datetime/format.test.js +++ b/test/datetime/format.test.js @@ -104,6 +104,33 @@ test("DateTime#toISO() suppresses [milli]seconds", () => { ); }); +test("DateTime#toISO() truncates [milli]seconds", () => { + const truncateMilliseconds = { truncateMilliseconds: true }; + expect(dt.toISO(truncateMilliseconds)).toBe("1982-05-25T09:23:54Z"); + expect(dt.set({ millisecond: 0 }).toISO(truncateMilliseconds)).toBe("1982-05-25T09:23:54Z"); + + const noZeroSeconds = { + suppressSeconds: true, + suppressMilliseconds: true, + truncateMilliseconds: true, + }; + expect(dt.set({ seconds: 0 }).toISO(noZeroSeconds)).toBe("1982-05-25T09:23Z"); + 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"); + + const suppressOnlySeconds = { suppressSeconds: true }; + expect(dt.set({ seconds: 0 }).toISO(suppressOnlySeconds)).toBe("1982-05-25T09:23:00.123Z"); + expect(dt.set({ seconds: 0, milliseconds: 0 }).toISO(suppressOnlySeconds)).toBe( + "1982-05-25T09:23Z" + ); + + const suppressMillisecondsOnly = { suppressMilliseconds: true }; + expect(dt.toISO(suppressMillisecondsOnly)).toBe("1982-05-25T09:23:54.123Z"); + expect(dt.set({ seconds: 0, milliseconds: 0 }).toISO(suppressMillisecondsOnly)).toBe( + "1982-05-25T09:23:00Z" + ); +}); + test("DateTime#toISO() returns null for invalid DateTimes", () => { expect(invalid.toISO()).toBe(null); }); @@ -221,6 +248,10 @@ test("DateTime#toISOTime() won't suppress milliseconds by default", () => { expect(dt.startOf("second").toISOTime()).toBe("09:23:54.000Z"); }); +test("DateTime#toISOTime() won't truncate milliseconds by default", () => { + expect(dt.toISOTime()).toBe("09:23:54.123Z"); +}); + test("DateTime#toISOTime({suppressMilliseconds: true}) won't suppress milliseconds if they're nonzero", () => { expect(dt.toISOTime({ suppressMilliseconds: true })).toBe("09:23:54.123Z"); }); @@ -229,6 +260,14 @@ test("DateTime#toISOTime({suppressMilliseconds: true}) will suppress millisecond expect(dt.set({ millisecond: 0 }).toISOTime({ suppressMilliseconds: true })).toBe("09:23:54Z"); }); +test("DateTime#toISOTime({truncateMilliseconds: true}) will truncate milliseconds if value is not zero", () => { + expect(dt.toISOTime({ truncateMilliseconds: true })).toBe("09:23:54Z"); +}); + +test("DateTime#toISOTime({truncateMilliseconds: true}) will truncate milliseconds if value is zero", () => { + expect(dt.set({ millisecond: 0 }).toISOTime({ truncateMilliseconds: true })).toBe("09:23:54Z"); +}); + test("DateTime#toISOTime({suppressSeconds: true}) won't suppress milliseconds if they're nonzero", () => { expect(dt.toISOTime({ suppressSeconds: true })).toBe("09:23:54.123Z"); });