Skip to content

Commit 003ac68

Browse files
authored
Merge branch 'main' into jsdoc
2 parents 5923bc5 + 028fde7 commit 003ac68

File tree

2 files changed

+33
-41
lines changed

2 files changed

+33
-41
lines changed

.github/workflows/unit-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Unit Tests
2-
on: push
2+
on: [push, pull_request]
33
permissions: read-all
44
jobs:
55
vitest:

parse.js

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,58 @@
22
* _Times are parsed as UTC if no offset is specified_
33
*/
44
export class IsoDateParts {
5-
static DEFAULT_TIMEZONE_OFFSET = {
6-
hours: 0,
7-
minutes: 0,
8-
};
9-
105
static FULL_DATE_REGEX = /^([+-]\d{6}|\d{4})-?([01]\d)-?([0-3]\d)$/;
116
static DATETIME_REGEX = /^([+-]\d{6}|\d{4})-?([01]\d)-?([0-3]\d)[Tt ]([0-2]\d(?:[\.\,]\d+)?)(?::?([0-5]\d(?:[\.\,]\d+)?)(?::?([0-5]\d))?(?:[\.\,](\d{1,9}))?)?(Z|[+-][0-2]\d(?::?[0-5]\d)?)?$/;
127
static TIMEZONE_REGEX = /^([+-]\d{2})(?::?(\d{2}))?$/;
138
static IS_FRACTIONAL_REGEX = /^\d+[\.\,]\d+$/;
149

15-
static getTimezoneOffset(offset = "") {
16-
if(offset === "Z") {
17-
return this.DEFAULT_TIMEZONE_OFFSET;
18-
}
19-
let match = offset.match(this.TIMEZONE_REGEX);
20-
if(!match) {
21-
return this.DEFAULT_TIMEZONE_OFFSET;
22-
}
10+
static getTimezoneOffset(offset = "Z") {
11+
let [, hours = "0", minutes = "0"] = offset.match(this.TIMEZONE_REGEX) ?? [];
2312

24-
let [hours, minutes] = [match[1], match[2]];
25-
let sign = hours[0] === '-' ? -1 : 1;
13+
let sign = hours[0] === '-' ? -1 : 1;
2614
return {
27-
hours: parseInt(hours, 10) || 0,
28-
minutes: (parseInt(minutes, 10) || 0) * sign
15+
hours: parseInt(hours, 10),
16+
minutes: parseInt(minutes, 10) * sign
2917
};
3018
}
3119

3220
/** @param {RegExpMatchArray} match */
33-
static getByDateTime(match) {
34-
let offset = this.getTimezoneOffset(match[8]);
21+
static getByDateTime(
22+
_, // full match
23+
year = "",
24+
month = "0", // 0-indexed default
25+
day = "1", // 1-indexed default
26+
hours = "0",
27+
minutes = "0",
28+
seconds = "0",
29+
milliseconds = "0",
30+
timezone = "Z",
31+
) {
32+
let offset = this.getTimezoneOffset(timezone);
3533

3634
return {
37-
year: parseInt(match[1], 10),
38-
month: match[2] ? parseInt(match[2], 10) - 1 : 0,
39-
day: match[3] ? parseInt(match[3], 10) : 1, // 1-indexed default
40-
hours: (match[4] ? parseInt(match[4], 10) : 0) - offset.hours,
41-
minutes: (match[5] ? parseInt(match[5], 10) : 0) - offset.minutes,
42-
seconds: match[6] ? parseInt(match[6], 10) : 0,
35+
year: parseInt(year, 10),
36+
month: parseInt(month, 10) - 1,
37+
day: parseInt(day, 10),
38+
hours: parseInt(hours, 10) - offset.hours,
39+
minutes: parseInt(minutes, 10) - offset.minutes,
40+
seconds: parseInt(seconds, 10),
4341
// may include extra precision but we only count the first 3 digits for milliseconds
44-
milliseconds: match[7] ? parseInt(match[7].slice(0, 3), 10) : 0,
42+
milliseconds: parseInt(milliseconds.slice(0, 3), 10),
4543
};
4644
}
4745

48-
/** @param {string} str An [RFC 9557](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime#rfc_9557_format)-compatible string */
49-
static getParts(str) {
50-
let dateMatch = str.match(this.FULL_DATE_REGEX);
51-
if(dateMatch) {
52-
return this.getByDateTime(dateMatch);
46+
/** @param {string} str An [RFC 9557](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime#rfc_9557_format)-compatible string */
47+
static getParts(str = "") {
48+
let dateTimeMatch = str.match(this.FULL_DATE_REGEX) ?? str.match(this.DATETIME_REGEX);
49+
if(!dateTimeMatch) {
50+
throw new Error(`Unsupported date format: ${str}`);
5351
}
54-
55-
let dateTimeMatch = str.match(this.DATETIME_REGEX);
56-
if(dateTimeMatch) {
57-
if(dateTimeMatch[4]?.match(this.IS_FRACTIONAL_REGEX) || dateTimeMatch[5]?.match(this.IS_FRACTIONAL_REGEX)) {
58-
throw new Error(`Unsupported date format (fractional hours or minutes): ${str}`);
59-
}
60-
61-
return this.getByDateTime(dateTimeMatch);
52+
if(dateTimeMatch.slice(4,6).some(part => !!part?.match(this.IS_FRACTIONAL_REGEX))) {
53+
throw new Error(`Unsupported date format (fractional hours or minutes): ${str}`);
6254
}
6355

64-
throw new Error(`Unsupported date format: ${str}`);
56+
return this.getByDateTime(...dateTimeMatch);
6557
}
6658
}
6759

0 commit comments

Comments
 (0)