Skip to content

Commit

Permalink
Merge pull request #2573 from exadel-inc/feat/time-parsing
Browse files Browse the repository at this point in the history
feat(esl-utils): add `parseTime`, less restrictive alternative to passed time format
  • Loading branch information
ala-n committed Aug 11, 2024
2 parents 0bd7a77 + 05e5963 commit d52213c
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 5 deletions.
16 changes: 12 additions & 4 deletions src/modules/esl-utils/misc/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,25 @@ export function format(str: string, source: Record<string, any>, matcher: RegExp
}
/**
* Parses time string ([CSS style](https://developer.mozilla.org/en-US/docs/Web/CSS/time))
* Less strict than CSS spec, allows empty string, numbers without units, ending dot.
* @example
* `.3s`, `4.5s`, `1000ms`
* @returns number - time in milliseconds
*/
export function parseCSSTime(timeStr: string): number {
export function parseTime(timeStr: string): number {
const str = timeStr.trim().toLowerCase();
if (!/\dm?s$/.test(str)) return NaN;
if (str.endsWith('ms')) return +str.slice(0, -2);
return +str.slice(0, -1) * 1000;
const parseNoEmpty = (s: string): number => s ? +s : NaN;
if (str.endsWith('ms')) return parseNoEmpty(str.slice(0, -2));
if (str.endsWith('s')) return parseNoEmpty(str.slice(0, -1)) * 1000;
return +str; // empty string without unit is treated as 0
}

/**
* Restrictive time parser according to [CSS style](https://developer.mozilla.org/en-US/docs/Web/CSS/time) spec.
* @see {@link parseTime}
*/
export const parseCSSTime = (timeStr: string): number => /(\d*\.?\d+)(ms|s)/i.test(timeStr) ? parseTime(timeStr) : NaN;

/**
* Parses string of times ([CSS style](https://developer.mozilla.org/en-US/docs/Web/CSS/time))
* @example
Expand Down
56 changes: 55 additions & 1 deletion src/modules/esl-utils/misc/test/format.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
parseNumber,
parseBoolean,
parseString,
parseTime,
parseCSSTime,
parseCSSTimeSet
} from '../format';
Expand Down Expand Up @@ -146,7 +147,7 @@ describe('misc/format helper tests', () => {
);
});

describe('parseCSSTime', () => {
describe('parseTime', () => {
test.each([
// Positive integer
['12s', 12000],
Expand All @@ -165,6 +166,59 @@ describe('misc/format helper tests', () => {
['14S', 14000],
// Zero with leading +/-
['+0s', 0],
['-0ms', -0],
// Digits without unit should be parsed as milliseconds
['0', 0],
['100', 100],
// Leading zeros
['012s', 12000],
['0350ms', 350],
// Empty string
['', 0],
// Extra dot
['350.s', 350000]
])(
'valid time = %s parsed as %s',
(time: string, result: number) => expect(parseTime(time)).toBe(result)
);
test.each([
// Invalid text
'five seconds',
's',
'ms',
' s ',
' ms ',
'350.n',
'abc',
'-',
'a',
// CSS time supports only seconds and milliseconds
'4min'
])(
'invalid time = %p parsed as NaN',
(time: string) => expect(parseTime(time)).toBe(NaN)
);
});

describe('parseCSSTime', () => {
test.each([
// Positive integer
['12s', 12000],
['350ms', 350],
['1024ms', 1024],
[' 12s ', 12000],
[' 350ms ', 350],
// Non-integer
['.3s', 300],
['.124s', 124],
['.3ms', 0.3],
// Negative integer
['-456ms', -456],
// Case insensitive
['14mS', 14],
['14S', 14000],
// Zero with leading +/-
['+0s', 0],
['-0ms', -0]
])(
'valid time = %s parsed as %s',
Expand Down

0 comments on commit d52213c

Please sign in to comment.