@prairielearn/formatter 1.0.0
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/.mocharc.cjs +3 -0
- package/.turbo/turbo-build.log +0 -0
- package/dist/date.d.ts +13 -0
- package/dist/date.js +30 -0
- package/dist/date.js.map +1 -0
- package/dist/date.test.d.ts +1 -0
- package/dist/date.test.js +31 -0
- package/dist/date.test.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
- package/src/date.test.ts +35 -0
- package/src/date.ts +34 -0
- package/src/index.ts +1 -0
- package/tsconfig.json +8 -0
package/.mocharc.cjs
ADDED
|
File without changes
|
package/dist/date.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a date to a human-readable string like '2020-03-27T12:34:56 (CDT)'.
|
|
3
|
+
*
|
|
4
|
+
* @param date The date to format.
|
|
5
|
+
* @param timeZone The time zone to use for formatting.
|
|
6
|
+
* @param param2.includeTz Whether to include the time zone in the output (default true).
|
|
7
|
+
* @param param2.longTz Whether to use the long time zone name (default false).
|
|
8
|
+
* @returns Human-readable string representing the date.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatDate(date: Date, timeZone: string, { includeTz, longTz }?: {
|
|
11
|
+
includeTz?: boolean;
|
|
12
|
+
longTz?: boolean;
|
|
13
|
+
}): string;
|
package/dist/date.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import keyBy from 'lodash/keyBy.js';
|
|
2
|
+
/**
|
|
3
|
+
* Format a date to a human-readable string like '2020-03-27T12:34:56 (CDT)'.
|
|
4
|
+
*
|
|
5
|
+
* @param date The date to format.
|
|
6
|
+
* @param timeZone The time zone to use for formatting.
|
|
7
|
+
* @param param2.includeTz Whether to include the time zone in the output (default true).
|
|
8
|
+
* @param param2.longTz Whether to use the long time zone name (default false).
|
|
9
|
+
* @returns Human-readable string representing the date.
|
|
10
|
+
*/
|
|
11
|
+
export function formatDate(date, timeZone, { includeTz = true, longTz = false } = {}) {
|
|
12
|
+
const options = {
|
|
13
|
+
timeZone,
|
|
14
|
+
hourCycle: 'h23',
|
|
15
|
+
year: 'numeric',
|
|
16
|
+
month: '2-digit',
|
|
17
|
+
day: '2-digit',
|
|
18
|
+
hour: '2-digit',
|
|
19
|
+
minute: '2-digit',
|
|
20
|
+
second: '2-digit',
|
|
21
|
+
timeZoneName: longTz ? 'long' : 'short',
|
|
22
|
+
};
|
|
23
|
+
const parts = keyBy(new Intl.DateTimeFormat('en-US', options).formatToParts(date), (x) => x.type);
|
|
24
|
+
let dateFormatted = `${parts.year.value}-${parts.month.value}-${parts.day.value} ${parts.hour.value}:${parts.minute.value}:${parts.second.value}`;
|
|
25
|
+
if (includeTz) {
|
|
26
|
+
dateFormatted = `${dateFormatted} (${parts.timeZoneName.value})`;
|
|
27
|
+
}
|
|
28
|
+
return dateFormatted;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=date.js.map
|
package/dist/date.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.js","sourceRoot":"","sources":["../src/date.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,iBAAiB,CAAC;AAEpC;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CACxB,IAAU,EACV,QAAgB,EAChB,EAAE,SAAS,GAAG,IAAI,EAAE,MAAM,GAAG,KAAK,KAAgD,EAAE;IAEpF,MAAM,OAAO,GAA+B;QAC1C,QAAQ;QACR,SAAS,EAAE,KAAK;QAChB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;KACxC,CAAC;IACF,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClG,IAAI,aAAa,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAClJ,IAAI,SAAS,EAAE,CAAC;QACd,aAAa,GAAG,GAAG,aAAa,KAAK,KAAK,CAAC,YAAY,CAAC,KAAK,GAAG,CAAC;IACnE,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import keyBy from 'lodash/keyBy.js';\n\n/**\n * Format a date to a human-readable string like '2020-03-27T12:34:56 (CDT)'.\n *\n * @param date The date to format.\n * @param timeZone The time zone to use for formatting.\n * @param param2.includeTz Whether to include the time zone in the output (default true).\n * @param param2.longTz Whether to use the long time zone name (default false).\n * @returns Human-readable string representing the date.\n */\nexport function formatDate(\n date: Date,\n timeZone: string,\n { includeTz = true, longTz = false }: { includeTz?: boolean; longTz?: boolean } = {},\n): string {\n const options: Intl.DateTimeFormatOptions = {\n timeZone,\n hourCycle: 'h23',\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n timeZoneName: longTz ? 'long' : 'short',\n };\n const parts = keyBy(new Intl.DateTimeFormat('en-US', options).formatToParts(date), (x) => x.type);\n let dateFormatted = `${parts.year.value}-${parts.month.value}-${parts.day.value} ${parts.hour.value}:${parts.minute.value}:${parts.second.value}`;\n if (includeTz) {\n dateFormatted = `${dateFormatted} (${parts.timeZoneName.value})`;\n }\n return dateFormatted;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { assert } from 'chai';
|
|
2
|
+
import { formatDate } from './date.js';
|
|
3
|
+
describe('date formatting', () => {
|
|
4
|
+
describe('formatDate', () => {
|
|
5
|
+
it('formats a UTC date', () => {
|
|
6
|
+
const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
|
|
7
|
+
assert.equal(formatDate(date, 'UTC'), '2018-01-01 12:00:00 (UTC)');
|
|
8
|
+
});
|
|
9
|
+
it('formats a CST date', () => {
|
|
10
|
+
const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
|
|
11
|
+
assert.equal(formatDate(date, 'America/Chicago'), '2018-01-01 06:00:00 (CST)');
|
|
12
|
+
});
|
|
13
|
+
it('formats a CDT date', () => {
|
|
14
|
+
const date = new Date(Date.UTC(2018, 6, 1, 12, 0, 0));
|
|
15
|
+
assert.equal(formatDate(date, 'America/Chicago'), '2018-07-01 07:00:00 (CDT)');
|
|
16
|
+
});
|
|
17
|
+
it('formats dates with zero hours', () => {
|
|
18
|
+
const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));
|
|
19
|
+
assert.equal(formatDate(date, 'UTC'), '2018-01-01 00:01:00 (UTC)');
|
|
20
|
+
});
|
|
21
|
+
it('formats dates without the timezone', () => {
|
|
22
|
+
const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
|
|
23
|
+
assert.equal(formatDate(date, 'UTC', { includeTz: false }), '2018-01-01 12:00:00');
|
|
24
|
+
});
|
|
25
|
+
it('formats dates with the long timezone name', () => {
|
|
26
|
+
const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
|
|
27
|
+
assert.equal(formatDate(date, 'America/Chicago', { longTz: true }), '2018-01-01 06:00:00 (Central Standard Time)');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=date.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.test.js","sourceRoot":"","sources":["../src/date.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YAC5B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,2BAA2B,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YAC5B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,2BAA2B,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YAC5B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,2BAA2B,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,2BAA2B,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,qBAAqB,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,KAAK,CACV,UAAU,CAAC,IAAI,EAAE,iBAAiB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EACrD,6CAA6C,CAC9C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { assert } from 'chai';\n\nimport { formatDate } from './date.js';\n\ndescribe('date formatting', () => {\n describe('formatDate', () => {\n it('formats a UTC date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'UTC'), '2018-01-01 12:00:00 (UTC)');\n });\n it('formats a CST date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'America/Chicago'), '2018-01-01 06:00:00 (CST)');\n });\n it('formats a CDT date', () => {\n const date = new Date(Date.UTC(2018, 6, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'America/Chicago'), '2018-07-01 07:00:00 (CDT)');\n });\n it('formats dates with zero hours', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));\n assert.equal(formatDate(date, 'UTC'), '2018-01-01 00:01:00 (UTC)');\n });\n it('formats dates without the timezone', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'UTC', { includeTz: false }), '2018-01-01 12:00:00');\n });\n it('formats dates with the long timezone name', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(\n formatDate(date, 'America/Chicago', { longTz: true }),\n '2018-01-01 06:00:00 (Central Standard Time)',\n );\n });\n });\n});\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { formatDate } from './date.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export { formatDate } from './date.js';\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prairielearn/formatter",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/PrairieLearn/PrairieLearn.git",
|
|
9
|
+
"directory": "packages/formatter"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"dev": "tsc --watch --preserveWatchOutput",
|
|
14
|
+
"test": "c8 mocha src/**/*.test.ts"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"lodash": "^4.17.21"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@prairielearn/tsconfig": "^0.0.0",
|
|
21
|
+
"@types/node": "^20.12.11",
|
|
22
|
+
"c8": "^9.1.0",
|
|
23
|
+
"chai": "^5.1.1",
|
|
24
|
+
"mocha": "^10.4.0",
|
|
25
|
+
"tsx": "^4.10.4",
|
|
26
|
+
"typescript": "^5.4.5"
|
|
27
|
+
},
|
|
28
|
+
"c8": {
|
|
29
|
+
"reporter": [
|
|
30
|
+
"html",
|
|
31
|
+
"text-summary",
|
|
32
|
+
"cobertura"
|
|
33
|
+
],
|
|
34
|
+
"all": true,
|
|
35
|
+
"include": [
|
|
36
|
+
"src/**"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/date.test.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { assert } from 'chai';
|
|
2
|
+
|
|
3
|
+
import { formatDate } from './date.js';
|
|
4
|
+
|
|
5
|
+
describe('date formatting', () => {
|
|
6
|
+
describe('formatDate', () => {
|
|
7
|
+
it('formats a UTC date', () => {
|
|
8
|
+
const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
|
|
9
|
+
assert.equal(formatDate(date, 'UTC'), '2018-01-01 12:00:00 (UTC)');
|
|
10
|
+
});
|
|
11
|
+
it('formats a CST date', () => {
|
|
12
|
+
const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
|
|
13
|
+
assert.equal(formatDate(date, 'America/Chicago'), '2018-01-01 06:00:00 (CST)');
|
|
14
|
+
});
|
|
15
|
+
it('formats a CDT date', () => {
|
|
16
|
+
const date = new Date(Date.UTC(2018, 6, 1, 12, 0, 0));
|
|
17
|
+
assert.equal(formatDate(date, 'America/Chicago'), '2018-07-01 07:00:00 (CDT)');
|
|
18
|
+
});
|
|
19
|
+
it('formats dates with zero hours', () => {
|
|
20
|
+
const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));
|
|
21
|
+
assert.equal(formatDate(date, 'UTC'), '2018-01-01 00:01:00 (UTC)');
|
|
22
|
+
});
|
|
23
|
+
it('formats dates without the timezone', () => {
|
|
24
|
+
const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
|
|
25
|
+
assert.equal(formatDate(date, 'UTC', { includeTz: false }), '2018-01-01 12:00:00');
|
|
26
|
+
});
|
|
27
|
+
it('formats dates with the long timezone name', () => {
|
|
28
|
+
const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
|
|
29
|
+
assert.equal(
|
|
30
|
+
formatDate(date, 'America/Chicago', { longTz: true }),
|
|
31
|
+
'2018-01-01 06:00:00 (Central Standard Time)',
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
package/src/date.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import keyBy from 'lodash/keyBy.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Format a date to a human-readable string like '2020-03-27T12:34:56 (CDT)'.
|
|
5
|
+
*
|
|
6
|
+
* @param date The date to format.
|
|
7
|
+
* @param timeZone The time zone to use for formatting.
|
|
8
|
+
* @param param2.includeTz Whether to include the time zone in the output (default true).
|
|
9
|
+
* @param param2.longTz Whether to use the long time zone name (default false).
|
|
10
|
+
* @returns Human-readable string representing the date.
|
|
11
|
+
*/
|
|
12
|
+
export function formatDate(
|
|
13
|
+
date: Date,
|
|
14
|
+
timeZone: string,
|
|
15
|
+
{ includeTz = true, longTz = false }: { includeTz?: boolean; longTz?: boolean } = {},
|
|
16
|
+
): string {
|
|
17
|
+
const options: Intl.DateTimeFormatOptions = {
|
|
18
|
+
timeZone,
|
|
19
|
+
hourCycle: 'h23',
|
|
20
|
+
year: 'numeric',
|
|
21
|
+
month: '2-digit',
|
|
22
|
+
day: '2-digit',
|
|
23
|
+
hour: '2-digit',
|
|
24
|
+
minute: '2-digit',
|
|
25
|
+
second: '2-digit',
|
|
26
|
+
timeZoneName: longTz ? 'long' : 'short',
|
|
27
|
+
};
|
|
28
|
+
const parts = keyBy(new Intl.DateTimeFormat('en-US', options).formatToParts(date), (x) => x.type);
|
|
29
|
+
let dateFormatted = `${parts.year.value}-${parts.month.value}-${parts.day.value} ${parts.hour.value}:${parts.minute.value}:${parts.second.value}`;
|
|
30
|
+
if (includeTz) {
|
|
31
|
+
dateFormatted = `${dateFormatted} (${parts.timeZoneName.value})`;
|
|
32
|
+
}
|
|
33
|
+
return dateFormatted;
|
|
34
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { formatDate } from './date.js';
|