GithubHelp home page GithubHelp logo

jokame / chrono Goto Github PK

View Code? Open in Web Editor NEW

This project forked from wanasit/chrono

0.0 2.0 0.0 4.83 MB

A natural language date parser in Javascript

Home Page: http://wanasit.github.io/pages/chrono/

License: MIT License

JavaScript 99.34% HTML 0.30% CSS 0.36%

chrono's Introduction

Chrono

A natural language date parser in Javascript, designed for extracting date information from any given text. (Java version is also available here)

Build Status Coverage Status

Chrono supports most date and time formats, such as :

  • Today, Tomorrow, Yesterday, Last Friday, etc
  • 17 August 2013 - 19 August 2013
  • This Friday from 13:00 - 16.00
  • 5 days ago
  • Sat Aug 17 2013 18:40:39 GMT+0900 (JST)
  • 2014-11-30T08:15:30-05:30

Install

Node.js

npm install chrono-node

Bower

bower install chrono

CDN

Via jsDelivr:

<script src="https://cdn.jsdelivr.net/chrono/VERSION/chrono.min.js"></script>

Rails

source 'https://rails-assets.org' do
  gem 'rails-assets-chrono'
end

Browserify

Chrono's modules are linked and packaged using Browserify on src/chrono.js. By default, chrono.js file exports chrono object as a window global.

browserify src/chrono.js --s chrono -o chrono.js

Usage

Simply pass a string to function chrono.parseDate or chrono.parse.

> var chrono = require('chrono-node')

> chrono.parseDate('An appointment on Sep 12-13') 
Fri Sep 12 2014 12:00:00 GMT-0500 (CDT)
    
> chrono.parse('An appointment on Sep 12-13');
[ { index: 18,
    text: 'Sep 12-13',
    tags: { ENMonthNameMiddleEndianParser: true },
    start: 
     { knownValues: [Object],
       impliedValues: [Object] },
    end: 
     { knownValues: [Object],
       impliedValues: [Object] } } ]

Reference Date

Today's "Friday" is different from last month's "Friday". The meaning of the referenced dates depends on when they are mentioned. Chrono lets you define a reference date using chrono.parse(text, ref) and chrono.parseDate(text, ref).

> chrono.parseDate('Friday', new Date(2012,7,23)); 
Fri Aug 24 2012 12:00:00 GMT+0700 (ICT)

> chrono.parseDate('Friday', new Date(2012,7,1)); 
Fri Aug 03 2012 12:00:00 GMT+0700 (ICT)

Detailed Parsed Results

The function chrono.parse returns detailed parsing results as objects of class chrono.ParsedResult.

var results = chrono.parse('I have an appointment tomorrow from 10 to 11 AM')

results[0].index  // 15
results[0].text   // 'tomorrow from 10 to 11 AM'
results[0].ref    // Sat Dec 13 2014 21:50:14 GMT-0600 (CST)

results[0].start.date()  // Sun Dec 14 2014 10:00:00 GMT-0600 (CST)
results[0].end.date()    // Sun Dec 14 2014 11:00:00 GMT-0600 (CST)

ParsedResult

  • start The parsed date components as a ParsedComponents object
  • end Similar to start but can be null.
  • index The location within the input text of this result
  • text The text this result that appears in the input
  • ref The reference date of this result

ParsedComponents

A group of found date and time components (year, month, hour, etc). ParsedComponents objects consist of knownValues and impliedValues.

  • assign(component, value) Set known value to the component
  • imply(component, value) Set implied value to the component
  • get(component) Get known or implied value for the component
  • isCertain(component) return true if the value of the component is known.
  • date() Create a javascript Date
// Remove the timezone offset of a parsed date and then create the Date object
> var results = new chrono.parse('2016-03-08T01:16:07+02:00'); // Create new ParsedResult Object
> results[0].start.assign('timezoneOffset', 0); // Change value in ParsedComponents Object 'start'
> var d = results[0].start.date(); // Create a Date object
> d.toString(); // Display resulting Date object
'Tue Mar 08 2016 01:16:07 GMT+0000 (GMT)'

Strict vs Casual

Chrono comes with strict mode that parse only formal date patterns.

// 'strict' mode
chrono.strict.parseDate('Today');       // null
chrono.strict.parseDate('Friday');      // null
chrono.strict.parseDate('2016-07-01');  // Fri Jul 01 2016 12:00:00 ...
chrono.strict.parseDate('Jul 01 2016'); // Fri Jul 01 2016 12:00:00 ...

// 'casual' mode (default) 
chrono.parseDate('Today');              // Thu Jun 30 2016 12:00:00 ...
chrono.casual.parseDate('Friday');      // Fri Jul 01 2016 12:00:00 ...
chrono.casual.parseDate('Jul 01 2016'); // Fri Jul 01 2016 12:00:00 ...
chrono.casual.parseDate('Friday');      // Fri Jul 01 2016 12:00:00 ...

Customize Chrono

Chrono’s extraction pipeline are mainly separated into 'parse' and ‘refine’ phases. During parsing, ‘parsers’ (Parser) are used to extract patterns from the input text. The parsed results (ParsedResult) are the combined, sorted, then refine using ‘refiners’ (Refiner). In the refining phase, the results can be combined, filtered-out, or attached with additional information.

Parser

Parser is a module for low-level pattern-based parsing. Ideally, each parser should be designed to handle a single specific date format. User can add new type of parsers for supporting new date formats or languages.

var christmasParser = new chrono.Parser();

// Provide search pattern
christmasParser.pattern = function () { return /Christmas/i } 

// This function will be called when matched pattern is found
christmasParser.extract = function(text, ref, match, opt) { 
    
    // Return a parsed result, that is 25 December
    return new chrono.ParsedResult({
        ref: ref,
        text: match[0],
        index: match.index,
        start: {    
            day: 25, 
            month: 12, 
        }
    });
}

// Create a new custom Chrono. The initial pipeline 'option' can also be specified as 
// - new chrono.Chrono(exports.options.strictOption())
// - new chrono.Chrono(exports.options.casualOption())
var custom = new chrono.Chrono();
custom.parsers.push(christmasParser);

custom.parseDate("I'll arrive at 2.30AM on Christmas night") 
// Wed Dec 25 2013 02:30:00 GMT+0900 (JST)

To create a custom parser, override pattern and extract methods on an object of class chrono.Parser.

  • The pattern method must return RegExp object of searching pattern.
  • The extract method will be called with the match object when the pattern is found. This function must create and return a result (or null to skip).

Refiner

Refiner is a heigher level module for improving or manipurating the results. User can add a new type of refiner to customize Chrono's results or to add some custom logic to Chrono.

var guessPMRefiner = new chrono.Refiner();
guessPMRefiner.refine = function(text, results, opt) {
    // If there is no AM/PM (meridiem) specified, 
    //  let all time between 1:00 - 4:00 be PM (13.00 - 16.00)
    results.forEach(function (result) {
        if (!result.start.isCertain('meridiem') 
            &&  result.start.get('hour') >= 1 && result.start.get('hour') < 4) {
            
            result.start.assign('meridiem', 1);
            result.start.assign('hour', result.start.get('hour') + 12);
        }
    });
    return results;
} 

// Create a new custom Chrono. The initial pipeline 'option' can also be specified as 
// - new chrono.Chrono(exports.options.strictOption())
// - new chrono.Chrono(exports.options.casualOption())
var custom = new chrono.Chrono();
custom.refiners.push(guessPMRefiner);

// This will be parsed as PM.
// > Tue Dec 16 2014 14:30:00 GMT-0600 (CST) 
custom.parseDate("This is at 2.30");

// Unless the 'AM' part is specified
// > Tue Dec 16 2014 02:30:00 GMT-0600 (CST)
custom.parseDate("This is at 2.30 AM");

In the example, a custom refiner is created for assigning PM to parsing results with ambiguous meridiem. The refine method of the refiner class will be called with parsing results (from parsers or other previous refiners). The method must return an array of the new results (which, in this case, we modified those results in place).

Development Guides

This guide explains how to setup chrono project for prospective contributors.

# Clone and install library
git clone https://github.com/wanasit/chrono.git chrono
cd chrono
npm install

# Try running the test
npm run test

Chrono's source files is in src directory. The built bundle (chrono.js and chrono.min.js) can be built by Browserify on src/chrono.js using the following command

npm run make

Parsing date from text is complicated. Sometimes, a small change can have effects on unexpected places. So, Chrono is a heavily tested library. Commits that break a test shouldn't be allowed in any condition.

Chrono's unit testing is based-on Qunit and Karma. During the developement, I recommend running Karma test together with watchify.

# Start karma
npm run karma

# Start watch (run on a different terminal)
npm run watch

chrono's People

Contributors

alexkwolfe avatar benaubin avatar chadfawcett avatar chaseontheweb avatar chena avatar gimenete avatar gregeinfrank avatar jeremyruppel avatar lpoujol avatar mvolz avatar niobos avatar penne12 avatar peterblazejewicz avatar philgooch avatar sawyerh avatar sebastianvommeer avatar shebbys avatar toshmeston avatar victor36max avatar wanasit avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.