Comparing version 3.3.0 to 3.4.0
{ | ||
"name": "luxon", | ||
"version": "3.3.0", | ||
"version": "3.4.0", | ||
"description": "Immutable date wrapper", | ||
@@ -54,3 +54,3 @@ "author": "Isaac Cambron", | ||
"jest": "^29.4.3", | ||
"lint-staged": "^11.0.0", | ||
"lint-staged": "^13.2.1", | ||
"prettier": "latest", | ||
@@ -57,0 +57,0 @@ "rollup": "^2.52.7", |
@@ -40,3 +40,3 @@ # Luxon | ||
[license-image]: http://img.shields.io/badge/license-MIT-blue.svg | ||
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg | ||
[license]: LICENSE.md | ||
@@ -43,0 +43,0 @@ |
@@ -15,2 +15,3 @@ import { InvalidArgumentError, InvalidDurationError, InvalidUnitError } from "./errors.js"; | ||
import Settings from "./settings.js"; | ||
import DateTime from "./datetime.js"; | ||
@@ -129,4 +130,5 @@ const INVALID = "Invalid Duration"; | ||
function antiTrunc(n) { | ||
return n < 0 ? Math.floor(n) : Math.ceil(n); | ||
// this is needed since in some test cases it would return 0.9999999999999999 instead of 1 | ||
function removePrecisionIssue(a) { | ||
return Math.trunc(a * 1e3) / 1e3; | ||
} | ||
@@ -138,8 +140,6 @@ | ||
raw = fromMap[fromUnit] / conv, | ||
sameSign = Math.sign(raw) === Math.sign(toMap[toUnit]), | ||
// ok, so this is wild, but see the matrix in the tests | ||
added = | ||
!sameSign && toMap[toUnit] !== 0 && Math.abs(raw) <= 1 ? antiTrunc(raw) : Math.trunc(raw); | ||
toMap[toUnit] += added; | ||
fromMap[fromUnit] -= added * conv; | ||
added = Math.floor(raw); | ||
toMap[toUnit] = removePrecisionIssue(toMap[toUnit] + added); | ||
fromMap[fromUnit] = removePrecisionIssue(fromMap[fromUnit] - added * conv); | ||
} | ||
@@ -554,22 +554,7 @@ | ||
...opts, | ||
includeOffset: false, | ||
}; | ||
const value = this.shiftTo("hours", "minutes", "seconds", "milliseconds"); | ||
let fmt = opts.format === "basic" ? "hhmm" : "hh:mm"; | ||
if (!opts.suppressSeconds || value.seconds !== 0 || value.milliseconds !== 0) { | ||
fmt += opts.format === "basic" ? "ss" : ":ss"; | ||
if (!opts.suppressMilliseconds || value.milliseconds !== 0) { | ||
fmt += ".SSS"; | ||
} | ||
} | ||
let str = value.toFormat(fmt); | ||
if (opts.includePrefix) { | ||
str = "T" + str; | ||
} | ||
return str; | ||
const dateTime = DateTime.fromMillis(millis, { zone: "UTC" }); | ||
return dateTime.toISOTime(opts); | ||
} | ||
@@ -598,3 +583,9 @@ | ||
toMillis() { | ||
return this.as("milliseconds"); | ||
let sum = this.values.milliseconds ?? 0; | ||
for (let unit of reverseUnits.slice(1)) { | ||
if (this.values?.[unit]) { | ||
sum += this.values[unit] * this.matrix[unit]["milliseconds"]; | ||
} | ||
} | ||
return sum; | ||
} | ||
@@ -716,4 +707,7 @@ | ||
const vals = this.toObject(); | ||
normalizeValues(this.matrix, vals); | ||
return clone(this, { values: vals }, true); | ||
if (this.valueOf() >= 0) { | ||
normalizeValues(this.matrix, vals); | ||
return clone(this, { values: vals }, true); | ||
} | ||
return this.negate().normalize().negate(); | ||
} | ||
@@ -720,0 +714,0 @@ |
@@ -28,2 +28,10 @@ import Duration from "../duration.js"; | ||
/* This loop tries to diff using larger units first. | ||
If we overshoot, we backtrack and try the next smaller unit. | ||
"cursor" starts out at the earlier timestamp and moves closer and closer to "later" | ||
as we use smaller and smaller units. | ||
highWater keeps track of where we would be if we added one more of the smallest unit, | ||
this is used later to potentially convert any difference smaller than the smallest higher order unit | ||
into a fraction of that smallest higher order unit | ||
*/ | ||
for (const [unit, differ] of differs) { | ||
@@ -37,4 +45,16 @@ if (units.indexOf(unit) >= 0) { | ||
if (highWater > later) { | ||
// we overshot the end point, backtrack cursor by 1 | ||
results[unit]--; | ||
cursor = earlier.plus(results); | ||
// if we are still overshooting now, we need to backtrack again | ||
// this happens in certain situations when diffing times in different zones, | ||
// because this calculation ignores time zones | ||
if (cursor > later) { | ||
// keep the "overshot by 1" around as highWater | ||
highWater = cursor; | ||
// backtrack cursor by 1 | ||
results[unit]--; | ||
cursor = earlier.plus(results); | ||
} | ||
} else { | ||
@@ -41,0 +61,0 @@ cursor = highWater; |
@@ -104,20 +104,21 @@ import * as English from "./english.js"; | ||
formatDateTime(dt, opts = {}) { | ||
const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); | ||
return df.format(); | ||
dtFormatter(dt, opts = {}) { | ||
return this.loc.dtFormatter(dt, { ...this.opts, ...opts }); | ||
} | ||
formatDateTimeParts(dt, opts = {}) { | ||
const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); | ||
return df.formatToParts(); | ||
formatDateTime(dt, opts) { | ||
return this.dtFormatter(dt, opts).format(); | ||
} | ||
formatInterval(interval, opts = {}) { | ||
const df = this.loc.dtFormatter(interval.start, { ...this.opts, ...opts }); | ||
formatDateTimeParts(dt, opts) { | ||
return this.dtFormatter(dt, opts).formatToParts(); | ||
} | ||
formatInterval(interval, opts) { | ||
const df = this.dtFormatter(interval.start, opts); | ||
return df.dtf.formatRange(interval.start.toJSDate(), interval.end.toJSDate()); | ||
} | ||
resolvedOptions(dt, opts = {}) { | ||
const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); | ||
return df.resolvedOptions(); | ||
resolvedOptions(dt, opts) { | ||
return this.dtFormatter(dt, opts).resolvedOptions(); | ||
} | ||
@@ -177,3 +178,3 @@ | ||
tokenToString = (token) => { | ||
// Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles | ||
// Where possible: https://cldr.unicode.org/translation/date-time/date-time-symbols | ||
switch (token) { | ||
@@ -180,0 +181,0 @@ // ms |
@@ -123,3 +123,3 @@ import { padStart, roundTo, hasRelative, formatOffset } from "./util.js"; | ||
for (let i = 1; i <= 12; i++) { | ||
const dt = DateTime.utc(2016, i, 1); | ||
const dt = DateTime.utc(2009, i, 1); | ||
ms.push(f(dt)); | ||
@@ -139,4 +139,4 @@ } | ||
function listStuff(loc, length, defaultOK, englishFn, intlFn) { | ||
const mode = loc.listingMode(defaultOK); | ||
function listStuff(loc, length, englishFn, intlFn) { | ||
const mode = loc.listingMode(); | ||
@@ -393,4 +393,4 @@ if (mode === "error") { | ||
months(length, format = false, defaultOK = true) { | ||
return listStuff(this, length, defaultOK, English.months, () => { | ||
months(length, format = false) { | ||
return listStuff(this, length, English.months, () => { | ||
const intl = format ? { month: length, day: "numeric" } : { month: length }, | ||
@@ -405,4 +405,4 @@ formatStr = format ? "format" : "standalone"; | ||
weekdays(length, format = false, defaultOK = true) { | ||
return listStuff(this, length, defaultOK, English.weekdays, () => { | ||
weekdays(length, format = false) { | ||
return listStuff(this, length, English.weekdays, () => { | ||
const intl = format | ||
@@ -421,7 +421,6 @@ ? { weekday: length, year: "numeric", month: "long", day: "numeric" } | ||
meridiems(defaultOK = true) { | ||
meridiems() { | ||
return listStuff( | ||
this, | ||
undefined, | ||
defaultOK, | ||
() => English.meridiems, | ||
@@ -443,4 +442,4 @@ () => { | ||
eras(length, defaultOK = true) { | ||
return listStuff(this, length, defaultOK, English.eras, () => { | ||
eras(length) { | ||
return listStuff(this, length, English.eras, () => { | ||
const intl = { era: length }; | ||
@@ -447,0 +446,0 @@ |
@@ -56,2 +56,6 @@ import { parseMillis, isUndefined, untruncateYear, signedOffset, hasOwnProperty } from "./util.js"; | ||
/** | ||
* @param token | ||
* @param {Locale} loc | ||
*/ | ||
function unitForToken(token, loc) { | ||
@@ -77,5 +81,5 @@ const one = digitRegex(loc), | ||
case "G": | ||
return oneOf(loc.eras("short", false), 0); | ||
return oneOf(loc.eras("short"), 0); | ||
case "GG": | ||
return oneOf(loc.eras("long", false), 0); | ||
return oneOf(loc.eras("long"), 0); | ||
// years | ||
@@ -98,5 +102,5 @@ case "y": | ||
case "MMM": | ||
return oneOf(loc.months("short", true, false), 1); | ||
return oneOf(loc.months("short", true), 1); | ||
case "MMMM": | ||
return oneOf(loc.months("long", true, false), 1); | ||
return oneOf(loc.months("long", true), 1); | ||
case "L": | ||
@@ -107,5 +111,5 @@ return intUnit(oneOrTwo); | ||
case "LLL": | ||
return oneOf(loc.months("short", false, false), 1); | ||
return oneOf(loc.months("short", false), 1); | ||
case "LLLL": | ||
return oneOf(loc.months("long", false, false), 1); | ||
return oneOf(loc.months("long", false), 1); | ||
// dates | ||
@@ -170,9 +174,9 @@ case "d": | ||
case "EEE": | ||
return oneOf(loc.weekdays("short", false, false), 1); | ||
return oneOf(loc.weekdays("short", false), 1); | ||
case "EEEE": | ||
return oneOf(loc.weekdays("long", false, false), 1); | ||
return oneOf(loc.weekdays("long", false), 1); | ||
case "ccc": | ||
return oneOf(loc.weekdays("short", true, false), 1); | ||
return oneOf(loc.weekdays("short", true), 1); | ||
case "cccc": | ||
return oneOf(loc.weekdays("long", true, false), 1); | ||
return oneOf(loc.weekdays("long", true), 1); | ||
// offset/zone | ||
@@ -227,6 +231,10 @@ case "Z": | ||
dayPeriod: "a", | ||
hour: { | ||
hour12: { | ||
numeric: "h", | ||
"2-digit": "hh", | ||
}, | ||
hour24: { | ||
numeric: "H", | ||
"2-digit": "HH", | ||
}, | ||
minute: { | ||
@@ -246,3 +254,3 @@ numeric: "m", | ||
function tokenForPart(part, formatOpts) { | ||
function tokenForPart(part, formatOpts, resolvedOpts) { | ||
const { type, value } = part; | ||
@@ -260,3 +268,22 @@ | ||
let val = partTypeStyleToTokenVal[type]; | ||
// The user might have explicitly specified hour12 or hourCycle | ||
// if so, respect their decision | ||
// if not, refer back to the resolvedOpts, which are based on the locale | ||
let actualType = type; | ||
if (type === "hour") { | ||
if (formatOpts.hour12 != null) { | ||
actualType = formatOpts.hour12 ? "hour12" : "hour24"; | ||
} else if (formatOpts.hourCycle != null) { | ||
if (formatOpts.hourCycle === "h11" || formatOpts.hourCycle === "h12") { | ||
actualType = "hour12"; | ||
} else { | ||
actualType = "hour24"; | ||
} | ||
} else { | ||
// tokens only differentiate between 24 hours or not, | ||
// so we do not need to check hourCycle here, which is less supported anyways | ||
actualType = resolvedOpts.hour12 ? "hour12" : "hour24"; | ||
} | ||
} | ||
let val = partTypeStyleToTokenVal[actualType]; | ||
if (typeof val === "object") { | ||
@@ -450,4 +477,6 @@ val = val[style]; | ||
const formatter = Formatter.create(locale, formatOpts); | ||
const parts = formatter.formatDateTimeParts(getDummyDateTime()); | ||
return parts.map((p) => tokenForPart(p, formatOpts)); | ||
const df = formatter.dtFormatter(getDummyDateTime()); | ||
const parts = df.formatToParts(); | ||
const resolvedOpts = df.resolvedOptions(); | ||
return parts.map((p) => tokenForPart(p, formatOpts, resolvedOpts)); | ||
} |
@@ -154,3 +154,3 @@ /* | ||
// covert a calendar object to a local timestamp (epoch, but with the offset baked in) | ||
// convert a calendar object to a local timestamp (epoch, but with the offset baked in) | ||
export function objToLocalTS(obj) { | ||
@@ -157,0 +157,0 @@ let d = Date.UTC( |
@@ -27,3 +27,3 @@ /** | ||
return FixedOffsetZone.instance(input); | ||
} else if (typeof input === "object" && input.offset && typeof input.offset === "number") { | ||
} else if (typeof input === "object" && "offset" in input && typeof input.offset === "function") { | ||
// This is dumb, but the instanceof check above doesn't seem to really work | ||
@@ -30,0 +30,0 @@ // so we're duck checking it |
@@ -12,3 +12,3 @@ import DateTime from "./datetime.js"; | ||
const VERSION = "3.3.0"; | ||
const VERSION = "3.4.0"; | ||
@@ -15,0 +15,0 @@ export { |
{ | ||
"type": "module", | ||
"version": "3.3.0" | ||
"version": "3.4.0" | ||
} |
@@ -115,6 +115,6 @@ import SystemZone from "./zones/systemZone.js"; | ||
* @type {number} | ||
* @example Settings.twoDigitCutoffYear = 0 // cut-off year is 0, so all 'yy' are interpretted as current century | ||
* @example Settings.twoDigitCutoffYear = 0 // cut-off year is 0, so all 'yy' are interpreted as current century | ||
* @example Settings.twoDigitCutoffYear = 50 // '49' -> 1949; '50' -> 2050 | ||
* @example Settings.twoDigitCutoffYear = 1950 // interpretted as 50 | ||
* @example Settings.twoDigitCutoffYear = 2050 // ALSO interpretted as 50 | ||
* @example Settings.twoDigitCutoffYear = 1950 // interpreted as 50 | ||
* @example Settings.twoDigitCutoffYear = 2050 // ALSO interpreted as 50 | ||
*/ | ||
@@ -121,0 +121,0 @@ static set twoDigitCutoffYear(cutoffYear) { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4063463
42397