Skip to content

Commit

Permalink
feat: add @IsTimeZone validator (typestack#1796)
Browse files Browse the repository at this point in the history
Co-authored-by: chandra shekhar <shekharneupane23@gmail.com>
  • Loading branch information
NoNameProvided and chandrashekhar07 authored Nov 20, 2022
1 parent c913e3c commit 6fa5680
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,7 @@ isBoolean(value);
| `@MaxLength(max: number)` | Checks if the string's length is not more than given number. |
| `@Matches(pattern: RegExp, modifiers?: string)` | Checks if string matches the pattern. Either matches('foo', /foo/i) or matches('foo', 'foo', 'i'). |
| `@IsMilitaryTime()` | Checks if the string is a valid representation of military time in the format HH:MM. |
| `@IsTimeZone()` | Checks if the string represents a valid IANA time-zone. |
| `@IsHash(algorithm: string)` | Checks if the string is a hash The following types are supported:`md4`, `md5`, `sha1`, `sha256`, `sha384`, `sha512`, `ripemd128`, `ripemd160`, `tiger128`, `tiger160`, `tiger192`, `crc32`, `crc32b`. |
| `@IsMimeType()` | Checks if the string matches to a valid [MIME type](https://en.wikipedia.org/wiki/Media_type) format |
| `@IsSemVer()` | Checks if the string is a Semantic Versioning Specification (SemVer). |
Expand Down
1 change: 1 addition & 0 deletions src/decorator/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export * from './string/IsPostalCode';
export * from './string/IsRFC3339';
export * from './string/IsRgbColor';
export * from './string/IsSemVer';
export * from './string/IsTimeZone';

// -------------------------------------------------------------------------
// Type checkers
Expand Down
43 changes: 43 additions & 0 deletions src/decorator/string/IsTimeZone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ValidationOptions } from '../ValidationOptions';
import { buildMessage, ValidateBy } from '../common/ValidateBy';

export const IS_TIMEZONE = 'isTimeZone';

/**
* Checks if the string represents a valid IANA timezone
* If the given value is not a valid IANA timezone, then it returns false.
*/
export function isTimeZone(value: unknown): boolean {
try {
if (typeof value !== 'string') {
return false;
}

/** Specifying an invalid time-zone will raise a `RangeError: Invalid time zone specified` error. */
Intl.DateTimeFormat(undefined, { timeZone: value });

return true;
} catch (exception) {
return false;
}
}

/**
* Checks if the string represents a valid IANA timezone
* If the given value is not a valid IANA timezone, then it returns false.
*/
export function IsTimeZone(validationOptions?: ValidationOptions): PropertyDecorator {
return ValidateBy(
{
name: IS_TIMEZONE,
validator: {
validate: (value, args): boolean => isTimeZone(value),
defaultMessage: buildMessage(
eachPrefix => eachPrefix + '$property must be a valid IANA time-zone',
validationOptions
),
},
},
validationOptions
);
}
23 changes: 23 additions & 0 deletions test/functional/validation-functions-and-decorators.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ import {
isPostalCode,
IsSemVer,
isSemVer,
IsTimeZone,
} from '../../src/decorator/decorators';
import { Validator } from '../../src/validation/Validator';
import { ValidatorOptions } from '../../src/validation/ValidatorOptions';
Expand Down Expand Up @@ -3829,6 +3830,28 @@ describe('IsMilitaryTime', () => {
});
});

describe('IsTimeZone', () => {
class MyClass {
@IsTimeZone()
someProperty: string;
}

it('should not fail for a valid IANA timezones', () => {
const validValues = ['Asia/Kathmandu', 'America/New_York', 'Europe/Paris', 'Europe/Berlin'];
return checkValidValues(new MyClass(), validValues);
});

it('should fail for invalid timezone format', () => {
const invalidValues = ['Asia/Pokhara', 'America', 'New_York', '/Paris'];
return checkInvalidValues(new MyClass(), invalidValues);
});

it('should fail for invalid values', () => {
const invalidValues = [undefined, null, 'Asia-Kathmandu'];
return checkInvalidValues(new MyClass(), invalidValues);
});
});

describe('isPhoneNumber', () => {
describe('with region', () => {
const validValues = [
Expand Down

0 comments on commit 6fa5680

Please sign in to comment.