ajv-dates
TypeScript icon, indicating that this package has built-in type declarations

1.1.0 • Public • Published

ajv-dates

npm version Coverage Status Build Status Bundle Phobia

What's this?

Good date validation has been conspicuously missing from the JSON schema spec. ajv-dates adds a few (configurable) keywords to ajv to make date validation a snap.

Getting Started

npm install ajv-dates
# or
yarn add ajv-dates

Usage

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 accepts a single argument that is, or can be parsed into a Date or unix timestamp:

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:

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:

instance.validate({
    type: 'string',
    isBetween: [Date.now()-86400, Date.now()+86400]
})

isWeekday

isWeekday accepts a boolean:

instance.validate({
    type: 'string',
    isWeekday: true
})

isWeekend

isWeekend accepts a boolean:

instance.validate({
    type: 'string',
    isWeekend: false
})

Bonus Keywords: times

If you supply a parser you can also take advantage of our time keywords:

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

instance.validate({
    type: 'string',
    isTimeAfter: '7:00pm',
}, '6:30pm');

// Error: Time must be after 7:00pm

isTimeBefore

instance.validate({
    type: 'string',
    isTimeBefore: '6:00pm',
}, '6:30pm');

// Error: Time must be before 6:00pm

isTimeBetween

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

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, the ability to specify a parser allows some really great features to be unlocked.

keywordMap = Partial<Record<Keyword,string>>

Don't like the keywords? Configure your own using the keyword map:

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:

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:

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); // null

instance.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

Contributing

Grab an issue, PRs welcome!

Readme

Keywords

Package Sidebar

Install

npm i ajv-dates

Weekly Downloads

194

Version

1.1.0

License

ISC

Unpacked Size

19.5 kB

Total Files

14

Last publish

Collaborators

  • akmjenkins