Add .validDate() (#203)

This commit is contained in:
Martin Eneqvist 2024-02-29 08:23:30 +01:00 committed by GitHub
parent 0e687a23a8
commit e9418fe1b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 0 deletions

View file

@ -574,6 +574,36 @@ is.all(is.string, '🦄', [], 'unicorns');
//=> false //=> false
``` ```
##### .validDate(value)
Returns `true` if the value is a valid date.
All [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date) objects have an internal timestamp value which is the number of milliseconds since the [Unix epoch](https://developer.mozilla.org/en-US/docs/Glossary/Unix_time). When a new `Date` is constructed with bad inputs, no error is thrown. Instead, a new `Date` object is returned. But the internal timestamp value is set to `NaN`, which is an `'Invalid Date'`. Bad inputs can be an non-parsable date string, a non-numeric value or a number that is outside of the expected range for a date value.
```js
const valid = new Date('2000-01-01');
is.date(valid);
//=> true
valid.getTime();
//=> 946684800000
valid.toUTCString();
//=> 'Sat, 01 Jan 2000 00:00:00 GMT'
is.validDate(valid);
//=> true
const invalid = new Date('Not a parsable date string');
is.date(invalid);
//=> true
invalid.getTime();
//=> NaN
invalid.toUTCString();
//=> 'Invalid Date'
is.validDate(invalid);
//=> false
```
##### .validLength(value) ##### .validLength(value)
Returns `true` if the value is a safe integer that is greater than or equal to zero. Returns `true` if the value is a safe integer that is greater than or equal to zero.

View file

@ -128,6 +128,7 @@ const assertionTypeDescriptions = [
'in range', 'in range',
'predicate returns truthy for any value', 'predicate returns truthy for any value',
'predicate returns truthy for all values', 'predicate returns truthy for all values',
'valid Date',
'valid length', 'valid length',
'whitespace string', 'whitespace string',
...objectTypeNames, ...objectTypeNames,
@ -311,6 +312,7 @@ const is = Object.assign(
urlInstance: isUrlInstance, urlInstance: isUrlInstance,
urlSearchParams: isUrlSearchParams, urlSearchParams: isUrlSearchParams,
urlString: isUrlString, urlString: isUrlString,
validDate: isValidDate,
validLength: isValidLength, validLength: isValidLength,
weakMap: isWeakMap, weakMap: isWeakMap,
weakRef: isWeakRef, weakRef: isWeakRef,
@ -760,6 +762,10 @@ export function isUrlString(value: unknown): value is string {
} }
} }
export function isValidDate(value: unknown): value is Date {
return isDate(value) && !isNan(Number(value));
}
export function isValidLength(value: unknown): value is number { export function isValidLength(value: unknown): value is number {
return isSafeInteger(value) && value >= 0; return isSafeInteger(value) && value >= 0;
} }
@ -917,6 +923,7 @@ type Assert = {
propertyKey: (value: unknown) => asserts value is PropertyKey; propertyKey: (value: unknown) => asserts value is PropertyKey;
formData: (value: unknown) => asserts value is FormData; formData: (value: unknown) => asserts value is FormData;
urlSearchParams: (value: unknown) => asserts value is URLSearchParams; urlSearchParams: (value: unknown) => asserts value is URLSearchParams;
validDate: (value: unknown) => asserts value is Date;
validLength: (value: unknown) => asserts value is number; validLength: (value: unknown) => asserts value is number;
whitespaceString: (value: unknown) => asserts value is string; whitespaceString: (value: unknown) => asserts value is string;
@ -1022,6 +1029,7 @@ export const assert: Assert = {
urlInstance: assertUrlInstance, urlInstance: assertUrlInstance,
urlSearchParams: assertUrlSearchParams, urlSearchParams: assertUrlSearchParams,
urlString: assertUrlString, urlString: assertUrlString,
validDate: assertValidDate,
validLength: assertValidLength, validLength: assertValidLength,
weakMap: assertWeakMap, weakMap: assertWeakMap,
weakRef: assertWeakRef, weakRef: assertWeakRef,
@ -1114,6 +1122,7 @@ const methodTypeMap = {
isUrlInstance: 'URL', isUrlInstance: 'URL',
isUrlSearchParams: 'URLSearchParams', isUrlSearchParams: 'URLSearchParams',
isUrlString: 'string with a URL', isUrlString: 'string with a URL',
isValidDate: 'valid Date',
isValidLength: 'valid length', isValidLength: 'valid length',
isWeakMap: 'WeakMap', isWeakMap: 'WeakMap',
isWeakRef: 'WeakRef', isWeakRef: 'WeakRef',
@ -1651,6 +1660,12 @@ export function assertUrlString(value: unknown): asserts value is string {
} }
} }
export function assertValidDate(value: unknown): asserts value is Date {
if (!isValidDate(value)) {
throw new TypeError(typeErrorMessage('valid Date', value));
}
}
export function assertValidLength(value: unknown): asserts value is number { export function assertValidLength(value: unknown): asserts value is number {
if (!isValidLength(value)) { if (!isValidLength(value)) {
throw new TypeError(typeErrorMessage('valid length', value)); throw new TypeError(typeErrorMessage('valid length', value));

View file

@ -2101,6 +2101,17 @@ test('is.urlSearchParams', t => {
}); });
}); });
test('is.validDate', t => {
t.true(is.validDate(new Date()));
t.false(is.validDate(new Date('x')));
t.notThrows(() => {
assert.validDate(new Date());
});
t.throws(() => {
assert.validDate(new Date('x'));
});
});
test('is.validLength', t => { test('is.validLength', t => {
t.true(is.validLength(1)); t.true(is.validLength(1));
t.true(is.validLength(0)); t.true(is.validLength(0));