kensnyder / any-date-parser

Parse a wide range of date formats including human-input dates
ISC License
32 stars 6 forks source link

any-date-parser

NPM Link Minified Size Build Status Code Coverage ISC License

Parse a wide range of date formats including human-input dates.

Supports Node, IE11+ and evergreen browsers.

Installation

npm install any-date-parser

OR

<script src="https://cdn.jsdelivr.net/npm/any-date-parser@1.5.4/dist/browser-bundle.js"></script>

Table of Contents

  1. Motivation
  2. Usage
  3. Supported formats
  4. Locale support
  5. Adding custom formats
  6. Removing parsing rules
  7. Creating a custom parser
  8. Unit tests
  9. Contributing

Motivation

  1. The APIs I consume have a lot of different date formats
  2. I want to create REST APIs that accept all major formats
  3. I want to handle user-input dates
  4. I want to support dates in other languages according to JavaScript's new Intl global object

Usage

There are three ways to use any-date-parser:

1.) Use a new function directly on Date:

Example:

require('any-date-parser');
Date.fromString('2020-10-15');
// same as new Date(2020, 9, 15, 0, 0, 0, 0)

2.) Use the parser object:

Example:

const parser = require('any-date-parser');
parser.fromString('2020-10-15');
// same as new Date(2020, 9, 15, 0, 0, 0, 0)

3.) It also exports parser with function parser.attempt(string, locale) that returns an object with one or more integer values for the following keys: year, month, day, hour, minute, second, millisecond, offset. Example:

const parser = require('any-date-parser');
parser.attempt('15 Oct 2020 at 6pm');
// returns:
{
  year: 2020,
  month: 10,
  day: 15,
  hour: 18,
}

4.) There are npm packages that integrate any-date-parser directly into popular date libraries:

Supported formats

Summary:

Exhaustive list of date formats

Locale Support

any-date-parser supports any locale that your runtime's Intl (ECMAScript Internationalization API) supports. In browsers that usually means the operating system language. In Node, that means the compiled language or the icu modules included. For unit tests, this library uses the full-icu npm package to make all locales available. That package is heavy and is not included as a dependency.

Adding custom formats

any-date-parser has an addFormat() function to add a custom parser.

First, parsers must have matcher or template.

Second, parsers must have units or handler.

Example 1: matcher + units

const parser,
    { Format } = require('any-date-parser');

parser.addFormat(
    new Format({
        matcher: /^(\d+) days? into month (\d+) in year (\d{4})$/,
        units: ['day', 'month', 'year'],
    })
);

Keep in mind that \d does not support other numbering system such as Chinese or Bengali. To support those you can use the template option given in example 3 and example 4.

Example 2: matcher + handler

const parser,
    { Format } = require('any-date-parser');

parser.addFormat(
    new Format({
        matcher: /^Q([1-4]) (\d{4})$/,
        handler: function ([, quarter, year]) {
            const monthByQuarter = { 1: 1, 2: 4, 3: 7, 4: 10 };
            const month = monthByQuarter[quarter];
            return { year, month };
        },
    })
);

Example 3: template + units

const parser,
    { Format } = require('any-date-parser');

parser.addFormat(
    new Format({
        template: 'The (_DAY_)(?:_ORDINAL_) day of (_MONTH_), (_YEAR_)',
        units: ['day', 'month', 'year'],
    })
);

Example 4: template + handler

const parser,
    { Format } = require('any-date-parser');

parser.addFormat(
    new Format({
        template: '^Q([1-4]) (_YEAR_)$',
        handler: function ([, quarter, year]) {
            const monthByQuarter = { 1: 1, 2: 4, 3: 7, 4: 10 };
            const month = monthByQuarter[quarter];
            return { year, month };
        },
    })
);

Removing parsing rules

To remove support for a certain format, use removeFormat()

const parser = require('any-date-parser');
const dayMonth = require('any-date-parser/src/formats/dayMonth/dayMonth.js');

parser.removeFormat(dayMonth);

Creating a custom parser

To create a new parser with a limited list of formats or your own custom formats, use new Parser

const { Parser } = require('any-date-parser');
const time24Hours = require('any-date-parser/src/formats/time24Hours/time24Hours.js');
const yearMonthDay = require('any-date-parser/src/formats/yearMonthDay/yearMonthDay.js');
const ago = require('any-date-parser/src/formats/ago/ago.js');

const parser = new Parser();
parser.addFormats([time24Hours, yearMonthDay, ago]);

You can convert your custom parser to a function. For example:

const { Parser } = require('any-date-parser');
const parser = new Parser();
// ....
parser.addFormats(/*...*/);
// Pass locale if you want to override the detected default
Date.fromString = parser.exportAsFunction();
Date.fromAny = parser.exportAsFunctionAny();

Unit tests

any-date-parser has 100% code coverage.

Testing

Contributing

Contributions are welcome. Please open a GitHub ticket for bugs or feature requests. Please make a pull request for any fixes or new code you'd like to be incorporated.

Exhaustive list of date formats

24 hour time (any date format followed by a 24-hour time expression)

12 hour time (any date format followed by a 12-hour time expression)

year month day

day monthname year

monthname day year

month day year

day month year

relative time

monthname day

day monthname

month day

day month

Twitter

unix timestamp

Microsoft JSON date string

chinese