@prairielearn/formatter 1.1.0 → 1.2.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/CHANGELOG.md +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/interval.d.ts +11 -0
- package/dist/interval.js +35 -0
- package/dist/interval.js.map +1 -0
- package/dist/interval.test.d.ts +1 -0
- package/dist/interval.test.js +31 -0
- package/dist/interval.test.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/interval.test.ts +35 -0
- package/src/interval.ts +39 -0
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export { formatDate, formatDateYMD, formatDateYMDHM } from './date.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC","sourcesContent":["export { formatDate, formatDateYMD, formatDateYMDHM } from './date.js';\nexport { formatInterval } from './interval.js';\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const SECOND_IN_MILLISECONDS = 1000;
|
|
2
|
+
export declare const MINUTE_IN_MILLISECONDS: number;
|
|
3
|
+
export declare const HOUR_IN_MILLISECONDS: number;
|
|
4
|
+
export declare const DAY_IN_MILLISECONDS: number;
|
|
5
|
+
/**
|
|
6
|
+
* Format an interval (in milliseconds) to a human-readable string like '3 h 40 m'.
|
|
7
|
+
*
|
|
8
|
+
* @param interval Time interval in milliseconds.
|
|
9
|
+
* @returns Human-readable string representing the interval.
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatInterval(interval: number): string;
|
package/dist/interval.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const SECOND_IN_MILLISECONDS = 1000;
|
|
2
|
+
export const MINUTE_IN_MILLISECONDS = 60 * SECOND_IN_MILLISECONDS;
|
|
3
|
+
export const HOUR_IN_MILLISECONDS = 60 * MINUTE_IN_MILLISECONDS;
|
|
4
|
+
export const DAY_IN_MILLISECONDS = 24 * HOUR_IN_MILLISECONDS;
|
|
5
|
+
/**
|
|
6
|
+
* Format an interval (in milliseconds) to a human-readable string like '3 h 40 m'.
|
|
7
|
+
*
|
|
8
|
+
* @param interval Time interval in milliseconds.
|
|
9
|
+
* @returns Human-readable string representing the interval.
|
|
10
|
+
*/
|
|
11
|
+
export function formatInterval(interval) {
|
|
12
|
+
const sign = interval < 0 ? '-' : '';
|
|
13
|
+
const days = Math.floor(Math.abs(interval) / DAY_IN_MILLISECONDS);
|
|
14
|
+
const hours = Math.floor(Math.abs(interval) / HOUR_IN_MILLISECONDS) % 24;
|
|
15
|
+
const mins = Math.floor(Math.abs(interval) / MINUTE_IN_MILLISECONDS) % 60;
|
|
16
|
+
const secs = Math.floor(Math.abs(interval) / SECOND_IN_MILLISECONDS) % 60;
|
|
17
|
+
const parts = [];
|
|
18
|
+
if (days > 0) {
|
|
19
|
+
parts.push(`${sign}${days} d`);
|
|
20
|
+
}
|
|
21
|
+
if (hours > 0) {
|
|
22
|
+
parts.push(`${sign}${hours} h`);
|
|
23
|
+
}
|
|
24
|
+
if (mins > 0) {
|
|
25
|
+
parts.push(`${sign}${mins} min`);
|
|
26
|
+
}
|
|
27
|
+
if (secs > 0) {
|
|
28
|
+
parts.push(`${sign}${secs} s`);
|
|
29
|
+
}
|
|
30
|
+
if (parts.length === 0) {
|
|
31
|
+
parts.push('0 s');
|
|
32
|
+
}
|
|
33
|
+
return parts.join(' ');
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=interval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interval.js","sourceRoot":"","sources":["../src/interval.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,GAAG,sBAAsB,CAAC;AAClE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,sBAAsB,CAAC;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,oBAAoB,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,IAAI,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAErC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,mBAAmB,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,oBAAoB,CAAC,GAAG,EAAE,CAAC;IACzE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,sBAAsB,CAAC,GAAG,EAAE,CAAC;IAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,sBAAsB,CAAC,GAAG,EAAE,CAAC;IAE1E,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,MAAM,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC","sourcesContent":["export const SECOND_IN_MILLISECONDS = 1000;\nexport const MINUTE_IN_MILLISECONDS = 60 * SECOND_IN_MILLISECONDS;\nexport const HOUR_IN_MILLISECONDS = 60 * MINUTE_IN_MILLISECONDS;\nexport const DAY_IN_MILLISECONDS = 24 * HOUR_IN_MILLISECONDS;\n\n/**\n * Format an interval (in milliseconds) to a human-readable string like '3 h 40 m'.\n *\n * @param interval Time interval in milliseconds.\n * @returns Human-readable string representing the interval.\n */\nexport function formatInterval(interval: number): string {\n const sign = interval < 0 ? '-' : '';\n\n const days = Math.floor(Math.abs(interval) / DAY_IN_MILLISECONDS);\n const hours = Math.floor(Math.abs(interval) / HOUR_IN_MILLISECONDS) % 24;\n const mins = Math.floor(Math.abs(interval) / MINUTE_IN_MILLISECONDS) % 60;\n const secs = Math.floor(Math.abs(interval) / SECOND_IN_MILLISECONDS) % 60;\n\n const parts: string[] = [];\n\n if (days > 0) {\n parts.push(`${sign}${days} d`);\n }\n if (hours > 0) {\n parts.push(`${sign}${hours} h`);\n }\n if (mins > 0) {\n parts.push(`${sign}${mins} min`);\n }\n if (secs > 0) {\n parts.push(`${sign}${secs} s`);\n }\n if (parts.length === 0) {\n parts.push('0 s');\n }\n\n return parts.join(' ');\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { assert } from 'chai';
|
|
2
|
+
import { formatInterval } from './interval.js';
|
|
3
|
+
describe('interval formatting', () => {
|
|
4
|
+
describe('formatInterval()', () => {
|
|
5
|
+
it('should handle seconds', () => {
|
|
6
|
+
assert.equal(formatInterval(7000), '7 s');
|
|
7
|
+
});
|
|
8
|
+
it('should handle fractional seconds', () => {
|
|
9
|
+
assert.equal(formatInterval(7321), '7 s');
|
|
10
|
+
});
|
|
11
|
+
it('should handle minutes', () => {
|
|
12
|
+
assert.equal(formatInterval(2 * 60 * 1000), '2 min');
|
|
13
|
+
});
|
|
14
|
+
it('should handle hours', () => {
|
|
15
|
+
assert.equal(formatInterval(3 * 60 * 60 * 1000), '3 h');
|
|
16
|
+
});
|
|
17
|
+
it('should handle hours', () => {
|
|
18
|
+
assert.equal(formatInterval(4 * 24 * 60 * 60 * 1000), '4 d');
|
|
19
|
+
});
|
|
20
|
+
it('should handle complex intervals', () => {
|
|
21
|
+
assert.equal(formatInterval((((4 * 24 + 3) * 60 + 2) * 60 + 7) * 1000), '4 d 3 h 2 min 7 s');
|
|
22
|
+
});
|
|
23
|
+
it('should handle zero', () => {
|
|
24
|
+
assert.equal(formatInterval(0), '0 s');
|
|
25
|
+
});
|
|
26
|
+
it('should handle negative intervals', () => {
|
|
27
|
+
assert.equal(formatInterval(-(((4 * 24 + 3) * 60 + 2) * 60 + 7) * 1000), '-4 d -3 h -2 min -7 s');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=interval.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interval.test.js","sourceRoot":"","sources":["../src/interval.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;YAC/B,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;YAC/B,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,mBAAmB,CAAC,CAAC;QAC/F,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,KAAK,CACV,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAC1D,uBAAuB,CACxB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { assert } from 'chai';\n\nimport { formatInterval } from './interval.js';\n\ndescribe('interval formatting', () => {\n describe('formatInterval()', () => {\n it('should handle seconds', () => {\n assert.equal(formatInterval(7000), '7 s');\n });\n it('should handle fractional seconds', () => {\n assert.equal(formatInterval(7321), '7 s');\n });\n it('should handle minutes', () => {\n assert.equal(formatInterval(2 * 60 * 1000), '2 min');\n });\n it('should handle hours', () => {\n assert.equal(formatInterval(3 * 60 * 60 * 1000), '3 h');\n });\n it('should handle hours', () => {\n assert.equal(formatInterval(4 * 24 * 60 * 60 * 1000), '4 d');\n });\n it('should handle complex intervals', () => {\n assert.equal(formatInterval((((4 * 24 + 3) * 60 + 2) * 60 + 7) * 1000), '4 d 3 h 2 min 7 s');\n });\n it('should handle zero', () => {\n assert.equal(formatInterval(0), '0 s');\n });\n it('should handle negative intervals', () => {\n assert.equal(\n formatInterval(-(((4 * 24 + 3) * 60 + 2) * 60 + 7) * 1000),\n '-4 d -3 h -2 min -7 s',\n );\n });\n });\n});\n"]}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { assert } from 'chai';
|
|
2
|
+
|
|
3
|
+
import { formatInterval } from './interval.js';
|
|
4
|
+
|
|
5
|
+
describe('interval formatting', () => {
|
|
6
|
+
describe('formatInterval()', () => {
|
|
7
|
+
it('should handle seconds', () => {
|
|
8
|
+
assert.equal(formatInterval(7000), '7 s');
|
|
9
|
+
});
|
|
10
|
+
it('should handle fractional seconds', () => {
|
|
11
|
+
assert.equal(formatInterval(7321), '7 s');
|
|
12
|
+
});
|
|
13
|
+
it('should handle minutes', () => {
|
|
14
|
+
assert.equal(formatInterval(2 * 60 * 1000), '2 min');
|
|
15
|
+
});
|
|
16
|
+
it('should handle hours', () => {
|
|
17
|
+
assert.equal(formatInterval(3 * 60 * 60 * 1000), '3 h');
|
|
18
|
+
});
|
|
19
|
+
it('should handle hours', () => {
|
|
20
|
+
assert.equal(formatInterval(4 * 24 * 60 * 60 * 1000), '4 d');
|
|
21
|
+
});
|
|
22
|
+
it('should handle complex intervals', () => {
|
|
23
|
+
assert.equal(formatInterval((((4 * 24 + 3) * 60 + 2) * 60 + 7) * 1000), '4 d 3 h 2 min 7 s');
|
|
24
|
+
});
|
|
25
|
+
it('should handle zero', () => {
|
|
26
|
+
assert.equal(formatInterval(0), '0 s');
|
|
27
|
+
});
|
|
28
|
+
it('should handle negative intervals', () => {
|
|
29
|
+
assert.equal(
|
|
30
|
+
formatInterval(-(((4 * 24 + 3) * 60 + 2) * 60 + 7) * 1000),
|
|
31
|
+
'-4 d -3 h -2 min -7 s',
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
package/src/interval.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const SECOND_IN_MILLISECONDS = 1000;
|
|
2
|
+
export const MINUTE_IN_MILLISECONDS = 60 * SECOND_IN_MILLISECONDS;
|
|
3
|
+
export const HOUR_IN_MILLISECONDS = 60 * MINUTE_IN_MILLISECONDS;
|
|
4
|
+
export const DAY_IN_MILLISECONDS = 24 * HOUR_IN_MILLISECONDS;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Format an interval (in milliseconds) to a human-readable string like '3 h 40 m'.
|
|
8
|
+
*
|
|
9
|
+
* @param interval Time interval in milliseconds.
|
|
10
|
+
* @returns Human-readable string representing the interval.
|
|
11
|
+
*/
|
|
12
|
+
export function formatInterval(interval: number): string {
|
|
13
|
+
const sign = interval < 0 ? '-' : '';
|
|
14
|
+
|
|
15
|
+
const days = Math.floor(Math.abs(interval) / DAY_IN_MILLISECONDS);
|
|
16
|
+
const hours = Math.floor(Math.abs(interval) / HOUR_IN_MILLISECONDS) % 24;
|
|
17
|
+
const mins = Math.floor(Math.abs(interval) / MINUTE_IN_MILLISECONDS) % 60;
|
|
18
|
+
const secs = Math.floor(Math.abs(interval) / SECOND_IN_MILLISECONDS) % 60;
|
|
19
|
+
|
|
20
|
+
const parts: string[] = [];
|
|
21
|
+
|
|
22
|
+
if (days > 0) {
|
|
23
|
+
parts.push(`${sign}${days} d`);
|
|
24
|
+
}
|
|
25
|
+
if (hours > 0) {
|
|
26
|
+
parts.push(`${sign}${hours} h`);
|
|
27
|
+
}
|
|
28
|
+
if (mins > 0) {
|
|
29
|
+
parts.push(`${sign}${mins} min`);
|
|
30
|
+
}
|
|
31
|
+
if (secs > 0) {
|
|
32
|
+
parts.push(`${sign}${secs} s`);
|
|
33
|
+
}
|
|
34
|
+
if (parts.length === 0) {
|
|
35
|
+
parts.push('0 s');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return parts.join(' ');
|
|
39
|
+
}
|