UNPKG

half-past

Version:

natural-language date-parsing in javascript

336 lines (291 loc) 8.29 kB
<div align="center"> <div>WIP</div> <a href="https://npmjs.org/package/half-past"> <img src="https://img.shields.io/npm/v/half-past.svg?style=flat-square" /> </a> <a href="https://unpkg.com/half-past"> <img src="https://badge-size.herokuapp.com/spencermountain/half-past/master/builds/half-past.min.js" /> </a> </div> **work-in-progress** rule-based interpreter for natural-language date-forms. an opinionated-but-configurable mash-up of [spacetime](https://github.com/spencermountain/spacetime) and [compromise](https://github.com/spencermountain/compromise) you've been warned! ### IF YOU DARE: `npm install half-past` <!-- ### What it does: * `"January 8th"` explicit date-forms * `"1999-12-25"` numeric/ISO date-forms * `"7:30pm"` NL time-of-day * `"5pm eastern time"` NL timezone * `"christmas"` named holidays * `"next friday"` this/next/last logic * `"end of the month"` end/start/middle logic * `between June 5th and 7th` range logic * `"three days after June 4rth"` 'punt' by a duration * `this winter` seasons - * `q2 2020` financial quarters - * `second semester 2019` academic semesters - * `every monday` repetitions by interval * `in April O'neil's house` ignore false-positives * handle DST/leap-year/hemisphere/leap-second logic (from [spacetime](https://github.com/spencermountain/spacetime) ) * handle tokenization/normalization/punctuation-handling (from [compromise](https://github.com/spencermountain/compromise) ) ### What it doesn't do: * `'easter 1440'` distant dates for astronomical holidays * `1536602449137` millisecond, or epoch-time as dates * force interpretation of british/american (always tries both!) * `sometime in June` decide on a soft-date * configurable 'last monday' logic --> ### Usage: ```js var nlp = require('compromise') var halfPast = require('half-past') //apply plugin nlp.plugin(halfPast) let context = { // what 'today', or 'now' is now: '2018-09-10T17:28:32.140Z', // defaults to Date.now() // our assumed timezone, unless given timezone: 'Canada/Eastern', // set our calendar assumptions days: { start: '8:00am', // colloquial start/end of a day end: '6:00pm', }, weeks: { start: 'monday', // some disagree. end: 'friday' }, casual:{ // amount of time returned in 'after June 5th', etc. weeks:2 }, holidays: { 'may day': '2018-06-01', // throws-away year info }, // seasons: [ // defaults to northern-hemisphere (sorry!) // '2018-03-01', //spring // '2019-01-01', //summer // '2019-04-01', //winter // '2019-07-01', //fall // ], // quarters: [ // '2018-01-01', //q1 // '2019-04-01', //q2 // '2019-07-01', //q3 // '2019-09-01', //q4 // ], // semesters: [ // https://en.wikipedia.org/wiki/Academic_term // '2018-09-01', // '2019-01-01', // '2019-04-01', // ], } let result=halfPast(nlp('june 1st'), context) /* [{ start:SpacetimeObject, //you can call .format('iso') or anything you want end:SpacetimeObject, precision:'day', interval:{ unit:'month', amount:3 }, }] */ console.log(result[0].start.format('iso')) // 2018-06-01T11:18:58.040-04:00 ``` ### How it works half-past understands natural language date-forms using the following classification: #### Single dates: ``` [two days after] [the end of] [next] [thursday] [at 2pm] [EST] 'shift' 'section' 'relative' 'unit' 'time' 'timezone' [6 hours before] [the start of] [this] [quarter] ``` #### Combined dates these single-dates can be interpreted as two dates, that share information ``` between [date] and [date] [date] to [date] before [date] after [date] in [date] ``` <!-- ### Examples: ``` explicit templates ✓ "march 2nd""2 march""2 march 2016""march 2nd""2nd of march""2nd of march, 2016""march 2nd, 2016""march 22nd""tuesday march 22nd""tuesday march 22nd, 2016""april the 22nd""22 april""22 april 2016""april 22nd""22nd of april""the 22nd of april, 2016""april 1st, 2016""april 1st""tuesday, april the 1st""tuesday april 1st, 2016" time-based cruft ✓ "july 5th at 2pm""july 5th, 2:12""4:23am july 5th ""july 5th 2pm PST""1pm pacific time, july 5th ""july 5th before noon pacific time""3:23 EST july 5th ""2 oclock july 5th ""july 5 2016 12 oclock PST""3:23 eastern standard time july 5" named holidays ✓ "new years eve""april fools""april fools at 5pm""april fools, 2016" numeric dates ✓ "1999/12/25""1999-12-25""12/25/1999""12-25-1999""25-12-1999""25-12-1999 12:32""25-12-1999 12:32:00""2016/03/13""03/13/2016 at 2:00""2016/13/03""13/03/2016 before 11" punted dates ✓ "two days from now""in two hours from now""two months from today""in one year""a year from now""after a few days""in a few years""two months later""two months in the future""a year forward" adhoc terms ✓ "tomorrow""the next day""the day after next""day after tomorrow" ``` ### Relative to now dates that are relative to given context time ``` relative Year ✓ "q1 2002""fourth quarter, 2002""fourth quarter""spring 2002""this march" ✓ next quarter ✓ next year ✓ this winter ✓ middle of the winter relative Month ✓ "first week of february""second week of february""2nd week of february" relative Week ✓ "this saturday""sunday""mon""tuesday""next wed""this thurs""next friday""friday""this weekend""next weekend""end of this week""next week""start of next week""end of next week""this monday""two mondays from now""3 mondays from now""three sundays from now""next monday""monday next week""the monday after next" ``` ### Ranges ``` explicit between range ✓ "between monday and friday""between next tuesday and next friday""between christmas and new years""between new years and christmas""from monday to friday""from next tuesday to next friday""from christmas to new years" ✓ june 5th to august 7th ✓ june 5th to 7th ✓ between june 5 and august seven now-implicit range (now → then) ✓ "by saturday""by tuesday""before next spring""by 2016-02-06" duration-implicit range (start → end) ✓ "on friday""on next tuesday""on christmas""on 12/12/1992""saturday""july 5th""july 5th 2016""next tuesday""tomorrow" ``` ### Repeating dates ``` Recurring dates ✓ every day ✓ every thursday ✓ every other day ✓ every other wednesday ✓ each monday at 9am ``` ### Calendar-hopping ``` punted dates ✓ 4 days from now ✓ three weeks from today relative range ✓ two weeks later Implicit range -- (assumed now-to-then) ✓ by the end of the year ✓ before christmas soft range - not fully day-defined ✓ middle of the month ✓ start of next week ✓ in august ✓ this spring punted week with day ✓ two saturdays from now ✓ the friday after next ``` --> ### See also * [Sugarjs](https://sugarjs.com/dates/) - by Andrew Plummer * [Chrono](https://github.com/wanasit/chrono) - by Wanasit Tanakitrungruang * [Datejs](http://www.datejs.com/) - by Geoffrey McGill #### Other languages * Clojure - [Duckling](https://duckling.wit.ai/) - by Facebook * Java - [Natty](http://natty.joestelmach.com/) - by Joe Stelmach * Go - [When](https://github.com/olebedev/when) - by Oleg Lebedev * Python - [dateparser](https://github.com/scrapinghub/dateparser) - by ScrapingHub There are also some excellent commercial services for date-parsing, which we've omitted here. MIT