Comparing version 1.25.0 to 1.26.0
# Changelog | ||
## 1.26.0 | ||
* Add fromISOTime, toISOTime and toMillis to Duration (#803) | ||
* Fix padding of negative years in IsoDate (#871) | ||
* Fix hasSame unit comparison (#798) | ||
* Export VERSION information (#794) | ||
* Durations are considered equal with extra zero units. Fixes #809 (#811) | ||
## 1.25.0 | ||
@@ -4,0 +12,0 @@ |
{ | ||
"name": "luxon", | ||
"version": "1.25.0", | ||
"version": "1.26.0", | ||
"description": "Immutable date wrapper", | ||
@@ -71,3 +71,3 @@ "author": "Isaac Cambron", | ||
"rollup-plugin-babel-minify": "^6.2.0", | ||
"uglify-js": "^3.9.0" | ||
"uglify-es": "^3.3.9" | ||
}, | ||
@@ -74,0 +74,0 @@ "main": "build/node/luxon.js", |
@@ -5,6 +5,6 @@ # Luxon | ||
Luxon is a library for working with dates and times in Javascript. | ||
Luxon is a library for working with dates and times in JavaScript. | ||
```js | ||
DateTime.local().setZone('America/New_York').minus({ weeks: 1 }).endOf('day').toISO(); | ||
DateTime.now().setZone("America/New_York").minus({ weeks: 1 }).endOf("day").toISO(); | ||
``` | ||
@@ -11,0 +11,0 @@ |
@@ -5,3 +5,3 @@ import { InvalidArgumentError, InvalidDurationError, InvalidUnitError } from "./errors.js"; | ||
import Locale from "./impl/locale.js"; | ||
import { parseISODuration } from "./impl/regexParser.js"; | ||
import { parseISODuration, parseISOTimeOnly } from "./impl/regexParser.js"; | ||
import { | ||
@@ -220,3 +220,3 @@ asNumber, | ||
/** | ||
* Create a Duration from a Javascript object with keys like 'years' and 'hours. | ||
* Create a Duration from a JavaScript object with keys like 'years' and 'hours. | ||
* If this object is empty then a zero milliseconds duration is returned. | ||
@@ -282,2 +282,27 @@ * @param {Object} obj - the object to create the DateTime from | ||
/** | ||
* Create a Duration from an ISO 8601 time string. | ||
* @param {string} text - text to parse | ||
* @param {Object} opts - options for parsing | ||
* @param {string} [opts.locale='en-US'] - the locale to use | ||
* @param {string} opts.numberingSystem - the numbering system to use | ||
* @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use | ||
* @see https://en.wikipedia.org/wiki/ISO_8601#Times | ||
* @example Duration.fromISOTime('11:22:33.444').toObject() //=> { hours: 11, minutes: 22, seconds: 33, milliseconds: 444 } | ||
* @example Duration.fromISOTime('11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } | ||
* @example Duration.fromISOTime('T11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } | ||
* @example Duration.fromISOTime('1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } | ||
* @example Duration.fromISOTime('T1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } | ||
* @return {Duration} | ||
*/ | ||
static fromISOTime(text, opts) { | ||
const [parsed] = parseISOTimeOnly(text); | ||
if (parsed) { | ||
const obj = Object.assign(parsed, opts); | ||
return Duration.fromObject(obj); | ||
} else { | ||
return Duration.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`); | ||
} | ||
} | ||
/** | ||
* Create an invalid Duration. | ||
@@ -389,3 +414,3 @@ * @param {string} reason - simple string of why this datetime is invalid. Should not contain parameters or anything else data-dependent | ||
/** | ||
* Returns a Javascript object with this Duration's values. | ||
* Returns a JavaScript object with this Duration's values. | ||
* @param opts - options for generating the object | ||
@@ -441,2 +466,54 @@ * @param {boolean} [opts.includeConfig=false] - include configuration attributes in the output | ||
/** | ||
* Returns an ISO 8601-compliant string representation of this Duration, formatted as a time of day. | ||
* Note that this will return null if the duration is invalid, negative, or equal to or greater than 24 hours. | ||
* @see https://en.wikipedia.org/wiki/ISO_8601#Times | ||
* @param {Object} opts - options | ||
* @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 | ||
* @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 | ||
* @param {boolean} [opts.includePrefix=false] - include the `T` prefix | ||
* @param {string} [opts.format='extended'] - choose between the basic and extended format | ||
* @example Duration.fromObject({ hours: 11 }).toISOTime() //=> '11:00:00.000' | ||
* @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressMilliseconds: true }) //=> '11:00:00' | ||
* @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressSeconds: true }) //=> '11:00' | ||
* @example Duration.fromObject({ hours: 11 }).toISOTime({ includePrefix: true }) //=> 'T11:00:00.000' | ||
* @example Duration.fromObject({ hours: 11 }).toISOTime({ format: 'basic' }) //=> '110000.000' | ||
* @return {string} | ||
*/ | ||
toISOTime(opts = {}) { | ||
if (!this.isValid) return null; | ||
const millis = this.toMillis(); | ||
if (millis < 0 || millis >= 86400000) return null; | ||
opts = Object.assign( | ||
{ | ||
suppressMilliseconds: false, | ||
suppressSeconds: false, | ||
includePrefix: false, | ||
format: "extended" | ||
}, | ||
opts | ||
); | ||
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; | ||
} | ||
/** | ||
* Returns an ISO 8601 representation of this Duration appropriate for use in JSON. | ||
@@ -461,3 +538,3 @@ * @return {string} | ||
*/ | ||
valueOf() { | ||
toMillis() { | ||
return this.as("milliseconds"); | ||
@@ -467,2 +544,10 @@ } | ||
/** | ||
* Returns an milliseconds value of this Duration. Alias of {@link toMillis} | ||
* @return {number} | ||
*/ | ||
valueOf() { | ||
return this.toMillis(); | ||
} | ||
/** | ||
* Make this Duration longer by the specified amount. Return a newly-constructed Duration. | ||
@@ -772,4 +857,10 @@ * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() | ||
function eq(v1, v2) { | ||
// Consider 0 and undefined as equal | ||
if (v1 === undefined || v1 === 0) return v2 === undefined || v2 === 0; | ||
return v1 === v2; | ||
} | ||
for (const u of orderedUnits) { | ||
if (this.values[u] !== other.values[u]) { | ||
if (!eq(this.values[u], other.values[u])) { | ||
return false; | ||
@@ -776,0 +867,0 @@ } |
@@ -16,2 +16,3 @@ import Duration from "../duration.js"; | ||
["years", (a, b) => b.year - a.year], | ||
["quarters", (a, b) => b.quarter - a.quarter], | ||
["months", (a, b) => b.month - a.month + (b.year - a.year) * 12], | ||
@@ -18,0 +19,0 @@ [ |
@@ -169,3 +169,3 @@ import * as English from "./english.js"; | ||
tokenToString = token => { | ||
// Where possible: http://cldr.unicode.org/translation/date-time#TOC-Stand-Alone-vs.-Format-Styles | ||
// Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles | ||
switch (token) { | ||
@@ -172,0 +172,0 @@ // ms |
@@ -186,16 +186,24 @@ import { hasFormatToParts, hasIntl, padStart, roundTo, hasRelative } from "./util.js"; | ||
if (dt.zone.universal && this.hasIntl) { | ||
// Chromium doesn't support fixed-offset zones like Etc/GMT+8 in its formatter, | ||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=364374. | ||
// So we have to make do. Two cases: | ||
// 1. The format options tell us to show the zone. We can't do that, so the best | ||
// we can do is format the date in UTC. | ||
// 2. The format options don't tell us to show the zone. Then we can adjust them | ||
// the time and tell the formatter to show it to us in UTC, so that the time is right | ||
// and the bad zone doesn't show up. | ||
// We can clean all this up when Chrome fixes this. | ||
z = "UTC"; | ||
if (opts.timeZoneName) { | ||
// UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like. | ||
// That is why fixed-offset TZ is set to that unless it is: | ||
// 1. Outside of the supported range Etc/GMT-14 to Etc/GMT+12. | ||
// 2. Not a whole hour, e.g. UTC+4:30. | ||
const gmtOffset = -1 * (dt.offset / 60); | ||
if (gmtOffset >= -14 && gmtOffset <= 12 && gmtOffset % 1 === 0) { | ||
z = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`; | ||
this.dt = dt; | ||
} else { | ||
this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000); | ||
// Not all fixed-offset zones like Etc/+4:30 are present in tzdata. | ||
// So we have to make do. Two cases: | ||
// 1. The format options tell us to show the zone. We can't do that, so the best | ||
// we can do is format the date in UTC. | ||
// 2. The format options don't tell us to show the zone. Then we can adjust them | ||
// the time and tell the formatter to show it to us in UTC, so that the time is right | ||
// and the bad zone doesn't show up. | ||
z = "UTC"; | ||
if (opts.timeZoneName) { | ||
this.dt = dt; | ||
} else { | ||
this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000); | ||
} | ||
} | ||
@@ -422,3 +430,3 @@ } else if (dt.zone.type === "local") { | ||
// This is utter bullshit. Different calendars are going to define eras totally differently. What I need is the minimum set of dates | ||
// This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates | ||
// to definitely enumerate them. | ||
@@ -425,0 +433,0 @@ if (!this.eraCache[length]) { |
@@ -100,6 +100,6 @@ import { | ||
const item = { | ||
hour: int(match, cursor, 0), | ||
minute: int(match, cursor + 1, 0), | ||
second: int(match, cursor + 2, 0), | ||
millisecond: parseMillis(match[cursor + 3]) | ||
hours: int(match, cursor, 0), | ||
minutes: int(match, cursor + 1, 0), | ||
seconds: int(match, cursor + 2, 0), | ||
milliseconds: parseMillis(match[cursor + 3]) | ||
}; | ||
@@ -122,2 +122,6 @@ | ||
// ISO time parsing | ||
const isoTimeOnly = RegExp(`^T?${isoTimeBaseRegex.source}$`); | ||
// ISO duration parsing | ||
@@ -300,2 +304,8 @@ | ||
const extractISOTimeOnly = combineExtractors(extractISOTime); | ||
export function parseISOTimeOnly(s) { | ||
return parse(s, [isoTimeOnly, extractISOTimeOnly]); | ||
} | ||
const sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex); | ||
@@ -302,0 +312,0 @@ const sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex); |
@@ -102,7 +102,13 @@ /* | ||
export function padStart(input, n = 2) { | ||
if (input.toString().length < n) { | ||
return ("0".repeat(n) + input).slice(-n); | ||
const minus = input < 0 ? "-" : ""; | ||
const target = minus ? input * -1 : input; | ||
let result; | ||
if (target.toString().length < n) { | ||
result = ("0".repeat(n) + target).slice(-n); | ||
} else { | ||
return input.toString(); | ||
result = target.toString(); | ||
} | ||
return `${minus}${result}`; | ||
} | ||
@@ -109,0 +115,0 @@ |
@@ -19,3 +19,3 @@ import DateTime from "./datetime.js"; | ||
static hasDST(zone = Settings.defaultZone) { | ||
const proto = DateTime.local() | ||
const proto = DateTime.now() | ||
.setZone(zone) | ||
@@ -22,0 +22,0 @@ .set({ month: 12 }); |
@@ -12,3 +12,6 @@ import DateTime from "./datetime.js"; | ||
const VERSION = "1.26.0"; | ||
export { | ||
VERSION, | ||
DateTime, | ||
@@ -15,0 +18,0 @@ Duration, |
@@ -7,3 +7,3 @@ import { formatOffset, parseZoneInfo, hasIntl } from "../impl/util.js"; | ||
/** | ||
* Represents the local zone for this Javascript environment. | ||
* Represents the local zone for this JavaScript environment. | ||
* @implements {Zone} | ||
@@ -10,0 +10,0 @@ */ |
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
3050799
34462