Skip to content

Commit

Permalink
feat: Adds ISO 8601 Full Date rule (#1702)
Browse files Browse the repository at this point in the history
* feat: Adds ISO 8601 Full Date validation

* docs: Removes incorrect statement
  • Loading branch information
ryasmi committed Jun 17, 2024
1 parent 44bb44e commit ab3e39d
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Rulr also comes with a growing list of convenient rules for constraining strings
- [email](./src/constrainedStrings/email/readme.md)
- [iri](./src/constrainedStrings/iri/readme.md)
- [iso8601Duration](./src/constrainedStrings/iso8601Duration/readme.md)
- [iso8601FullDate](./src/constrainedStrings/iso8601FullDate/readme.md)
- [iso8601Timestamp](./src/constrainedStrings/iso8601Timestamp/readme.md)
- [locale](./src/constrainedStrings/locale/readme.md)
- [mailto](./src/constrainedStrings/mailto/readme.md)
Expand Down
52 changes: 52 additions & 0 deletions src/constrainedStrings/iso8601FullDate/iso8601FullDate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as assert from 'assert'
import { iso8601FullDate, ISO8601FullDate, InvalidISO8601FullDateError } from '../../rulr'

test('ISO 8601 Full Date should not allow invalid string input', () => {
const input = 0
assert.throws(() => iso8601FullDate(input), InvalidISO8601FullDateError)
})

test('ISO 8601 Full Date should allow valid ISO 8601 Full Date', () => {
const input = '2020-01-01'
const output: ISO8601FullDate = iso8601FullDate(input)
assert.strictEqual(output, input)
})

test('ISO 8601 Full Date should not allow invalid ISO 8601 Full Date', () => {
const input = '2020-01-01T00:00Z'
assert.throws(() => iso8601FullDate(input), InvalidISO8601FullDateError)
})

test('ISO 8601 Full Date should not allow basic format ISO 8601 Full Date', () => {
const input = '20090131'
assert.throws(() => iso8601FullDate(input), InvalidISO8601FullDateError)
})

test('ISO 8601 Full Date should allow valid extended format ISO 8601 Full Date', () => {
const input = '2009-01-31'
const output: ISO8601FullDate = iso8601FullDate(input)
assert.strictEqual(output, input)
})

// http://stackoverflow.com/questions/12756159
test('ISO 8601 Full Date should allow old ISO 8601 Full Date', () => {
const input = '0785-10-10'
const output: ISO8601FullDate = iso8601FullDate(input)
assert.strictEqual(output, input)
})

// http://stackoverflow.com/questions/12756159
test('ISO 8601 Full Date should not allow invalid month and date', () => {
const input = '2013-99-99'
assert.throws(() => iso8601FullDate(input), InvalidISO8601FullDateError)
})

test('ISO 8601 Full Date should not allow year only', () => {
const input = '2017'
assert.throws(() => iso8601FullDate(input), InvalidISO8601FullDateError)
})

test('ISO 8601 Full Date should not allow year and month only', () => {
const input = '2017-01'
assert.throws(() => iso8601FullDate(input), InvalidISO8601FullDateError)
})
30 changes: 30 additions & 0 deletions src/constrainedStrings/iso8601FullDate/iso8601FullDate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { BaseError } from 'make-error'
import { isString } from '../../valueRules/string/string'
import { Constrained } from '../../core'

export class InvalidISO8601FullDateError extends BaseError {
constructor() {
super('expected ISO 8601 Full Date')
}
}

const iso8601FullDateRegex = /^\d\d\d\d-\d\d-\d\d$/i

export const iso8601FullDateSymbol = Symbol()

export type ISO8601FullDate = Constrained<typeof iso8601FullDateSymbol, string>

export function isISO8601FullDate(input: unknown): input is ISO8601FullDate {
if (isString(input) && iso8601FullDateRegex.test(input)) {
const date = new Date(input);
return !isNaN(date.getTime());
}
return false;
}

export function iso8601FullDate(input: unknown) {
if (isISO8601FullDate(input)) {
return input
}
throw new InvalidISO8601FullDateError()
}
40 changes: 40 additions & 0 deletions src/constrainedStrings/iso8601FullDate/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# iso8601FullDate

[Back to root readme.md](../../../readme.md)

This function uses the `rulr.isISO8601FullDate` guard to check the input is a valid ISO 8601 Full Date as shown in the example below. It should only throw `rulr.InvalidISO8601FullDateError`.

```ts
import * as rulr from 'rulr'

const constrainToExample = rulr.object({
required: {
example: rulr.iso8601FullDate,
},
})

type Example = rulr.Static<typeof constrainToExample>
// {
// example: rulr.ISO8601FullDate
// }

// Valid
const example1: Example = constrainToExample({
example: '2020-01-01',
})

// Invalid: Not a valid ISO 8601 Full Date
const example2: Example = constrainToExample({
example: '2020-01-01T00:00Z',
})

// Invalid: Not a valid ISO 8601 Full Date
const example2: Example = constrainToExample({
example: '2020-01',
})

// Invalid: Not a string
const example3: Example = constrainToExample({
example: 1,
})
```
6 changes: 6 additions & 0 deletions src/rulr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export {
} from './constrainedValues/positiveNumber/positiveNumber'
export { email, isEmail, Email, InvalidEmailError } from './constrainedStrings/email/email'
export { iri, isIRI, IRI, InvalidIRIError } from './constrainedStrings/iri/iri'
export {
iso8601FullDate,
isISO8601FullDate,
ISO8601FullDate,
InvalidISO8601FullDateError,
} from './constrainedStrings/iso8601FullDate/iso8601FullDate'
export {
iso8601Duration,
isISO8601Duration,
Expand Down

0 comments on commit ab3e39d

Please sign in to comment.