mdtg 2.1.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -10
- package/package.json +8 -4
- package/src/constants.js +55 -0
- package/src/format.js +81 -0
- package/src/index.js +8 -0
- package/src/parse.js +81 -0
- package/src/validation.js +50 -0
- package/index.js +0 -249
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MDTG
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This package converts `Date` objects to [military date time](https://en.wikipedia.org/wiki/Date-time_group) and vice versa.
|
|
4
4
|
|
|
5
5
|
### Install
|
|
6
6
|
|
|
@@ -11,16 +11,42 @@ npm install mdtg
|
|
|
11
11
|
### Usage
|
|
12
12
|
|
|
13
13
|
```js
|
|
14
|
-
import {
|
|
14
|
+
import { parse, toMDT } from "mdtg";
|
|
15
15
|
|
|
16
|
-
const
|
|
16
|
+
const date = new Date();
|
|
17
17
|
|
|
18
|
-
console.log(
|
|
19
|
-
console.log(
|
|
20
|
-
console.log(
|
|
18
|
+
console.log(toMDT(date, { form: "short" }));
|
|
19
|
+
console.log(toMDT(date, { form: "shortened" }));
|
|
20
|
+
console.log(toMDT(date, { form: "long" }));
|
|
21
21
|
|
|
22
|
-
console.log(
|
|
23
|
-
console.log(
|
|
24
|
-
console.log(
|
|
25
|
-
console.log(
|
|
22
|
+
console.log(parse("12135530Zaug24"));
|
|
23
|
+
console.log(parse("12135530Asep24"));
|
|
24
|
+
console.log(parse("121355LOCT24"));
|
|
25
|
+
console.log(parse("121355M"));
|
|
26
26
|
```
|
|
27
|
+
|
|
28
|
+
### API
|
|
29
|
+
|
|
30
|
+
#### `toMDT(date, options)`
|
|
31
|
+
|
|
32
|
+
Converts a valid `Date` to a date-time group. `date` defaults to the current
|
|
33
|
+
date. `options.form` is `"short"`, `"shortened"`, or `"long"` (the default).
|
|
34
|
+
`options.timezone` accepts the NATO time-zone letters `A` through `Z`;
|
|
35
|
+
lowercase letters are accepted and unknown values default to `Z`.
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
toMDT(new Date(Date.UTC(2024, 7, 12, 11, 55, 30)), {
|
|
39
|
+
form: "long",
|
|
40
|
+
timezone: "A",
|
|
41
|
+
});
|
|
42
|
+
// "12125530Aaug24"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### `parse(value)`
|
|
46
|
+
|
|
47
|
+
Parses short (`121155Z`), shortened (`121155Zaug24`), and long
|
|
48
|
+
(`12115530Zaug24`) formats into a `Date`. Short values use the current UTC
|
|
49
|
+
month and year. Years are interpreted as `2000` through `2099`.
|
|
50
|
+
|
|
51
|
+
Invalid calendar dates and times, such as `310224Zfeb24` or `126155Z`, throw a
|
|
52
|
+
`RangeError`. Other invalid values throw an `Error`.
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdtg",
|
|
3
|
-
"version": "
|
|
4
|
-
"main": "index.js",
|
|
3
|
+
"version": "3.0.1",
|
|
4
|
+
"main": "src/index.js",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/index.js"
|
|
8
|
+
},
|
|
6
9
|
"engines": {
|
|
7
|
-
"node": ">=
|
|
10
|
+
"node": ">=22.0.0",
|
|
11
|
+
"npm": ">=10.0.0"
|
|
8
12
|
},
|
|
9
13
|
"scripts": {
|
|
10
14
|
"bench": "vitest bench --run",
|
|
11
15
|
"coverage": "vitest run --coverage",
|
|
12
|
-
"format": "biome
|
|
16
|
+
"format": "biome check .",
|
|
13
17
|
"prelint": "npm run format && npm run prettier",
|
|
14
18
|
"lint": "biome lint .",
|
|
15
19
|
"prettier": "prettier **/*.yml",
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export const MONTHS = [
|
|
2
|
+
"jan",
|
|
3
|
+
"feb",
|
|
4
|
+
"mar",
|
|
5
|
+
"apr",
|
|
6
|
+
"may",
|
|
7
|
+
"jun",
|
|
8
|
+
"jul",
|
|
9
|
+
"aug",
|
|
10
|
+
"sep",
|
|
11
|
+
"oct",
|
|
12
|
+
"nov",
|
|
13
|
+
"dec",
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export const OFFSETS = Object.freeze({
|
|
17
|
+
Y: 12,
|
|
18
|
+
X: 11,
|
|
19
|
+
W: 10,
|
|
20
|
+
V: 9,
|
|
21
|
+
U: 8,
|
|
22
|
+
T: 7,
|
|
23
|
+
S: 6,
|
|
24
|
+
R: 5,
|
|
25
|
+
Q: 4,
|
|
26
|
+
P: 3,
|
|
27
|
+
O: 2,
|
|
28
|
+
N: 1,
|
|
29
|
+
Z: 0,
|
|
30
|
+
A: -1,
|
|
31
|
+
B: -2,
|
|
32
|
+
C: -3,
|
|
33
|
+
D: -4,
|
|
34
|
+
E: -5,
|
|
35
|
+
F: -6,
|
|
36
|
+
G: -7,
|
|
37
|
+
H: -8,
|
|
38
|
+
I: -9,
|
|
39
|
+
J: -10,
|
|
40
|
+
K: -11,
|
|
41
|
+
L: -12,
|
|
42
|
+
M: -13,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const SHORT_FORMAT_REGEX = /^[0-9]{6}[A-Z]$/;
|
|
46
|
+
export const SHORTENED_FORMAT_REGEX =
|
|
47
|
+
/^[0-9]{6}[A-Z](jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[0-9]{2}$/i;
|
|
48
|
+
export const LONG_FORMAT_REGEX =
|
|
49
|
+
/^[0-9]{8}[A-Z](jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[0-9]{2}$/i;
|
|
50
|
+
|
|
51
|
+
export const FORM = Object.freeze({
|
|
52
|
+
SHORT: "short",
|
|
53
|
+
SHORTENED: "shortened",
|
|
54
|
+
LONG: "long",
|
|
55
|
+
});
|
package/src/format.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { FORM, MONTHS, OFFSETS } from "./constants.js";
|
|
2
|
+
import {
|
|
3
|
+
isLongFormat,
|
|
4
|
+
isShortenedFormat,
|
|
5
|
+
isShortFormat,
|
|
6
|
+
validateDate,
|
|
7
|
+
validateTimezone,
|
|
8
|
+
} from "./validation.js";
|
|
9
|
+
|
|
10
|
+
const normalizeNumber = (number) => String(number).padStart(2, "0");
|
|
11
|
+
|
|
12
|
+
const createDateWithOffset = (date, offset) =>
|
|
13
|
+
new Date(date.getTime() - offset * 60 * 60 * 1000);
|
|
14
|
+
|
|
15
|
+
const buildShort = (date, timezone) => {
|
|
16
|
+
const result = [date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes()]
|
|
17
|
+
.map(normalizeNumber)
|
|
18
|
+
.concat(timezone)
|
|
19
|
+
.join("");
|
|
20
|
+
|
|
21
|
+
if (!isShortFormat(result)) {
|
|
22
|
+
throw new Error("Failed to build short MDTG");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const buildLong = (date, timezone) => {
|
|
29
|
+
const result = [
|
|
30
|
+
date.getUTCDate(),
|
|
31
|
+
date.getUTCHours(),
|
|
32
|
+
date.getUTCMinutes(),
|
|
33
|
+
date.getUTCSeconds(),
|
|
34
|
+
]
|
|
35
|
+
.map(normalizeNumber)
|
|
36
|
+
.concat(
|
|
37
|
+
timezone,
|
|
38
|
+
MONTHS[date.getUTCMonth()],
|
|
39
|
+
normalizeNumber(date.getUTCFullYear() % 100),
|
|
40
|
+
)
|
|
41
|
+
.join("");
|
|
42
|
+
|
|
43
|
+
if (!isLongFormat(result)) {
|
|
44
|
+
throw new Error("Failed to build long MDTG");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const buildShortened = (date, timezone) => {
|
|
51
|
+
const result = [
|
|
52
|
+
buildShort(date, timezone),
|
|
53
|
+
MONTHS[date.getUTCMonth()],
|
|
54
|
+
normalizeNumber(date.getUTCFullYear() % 100),
|
|
55
|
+
].join("");
|
|
56
|
+
|
|
57
|
+
if (!isShortenedFormat(result)) {
|
|
58
|
+
throw new Error("Failed to build shortened MDTG");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const toMDT = (
|
|
65
|
+
date = new Date(),
|
|
66
|
+
{ form = FORM.LONG, timezone: timezoneInput = "Z" } = {},
|
|
67
|
+
) => {
|
|
68
|
+
validateDate(date);
|
|
69
|
+
|
|
70
|
+
const timezone = validateTimezone(timezoneInput);
|
|
71
|
+
const adjustedDate = createDateWithOffset(date, OFFSETS[timezone]);
|
|
72
|
+
|
|
73
|
+
switch (form) {
|
|
74
|
+
case FORM.SHORT:
|
|
75
|
+
return buildShort(adjustedDate, timezone);
|
|
76
|
+
case FORM.SHORTENED:
|
|
77
|
+
return buildShortened(adjustedDate, timezone);
|
|
78
|
+
default:
|
|
79
|
+
return buildLong(adjustedDate, timezone);
|
|
80
|
+
}
|
|
81
|
+
};
|
package/src/index.js
ADDED
package/src/parse.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { MONTHS, OFFSETS } from "./constants.js";
|
|
2
|
+
import {
|
|
3
|
+
isLongFormat,
|
|
4
|
+
isShortenedFormat,
|
|
5
|
+
isShortFormat,
|
|
6
|
+
validateDateTime,
|
|
7
|
+
} from "./validation.js";
|
|
8
|
+
|
|
9
|
+
const parseInteger = (input) => Number.parseInt(input, 10);
|
|
10
|
+
|
|
11
|
+
const parseShort = (value) => {
|
|
12
|
+
const day = parseInteger(value.slice(0, 2));
|
|
13
|
+
const hours = parseInteger(value.slice(2, 4));
|
|
14
|
+
const minutes = parseInteger(value.slice(4, 6));
|
|
15
|
+
const timezone = value.slice(6, 7).toUpperCase();
|
|
16
|
+
const now = new Date();
|
|
17
|
+
|
|
18
|
+
validateDateTime({
|
|
19
|
+
year: now.getUTCFullYear(),
|
|
20
|
+
month: now.getUTCMonth(),
|
|
21
|
+
day,
|
|
22
|
+
hours,
|
|
23
|
+
minutes,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return new Date(
|
|
27
|
+
Date.UTC(
|
|
28
|
+
now.getUTCFullYear(),
|
|
29
|
+
now.getUTCMonth(),
|
|
30
|
+
day,
|
|
31
|
+
hours + OFFSETS[timezone],
|
|
32
|
+
minutes,
|
|
33
|
+
),
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const parseWithMonth = (value, { hasSeconds, timezoneIndex, monthStart }) => {
|
|
38
|
+
const day = parseInteger(value.slice(0, 2));
|
|
39
|
+
const hours = parseInteger(value.slice(2, 4));
|
|
40
|
+
const minutes = parseInteger(value.slice(4, 6));
|
|
41
|
+
const seconds = hasSeconds ? parseInteger(value.slice(6, 8)) : undefined;
|
|
42
|
+
const timezone = value.slice(timezoneIndex, timezoneIndex + 1).toUpperCase();
|
|
43
|
+
const month = MONTHS.indexOf(
|
|
44
|
+
value.slice(monthStart, monthStart + 3).toLowerCase(),
|
|
45
|
+
);
|
|
46
|
+
const year = 2000 + parseInteger(value.slice(monthStart + 3, monthStart + 5));
|
|
47
|
+
|
|
48
|
+
validateDateTime({
|
|
49
|
+
year,
|
|
50
|
+
month,
|
|
51
|
+
day,
|
|
52
|
+
hours,
|
|
53
|
+
minutes,
|
|
54
|
+
seconds,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const dateParts = [year, month, day, hours + OFFSETS[timezone], minutes];
|
|
58
|
+
if (seconds !== undefined) dateParts.push(seconds);
|
|
59
|
+
|
|
60
|
+
return new Date(Date.UTC(...dateParts));
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const parse = (value) => {
|
|
64
|
+
if (isShortFormat(value)) return parseShort(value);
|
|
65
|
+
if (isShortenedFormat(value)) {
|
|
66
|
+
return parseWithMonth(value, {
|
|
67
|
+
hasSeconds: false,
|
|
68
|
+
timezoneIndex: 6,
|
|
69
|
+
monthStart: 7,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (isLongFormat(value)) {
|
|
73
|
+
return parseWithMonth(value, {
|
|
74
|
+
hasSeconds: true,
|
|
75
|
+
timezoneIndex: 8,
|
|
76
|
+
monthStart: 9,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
throw new Error(`Invalid MDTG string "${value}"`);
|
|
81
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LONG_FORMAT_REGEX,
|
|
3
|
+
OFFSETS,
|
|
4
|
+
SHORT_FORMAT_REGEX,
|
|
5
|
+
SHORTENED_FORMAT_REGEX,
|
|
6
|
+
} from "./constants.js";
|
|
7
|
+
|
|
8
|
+
export const isShortFormat = (value) =>
|
|
9
|
+
typeof value === "string" && SHORT_FORMAT_REGEX.test(value);
|
|
10
|
+
|
|
11
|
+
export const isShortenedFormat = (value) =>
|
|
12
|
+
typeof value === "string" && SHORTENED_FORMAT_REGEX.test(value);
|
|
13
|
+
|
|
14
|
+
export const isLongFormat = (value) =>
|
|
15
|
+
typeof value === "string" && LONG_FORMAT_REGEX.test(value);
|
|
16
|
+
|
|
17
|
+
export const validateDate = (date) => {
|
|
18
|
+
if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
|
|
19
|
+
throw new TypeError("Expected a valid Date object");
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const validateTimezone = (timezone) => {
|
|
24
|
+
const key = timezone?.toUpperCase();
|
|
25
|
+
return key in OFFSETS ? key : "Z";
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const validateDateTime = ({
|
|
29
|
+
year,
|
|
30
|
+
month,
|
|
31
|
+
day,
|
|
32
|
+
hours,
|
|
33
|
+
minutes,
|
|
34
|
+
seconds,
|
|
35
|
+
}) => {
|
|
36
|
+
const candidate = new Date(
|
|
37
|
+
Date.UTC(year, month, day, hours, minutes, seconds ?? 0),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
if (
|
|
41
|
+
candidate.getUTCFullYear() !== year ||
|
|
42
|
+
candidate.getUTCMonth() !== month ||
|
|
43
|
+
candidate.getUTCDate() !== day ||
|
|
44
|
+
candidate.getUTCHours() !== hours ||
|
|
45
|
+
candidate.getUTCMinutes() !== minutes ||
|
|
46
|
+
candidate.getUTCSeconds() !== (seconds ?? 0)
|
|
47
|
+
) {
|
|
48
|
+
throw new RangeError("Invalid MDTG date or time");
|
|
49
|
+
}
|
|
50
|
+
};
|
package/index.js
DELETED
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
const normalizeNumber = (number) => String(number).padStart(2, "0");
|
|
2
|
-
const parseInteger = (input) => Number.parseInt(input, 10);
|
|
3
|
-
|
|
4
|
-
export class MDTG {
|
|
5
|
-
#currentDate;
|
|
6
|
-
|
|
7
|
-
static FORM = {
|
|
8
|
-
SHORT: "short",
|
|
9
|
-
SHORTENED: "shortened",
|
|
10
|
-
LONG: "long",
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
static #months = [
|
|
14
|
-
"jan",
|
|
15
|
-
"feb",
|
|
16
|
-
"mar",
|
|
17
|
-
"apr",
|
|
18
|
-
"may",
|
|
19
|
-
"jun",
|
|
20
|
-
"jul",
|
|
21
|
-
"aug",
|
|
22
|
-
"sep",
|
|
23
|
-
"oct",
|
|
24
|
-
"nov",
|
|
25
|
-
"dec",
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
static #shortFormatRegex = /^[0-9]{6}[A-Z]$/;
|
|
29
|
-
static #shortenedFormatRegex =
|
|
30
|
-
/^[0-9]{6}[A-Z](jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[0-9]{2}$/i;
|
|
31
|
-
static #longFormatRegex =
|
|
32
|
-
/^[0-9]{8}[A-Z](jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[0-9]{2}$/i;
|
|
33
|
-
|
|
34
|
-
static #offset = {
|
|
35
|
-
Y: 12,
|
|
36
|
-
X: 11,
|
|
37
|
-
W: 10,
|
|
38
|
-
V: 9,
|
|
39
|
-
U: 8,
|
|
40
|
-
T: 7,
|
|
41
|
-
S: 6,
|
|
42
|
-
R: 5,
|
|
43
|
-
Q: 4,
|
|
44
|
-
P: 3,
|
|
45
|
-
O: 2,
|
|
46
|
-
N: 1,
|
|
47
|
-
Z: 0,
|
|
48
|
-
A: -1,
|
|
49
|
-
B: -2,
|
|
50
|
-
C: -3,
|
|
51
|
-
D: -4,
|
|
52
|
-
E: -5,
|
|
53
|
-
F: -6,
|
|
54
|
-
G: -7,
|
|
55
|
-
H: -8,
|
|
56
|
-
I: -9,
|
|
57
|
-
J: -10,
|
|
58
|
-
K: -11,
|
|
59
|
-
L: -12,
|
|
60
|
-
M: -13,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
constructor(date) {
|
|
64
|
-
if (date && !(date instanceof Date)) {
|
|
65
|
-
throw new TypeError("Expected Date object");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const now = new Date();
|
|
69
|
-
|
|
70
|
-
this.#currentDate =
|
|
71
|
-
date ??
|
|
72
|
-
new Date(
|
|
73
|
-
Date.UTC(
|
|
74
|
-
now.getUTCFullYear(),
|
|
75
|
-
now.getUTCMonth(),
|
|
76
|
-
now.getUTCDate(),
|
|
77
|
-
now.getUTCHours(),
|
|
78
|
-
now.getUTCMinutes(),
|
|
79
|
-
now.getUTCSeconds(),
|
|
80
|
-
now.getUTCMilliseconds(),
|
|
81
|
-
),
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
static #validateTimezone(tz) {
|
|
86
|
-
const key = tz?.toUpperCase();
|
|
87
|
-
return key in MDTG.#offset ? key : "Z";
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
#createDateWithOffset(offset) {
|
|
91
|
-
const d = this.#currentDate;
|
|
92
|
-
|
|
93
|
-
return new Date(
|
|
94
|
-
Date.UTC(
|
|
95
|
-
d.getUTCFullYear(),
|
|
96
|
-
d.getUTCMonth(),
|
|
97
|
-
d.getUTCDate(),
|
|
98
|
-
d.getUTCHours() - offset,
|
|
99
|
-
d.getUTCMinutes(),
|
|
100
|
-
d.getUTCSeconds(),
|
|
101
|
-
),
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
static isShortFormat(str) {
|
|
106
|
-
return MDTG.#shortFormatRegex.test(str);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
static isShortenedFormat(str) {
|
|
110
|
-
return MDTG.#shortenedFormatRegex.test(str);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
static isLongFormat(str) {
|
|
114
|
-
return MDTG.#longFormatRegex.test(str);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
#toShortMDT(timezone = "Z") {
|
|
118
|
-
const tz = MDTG.#validateTimezone(timezone);
|
|
119
|
-
const date = this.#createDateWithOffset(MDTG.#offset[tz]);
|
|
120
|
-
|
|
121
|
-
const result = [date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes()]
|
|
122
|
-
.map(normalizeNumber)
|
|
123
|
-
.concat(tz)
|
|
124
|
-
.join("");
|
|
125
|
-
|
|
126
|
-
if (!MDTG.isShortFormat(result)) {
|
|
127
|
-
throw new Error("Failed to build short MDTG");
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return result;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
#toLongMDT(timezone = "Z") {
|
|
134
|
-
const tz = MDTG.#validateTimezone(timezone);
|
|
135
|
-
const date = this.#createDateWithOffset(MDTG.#offset[tz]);
|
|
136
|
-
|
|
137
|
-
const result = [
|
|
138
|
-
date.getUTCDate(),
|
|
139
|
-
date.getUTCHours(),
|
|
140
|
-
date.getUTCMinutes(),
|
|
141
|
-
date.getUTCSeconds(),
|
|
142
|
-
]
|
|
143
|
-
.map(normalizeNumber)
|
|
144
|
-
.concat(
|
|
145
|
-
tz,
|
|
146
|
-
MDTG.#months[date.getUTCMonth()],
|
|
147
|
-
normalizeNumber(date.getUTCFullYear() % 100),
|
|
148
|
-
)
|
|
149
|
-
.join("");
|
|
150
|
-
|
|
151
|
-
if (!MDTG.isLongFormat(result)) {
|
|
152
|
-
throw new Error("Failed to build long MDTG");
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
#toShortenedMDT(timezone = "Z") {
|
|
159
|
-
const tz = MDTG.#validateTimezone(timezone);
|
|
160
|
-
const date = this.#createDateWithOffset(MDTG.#offset[tz]);
|
|
161
|
-
|
|
162
|
-
const result = [
|
|
163
|
-
this.#toShortMDT(tz),
|
|
164
|
-
MDTG.#months[date.getUTCMonth()],
|
|
165
|
-
normalizeNumber(date.getUTCFullYear() % 100),
|
|
166
|
-
].join("");
|
|
167
|
-
|
|
168
|
-
if (!MDTG.isShortenedFormat(result)) {
|
|
169
|
-
throw new Error("Failed to build shortened MDTG");
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
toMDT({ form = MDTG.FORM.LONG, timezone = "Z" } = {}) {
|
|
176
|
-
switch (form) {
|
|
177
|
-
case MDTG.FORM.SHORT:
|
|
178
|
-
return this.#toShortMDT(timezone);
|
|
179
|
-
case MDTG.FORM.SHORTENED:
|
|
180
|
-
return this.#toShortenedMDT(timezone);
|
|
181
|
-
default:
|
|
182
|
-
return this.#toLongMDT(timezone);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
static #parseShort(str) {
|
|
187
|
-
const day = parseInteger(str.slice(0, 2));
|
|
188
|
-
const hours = parseInteger(str.slice(2, 4));
|
|
189
|
-
const minutes = parseInteger(str.slice(4, 6));
|
|
190
|
-
const tz = str.slice(6, 7).toUpperCase();
|
|
191
|
-
|
|
192
|
-
const today = new Date();
|
|
193
|
-
|
|
194
|
-
return new Date(
|
|
195
|
-
Date.UTC(
|
|
196
|
-
today.getUTCFullYear(),
|
|
197
|
-
today.getUTCMonth(),
|
|
198
|
-
day,
|
|
199
|
-
hours + MDTG.#offset[tz],
|
|
200
|
-
minutes,
|
|
201
|
-
),
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
static #parseShortened(str) {
|
|
206
|
-
const day = parseInteger(str.slice(0, 2));
|
|
207
|
-
const hours = parseInteger(str.slice(2, 4));
|
|
208
|
-
const minutes = parseInteger(str.slice(4, 6));
|
|
209
|
-
const tz = str.slice(6, 7).toUpperCase();
|
|
210
|
-
|
|
211
|
-
const month = MDTG.#months.indexOf(str.slice(7, 10).toLowerCase());
|
|
212
|
-
if (month === -1) throw new Error("Invalid month");
|
|
213
|
-
|
|
214
|
-
const year = 2000 + parseInteger(str.slice(10, 12));
|
|
215
|
-
|
|
216
|
-
return new Date(
|
|
217
|
-
Date.UTC(year, month, day, hours + MDTG.#offset[tz], minutes),
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
static #parseLong(str) {
|
|
222
|
-
const day = parseInteger(str.slice(0, 2));
|
|
223
|
-
const hours = parseInteger(str.slice(2, 4));
|
|
224
|
-
const minutes = parseInteger(str.slice(4, 6));
|
|
225
|
-
const seconds = parseInteger(str.slice(6, 8));
|
|
226
|
-
const tz = str.slice(8, 9).toUpperCase();
|
|
227
|
-
|
|
228
|
-
const month = MDTG.#months.indexOf(str.slice(9, 12).toLowerCase());
|
|
229
|
-
if (month === -1) throw new Error("Invalid month");
|
|
230
|
-
|
|
231
|
-
const year = 2000 + parseInteger(str.slice(12, 14));
|
|
232
|
-
|
|
233
|
-
return new Date(
|
|
234
|
-
Date.UTC(year, month, day, hours + MDTG.#offset[tz], minutes, seconds),
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
static parse(str) {
|
|
239
|
-
if (MDTG.isShortFormat(str)) return MDTG.#parseShort(str);
|
|
240
|
-
if (MDTG.isShortenedFormat(str)) return MDTG.#parseShortened(str);
|
|
241
|
-
if (MDTG.isLongFormat(str)) return MDTG.#parseLong(str);
|
|
242
|
-
|
|
243
|
-
throw new Error(`Invalid MDTG string "${str}"`);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
toDate() {
|
|
247
|
-
return new Date(this.#currentDate);
|
|
248
|
-
}
|
|
249
|
-
}
|