Skip to content

Commit

Permalink
update precision pull request
Browse files Browse the repository at this point in the history
  • Loading branch information
dobon committed Dec 5, 2024
1 parent 3e9983c commit a3e57dd
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 17 deletions.
60 changes: 43 additions & 17 deletions src/datetime.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ import Invalid from "./impl/invalid.js";

const INVALID = "Invalid DateTime";
const MAX_DATE = 8.64e15;
const Precision = {
hours: 1,
minutes: 2,
seconds: 3,
milliseconds: 4,
};

function unsupportedZone(zone) {
return new Invalid("unsupported zone", `the zone "${zone.name}" is not supported`);
Expand Down Expand Up @@ -238,25 +244,30 @@ function toISOTime(
suppressSeconds,
suppressMilliseconds,
includeOffset,
extendedZone
extendedZone,
precision
) {
let desiredPrecision = Precision[normalizeUnit(precision)];
if (desiredPrecision === undefined) throw new InvalidUnitError(precision);

let c = padStart(o.c.hour);
if (extended) {
c += ":";
c += padStart(o.c.minute);
if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) {
c += ":";
}
} else {
if (desiredPrecision >= Precision.minutes) {
if (extended) c += ":";
c += padStart(o.c.minute);
}

if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) {
c += padStart(o.c.second);

if (o.c.millisecond !== 0 || !suppressMilliseconds) {
c += ".";
c += padStart(o.c.millisecond, 3);
if (
desiredPrecision >= Precision.seconds &&
!(suppressSeconds && o.c.millisecond === 0 && o.c.second === 0)
) {
if (extended) c += ":";
c += padStart(o.c.second);

if (
desiredPrecision >= Precision.milliseconds &&
!(suppressMilliseconds && o.c.millisecond === 0)
) {
c += "." + padStart(o.c.millisecond, 3);
}
}
}

Expand Down Expand Up @@ -1819,10 +1830,12 @@ export default class DateTime {
* @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
* @param {string} [opts.precision='milliseconds'] - specify desired time precision: 'hours', 'minutes', 'seconds' or 'milliseconds'
* @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'
* @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400'
* @example DateTime.now().toISO({ precision: 'minute' }) //=> '2017-04-22T20:47Z'
* @return {string|null}
*/
toISO({
Expand All @@ -1831,6 +1844,7 @@ export default class DateTime {
suppressMilliseconds = false,
includeOffset = true,
extendedZone = false,
precision = "milliseconds",
} = {}) {
if (!this.isValid) {
return null;
Expand All @@ -1840,7 +1854,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,
precision
);
return c;
}

Expand Down Expand Up @@ -1878,10 +1900,12 @@ export default class DateTime {
* @param {boolean} [opts.extendedZone=true] - add the time zone format extension
* @param {boolean} [opts.includePrefix=false] - include the `T` prefix
* @param {string} [opts.format='extended'] - choose between the basic and extended format
* @param {string} [opts.precision='milliseconds'] - specify desired time precision: 'hours', 'minutes', 'seconds' or 'milliseconds'
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z'
* @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z'
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z'
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z'
* @example DateTime.utc().set({ hour: 7, minute: 34, second: 56 }).toISOTime({ precision: 'minute' }) //=> '07:34Z'
* @return {string}
*/
toISOTime({
Expand All @@ -1891,6 +1915,7 @@ export default class DateTime {
includePrefix = false,
extendedZone = false,
format = "extended",
precision = "milliseconds",
} = {}) {
if (!this.isValid) {
return null;
Expand All @@ -1905,7 +1930,8 @@ export default class DateTime {
suppressSeconds,
suppressMilliseconds,
includeOffset,
extendedZone
extendedZone,
precision
)
);
}
Expand Down
30 changes: 30 additions & 0 deletions test/datetime/format.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* global test expect */

import { DateTime, Zone, FixedOffsetZone } from "../../src/luxon";
import { InvalidUnitError } from "../../src/errors";

const dtMaker = () =>
DateTime.fromObject(
Expand Down Expand Up @@ -261,6 +262,35 @@ test("DateTime#toISOTime() returns null for invalid DateTimes", () => {
expect(invalid.toISOTime()).toBe(null);
});

test("DateTime#toISOTime({precision}) truncates time to desired precision", () => {
expect(dt.toISOTime({ precision: "millisecond" })).toBe("09:23:54.123Z");
expect(dt.toISOTime({ precision: "second" })).toBe("09:23:54Z");
expect(dt.toISOTime({ precision: "minute" })).toBe("09:23Z");
expect(dt.toISOTime({ precision: "hours" })).toBe("09Z");
});

test("DateTime#toISOTime({precision}) throws when the precision is invalid", () => {
expect(() => dt.toISOTime({ precision: "ms" })).toThrow(InvalidUnitError);
expect(() => dt.toISOTime({ precision: "xxx" })).toThrow(InvalidUnitError);
expect(() => dt.toISOTime({ precision: null })).toThrow(InvalidUnitError);
expect(() => dt.toISOTime({ precision: "days" })).toThrow(InvalidUnitError);
expect(() => dt.toISOTime({ precision: "months" })).toThrow(InvalidUnitError);
expect(() => dt.toISOTime({ precision: "years" })).toThrow(InvalidUnitError);
});

test("DateTime#toISOTime({precision, suppressSeconds}) precision takes precedence", () => {
const dt2 = dt.set({ second: 0, millisecond: 0 });
expect(dt2.toISOTime({ precision: "minute", suppressSeconds: true })).toBe("09:23Z");
expect(dt2.toISOTime({ precision: "second", suppressSeconds: true })).toBe("09:23Z");
expect(dt2.toISOTime({ precision: "millisecond", suppressSeconds: true })).toBe("09:23Z");
});

test("DateTime#toISOTime({precision, suppressMilliseconds}) supress", () => {
expect(
dt.set({ millisecond: 0 }).toISOTime({ precision: "millisecond", suppressMilliseconds: true })
).toBe("09:23:54Z");
});

//------
// #toRFC2822()
//------
Expand Down

0 comments on commit a3e57dd

Please sign in to comment.