https://github.com/akmjenkins/ajv-dates
Intuitive JSON Schema Date Validation
https://github.com/akmjenkins/ajv-dates
Last synced: about 1 month ago
JSON representation
Intuitive JSON Schema Date Validation
- Host: GitHub
- URL: https://github.com/akmjenkins/ajv-dates
- Owner: akmjenkins
- License: mit
- Created: 2021-12-29T23:23:55.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2022-05-15T23:22:22.000Z (almost 3 years ago)
- Last Synced: 2025-03-03T21:17:55.429Z (about 2 months ago)
- Language: JavaScript
- Size: 117 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ajv-dates
[](https://npmjs.org/package/ajv-dates)
[](https://coveralls.io/github/akmjenkins/ajv-dates)

[](https://bundlephobia.com/result?p=ajv-dates)## What's this?
Good date validation has been conspicuously missing from the JSON schema spec. `ajv-dates` adds a few (configurable) keywords to [ajv](https://ajv.js.org/) to make date validation a snap.
## Getting Started
```bash
npm install ajv-dates
# or
yarn add ajv-dates
```## Usage
```js
import Ajv from 'ajv';
import dates from 'ajv-dates';const instance = dates(new Ajv());
const validator = instance.compile({
type: 'string',
isAfter: Date.UTC(2021, 12, 31)
});console.log(validator('2022-01-01').errors)
// null, no errors!console.log(validator('2021-01-01').errors)
/*[
{
message: 'Date must be after 1643587200000',
instancePath: '',
schemaPath: '#/isAfter'
}
]*/
```
## Keywords
- [isAfter](#isAfter)
- [isBefore](#isBefore)
- [isBetween](#isBetween)
- [isWeekday](#isWeekday)
- [isWeekend](#isWeekend)`isAfter`
---`isAfter` accepts a single argument that is, or can be parsed into a Date or unix timestamp:
```ts
instance.validate({
type: 'string',
isAfter: Date.now()
})
````isBefore`
---`isBefore` accepts a single argument that is, or can be parsed into a Date or unix timestamp:
```ts
instance.validate({
type: 'string',
isAfter: Date.now()
})
````isBetween`
---`isBetween` accepts a tuple of two values that are, or can be parsed into, Dates or unix timestamps:
```ts
instance.validate({
type: 'string',
isBetween: [Date.now()-86400, Date.now()+86400]
})
````isWeekday`
---`isWeekday` accepts a boolean:
```ts
instance.validate({
type: 'string',
isWeekday: true
})
````isWeekend`
---`isWeekend` accepts a boolean:
```ts
instance.validate({
type: 'string',
isWeekend: false
})
```## Bonus Keywords: times
If you supply a [`parser`](#parser) you can also take advantage of our time keywords:
```js
import Ajv from 'ajv';
import { date, times } from 'ajv-dates';
import { parseDate } from 'chrono-node';const options = { parser: parseDate }
const instance = times(dates(new Ajv(),options),options)
```- [isTimeAfter](#isTimeAfter)
- [isTimeBefore](#isTimeBefore)
- [isTimeBetween](#isTimeBetween)`isTimeAfter`
---```js
instance.validate({
type: 'string',
isTimeAfter: '7:00pm',
}, '6:30pm');// Error: Time must be after 7:00pm
````isTimeBefore`
---```js
instance.validate({
type: 'string',
isTimeBefore: '6:00pm',
}, '6:30pm');// Error: Time must be before 6:00pm
````isTimeBetween`
---```js
instance.validate({
type: 'string',
isTimeBetween: ['7:00pm','10:00pm'],
}, '6:30pm');// Error: Time must be between 7:00pm and 10:00pm
```## API
This library exports a default function that accepts an AJV instance and [options](#options).
### Options
```ts
type Options = {
parser?: (val: any) => Date | number;
keywordMap?: KeywordMap;
};
```#### `parser = (val) => new Date(val)`
The parser accepts any value and tries to parse it to a Date (or a unix timestamp). It is used to parse both the subject being evaluated and the arguments given to the keyword. As shown [below](#parser), the ability to specify a parser allows some really great features to be unlocked.
#### `keywordMap = Partial>`
Don't like the keywords? Configure your own using the keyword map:
```js
const instance = dates(
new Ajv(),
{
keywordMap: {
isAfter: 'isDateAfter'
}
}
)instance.validate({
type: 'string',
isDateAfter: Date.now()
}, '2021-12-31')
```## Parser
Even with [ajv-formats](), there's still something missing with date validation - the difficulty to encode "now", for validation purposes, in a schema. Fortunately, by using a smart date parser that can parse natural language relative strings into timestamps, you can now encode relative date logic into your schemas.
Two great options (tested with `ajv-dates`) are:
- The older, but still incredibly powerful and relevant [Sugar Date](https://sugarjs.com/dates/)
- The more modern [chrono-node](https://www.npmjs.com/package/chrono-node)```js
import Ajv from 'ajv';
import dates from 'ajv-dates';import { Date as SDate } from 'sugar-date'
import { parseDate } from 'chrono-node';// sugardate
const instance = dates(new Ajv(), { parser: SDate.create })// chrono
const instance = dates(new Ajv(), { parser: parseDate })
```Here's what the super power looks like:
```js
const schema = {
type: 'string',
isAfter: '30 days ago'
}const instance = dates(new Ajv(), { parser: /* your chosen natural language date parser */ })
const today = (new Date()).toISOString();instance.validate(
{
type: 'string',
isAfter: '2 weeks ago'
},
today
);
console.log(instance.errors); // nullinstance.validate(
{
type: 'string',
isAfter: '2 weeks from now'
},
today
);console.log(instance.errors);
/*[
{
message: 'Date must be after 2 weeks from now',
instancePath: '',
schemaPath: '#/isAfter'
}
]*/
```## License
[MIT](./LICENSE)
## Contributing
Grab an issue, PRs welcome!