{"id":13447053,"url":"https://github.com/wanasit/chrono","last_synced_at":"2025-09-09T20:41:08.569Z","repository":{"id":4181142,"uuid":"5297944","full_name":"wanasit/chrono","owner":"wanasit","description":"A natural language date parser in Javascript","archived":false,"fork":false,"pushed_at":"2025-08-30T02:22:36.000Z","size":11309,"stargazers_count":5031,"open_issues_count":125,"forks_count":358,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-08-30T03:23:20.641Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wanasit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2012-08-04T19:13:24.000Z","updated_at":"2025-08-30T02:22:02.000Z","dependencies_parsed_at":"2024-11-13T20:06:46.674Z","dependency_job_id":"0af0c641-b3fb-4648-8db4-7d3a5aee15ad","html_url":"https://github.com/wanasit/chrono","commit_stats":{"total_commits":840,"total_committers":97,"mean_commits":8.65979381443299,"dds":0.5357142857142857,"last_synced_commit":"80c126ba1df547c2092cb4412be5c4f1b1979f8d"},"previous_names":["berryboy/chrono"],"tags_count":78,"template":false,"template_full_name":null,"purl":"pkg:github/wanasit/chrono","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanasit%2Fchrono","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanasit%2Fchrono/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanasit%2Fchrono/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanasit%2Fchrono/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wanasit","download_url":"https://codeload.github.com/wanasit/chrono/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanasit%2Fchrono/sbom","scorecard":{"id":234539,"data":{"date":"2025-07-21","repo":{"name":"github.com/wanasit/chrono","commit":"ce58eda9921e284c8c2cf517162e18209db3a6ea"},"scorecard":{"version":"v5.2.1-24-gc29a04d4","commit":"c29a04d46d1570393e94662bc34e9906398e1bfa"},"score":4.4,"checks":[{"name":"Code-Review","score":2,"reason":"Found 5/19 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#cii-best-practices"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 4 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#maintained"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#license"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/documentation.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#binary-artifacts"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/documentation.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/wanasit/chrono/documentation.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/wanasit/chrono/test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/wanasit/chrono/test.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/documentation.yml:24","Warn: npmCommand not pinned by hash: .github/workflows/test.yml:14","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#fuzzing"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 16 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-xffm-g5w8-qvg7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T05:23:18.412Z","repository_id":4181142,"created_at":"2025-08-17T05:23:18.417Z","updated_at":"2025-08-17T05:23:18.417Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274358644,"owners_count":25270680,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T05:01:06.969Z","updated_at":"2025-09-09T20:41:08.562Z","avatar_url":"https://github.com/wanasit.png","language":"TypeScript","readme":"# Chrono (v2)\n\nA natural language date parser in Javascript. \n\n![Build Status](https://github.com/github/docs/actions/workflows/test.yml/badge.svg)\n[![Coverage Status](https://img.shields.io/coverallsCoverage/github/wanasit/chrono.svg)](https://coveralls.io/r/wanasit/chrono?branch=master)\n\nIt is designed to handle most date/time format and extract information from any given text:\n\n* _Today_, _Tomorrow_, _Yesterday_, _Last Friday_, etc\n* _17 August 2013 - 19 August 2013_\n* _This Friday from 13:00 - 16.00_\n* _5 days ago_\n* _2 weeks from now_\n* _Sat Aug 17 2013 18:40:39 GMT+0900 (JST)_\n* _2014-11-30T08:15:30-05:30_\n\n### Installation\n\nWith npm:\n```bash\n$ npm install --save chrono-node\n```\n    \n```javascript\nimport * as chrono from 'chrono-node';\n\nchrono.parseDate('An appointment on Sep 12-13'); \n```\nFor Node.js:\n```javascript\nconst chrono = require('chrono-node');\n\n// or `import chrono from 'chrono-node'` for ECMAScript\n```\n\n### What's changed in the v2\nFor Users\n* Chrono’s default now handles only international English. While in the previous version, it tried to parse with all known languages.\n* The current fully supported languages are `en`, `ja`, `fr`, `nl`, `ru` and `uk` (`de`, `es`, `pt`, and `zh.hant` are partially supported). \n\nFor contributors and advanced users\n* The project is rewritten in TypeScript\n* New [Parser](#parser) and [Refiner](#refiner) interface \n* New source code structure. All parsers, refiners, and configuration should be under a locale directory (See. `locales/en`)\n\n**Note: [v1.x.x](https://github.com/wanasit/chrono/tree/v1.x.x) will still be supported for the time being.**\n\n## Usage\n\nSimply pass a `string` to functions `chrono.parseDate` or `chrono.parse`. \n\n```javascript\nimport * as chrono from 'chrono-node';\n\nchrono.parseDate('An appointment on Sep 12-13');\n// Fri Sep 12 2014 12:00:00 GMT-0500 (CDT)\n    \nchrono.parse('An appointment on Sep 12-13');\n/* [{ \n    index: 18,\n    text: 'Sep 12-13',\n    start: ...\n}] */\n```\n\nFor more advanced usage, here is the typescript definition of the `parse` function:\n```typescript\nparse(text: string, ref?: ParsingReference, option?: ParsingOption): ParsedResult[] {...}\n```\n\n#### Parsing Reference (Date / Timezone)\n\nToday's \"Friday\" is different from last month's \"Friday\". \nThe meaning of the referenced dates depends on when and where they are mentioned. \nChrono lets you define the reference as `Date` or `ParsingReference` object:\n\n```javascript\n// (Note: the examples run on JST timezone)\n\nchrono.parseDate('Friday', new Date(2012, 8 - 1, 23)); \n// Fri Aug 24 2012 12:00:00 GMT+0900 (JST)\n\nchrono.parseDate('Friday', new Date(2012, 8 - 1, 1)); \n// Fri Aug 03 2012 12:00:00 GMT+0900 (JST)\n\nchrono.parseDate(\"Friday at 4pm\", {\n    // Wed Jun 09 2021 21:00:00 GMT+0900 (JST)\n    // = Wed Jun 09 2021 07:00:00 GMT-0500 (CDT)\n    instant: new Date(1623240000000), \n    timezone: \"CDT\",\n})\n// Sat Jun 12 2021 06:00:00 GMT+0900 (JST)\n// = Fri Jun 11 2021 16:00:00 GMT-0500 (CDT)\n```\n\n#### ParsingReference\n* `instant?: Date` The instant when the input is written or mentioned\n* `timezone?: string | number` The timezone where the input is written or mentioned. \n  Support minute-offset (number) and timezone name (e.g. \"GMT\", \"CDT\")\n\n### Parsing Options\n\n`forwardDate` (boolean) to assume the results should happen after the reference date (forward into the future)\n\n```javascript\nconst referenceDate = new Date(2012, 7, 25);\n// Sat Aug 25 2012 00:00:00 GMT+0900 -- The reference date was Saturday\n\nchrono.parseDate('Friday', referenceDate);\n// Fri Aug 24 2012 12:00:00 GMT+0900 (JST) -- The day before was Friday\n\nchrono.parseDate('Friday', referenceDate, { forwardDate: true });\n// Fri Aug 31 2012 12:00:00 GMT+0900 (JST) -- The following Friday\n```\n\n`timezones` Override or add custom mappings between timezone abbreviations and offsets. Use this when you want Chrono to parse certain text into a given timezone offset. Chrono supports both unambiguous (normal) timezone mappings and ambigous mappings where the offset is different during and outside of daylight savings.\n\n```javascript\n// Chrono doesn't understand XYZ, so no timezone is parsed\nchrono.parse('at 10:00 XYZ', new Date(2023, 3, 20))\n// \"knownValues\": {\"hour\": 10, \"minute\": 0}\n\n// Make Chrono parse XYZ as offset GMT-0300 (180 minutes)\nchrono.parse('at 10:00 XYZ', new Date(2023, 3, 20), { timezones: { XYZ: -180 } })\n// \"knownValues\": {\"hour\": 10, \"minute\": 0, \"timezoneOffset\": -180}\n\n// Make Chrono parse XYZ as offset GMT-0300 outside of DST, and GMT-0200 during DST. Assume DST is between \nimport { getLastDayOfMonthTransition } from \"timezone\";\nimport { Weekday, Month } from \"parsing\";\n\nconst parseXYZAsAmbiguousTz = {\n  timezoneOffsetDuringDst: -120,\n  timezoneOffsetNonDst: -180,\n  dstStart: (year: number) =\u003e getLastWeekdayOfMonth(year, Month.FEBRUARY, Weekday.SUNDAY, 2),\n  dstEnd: (year: number) =\u003e getLastWeekdayOfMonth(year, Month.SEPTEMBER, Weekday.SUNDAY, 3)\n};\n// Parsing a date which falls within DST\nchrono.parse('Jan 1st 2023 at 10:00 XYZ', new Date(2023, 3, 20), { timezones: { XYZ: parseXYZAsAmbiguousTz } })\n// \"knownValues\": {\"month\": 1, ..., \"timezoneOffset\": -180}\n\n// Parsing a non-DST date\nchrono.parse('Jun 1st 2023 at 10:00 XYZ', new Date(2023, 3, 20), { timezones: { XYZ: parseXYZAsAmbiguousTz } })\n// \"knownValues\": {\"month\": 6, ..., \"timezoneOffset\": -120}\n```\n\n### Parsed Results and Components\n\n#### ParsedResult\n* `refDate: Date` The [reference date](#reference-date) of this result\n* `index: number` The location within the input text of this result  \n* `text: string`  The text this result that appears in the input \n* `start: ParsedComponents` The parsed date components as a [ParsedComponents](#parsedcomponents) object\n* `end?: ParsedComponents`  Similar to `start`\n* `date: () =\u003e Date` Create a javascript Date\n\n#### ParsedComponents\n* `get: (c: Component) =\u003e number | null`    Get known or implied value for the component\n* `isCertain: (c: Component) =\u003e boolean`    Check if the component has a known value\n* `date: () =\u003e Date`    Create a javascript Date\n\nFor example:\n```js\nconst results = chrono.parse('I have an appointment tomorrow from 10 to 11 AM');\n\nresults[0].index;     // 22\nresults[0].text;      // 'tomorrow from 10 to 11 AM'\nresults[0].refDate;   // Sat Dec 13 2014 21:50:14 GMT-0600 (CST)\n\n// `start` is Sat Dec 14 2014 10:00:00\nresults[0].start.get('day');    // 14 (the 14th, the day after refDate)\nresults[0].start.get('month');  // 12 (or December)\nresults[0].start.get('hour');   // 10 \nresults[0].start.date();        // Sun Dec 14 2014 10:00:00 GMT-0600 (CST)\n\n...\nresults[0].end.date();  // Sun Dec 14 2014 11:00:00 GMT-0600 (CST)\n```\n\n### Strict vs Casual configuration\n\nChrono comes with `strict` mode that parse only formal date patterns. \n\n```js\n// 'strict' mode\nchrono.strict.parseDate('Today');       // null\nchrono.strict.parseDate('Friday');      // null\nchrono.strict.parseDate('2016-07-01');  // Fri Jul 01 2016 12:00:00 ...\nchrono.strict.parseDate('Jul 01 2016'); // Fri Jul 01 2016 12:00:00 ...\n\n// 'casual' mode (default) \nchrono.parseDate('Today');              // Thu Jun 30 2016 12:00:00 ...\nchrono.casual.parseDate('Friday');      // Fri Jul 01 2016 12:00:00 ...\nchrono.casual.parseDate('2016-07-01');  // Fri Jul 01 2016 12:00:00 ...\nchrono.casual.parseDate('Jul 01 2016'); // Fri Jul 01 2016 12:00:00 ...\n```\n\n### Locales\n\nBy default, Chrono is configured to handle **only international English**. \nThis differs from the previous version of Chrono that would try all locales by default.\n\nThere are several locales supported contributed by multiple developers under `./locales` directory.\n\n```js\n// default English (US)\nchrono.parseDate('6/10/2018');    \n\nchrono.en.parseDate('6/10/2018');       // June 10th, 2018\nchrono.en.GB.parseDate('6/10/2018');    // October 6th, 2018\n\nchrono.ja.parseDate('昭和６４年１月７日'); \n```\n\nCurrent supported locale options are: `en`, `ja`, `fr`, `nl`, `ru` and `uk` (`de`, `pt`, and `zh.hant` are partially supported).\n\n#### Importing specific locales\n\nChrono exports all locale options by default for simplicity. However, this can cause issues when using Chrono if you're using a Node.js runtime that was built with the Intl module disabled (with the `--without-intl` flag), such as: \n```\nInvalid regular expression: /* omitted */: Invalid property name in character class\n```\n\nThis is because the Intl module is required to handle special characters, such as Cyrillic (`ru`).\n\nTo avoid this, you can specify only the locale(s) you want to import:\n```typescript\n// CommonJS (Node.js)\nconst chrono = require('chrono-node/en')\n\n// ECMAScript\nimport chrono from 'chrono-node/en'\n\n// TypeScript\n// Warning: `moduleResolution` must be set to `node16` or `nodeNext` in tsconfig.json`\nimport * as chrono from 'chrono-node/en'\n```\n\n## Customize Chrono\n\nChrono’s extraction pipeline configuration consists of `parsers: Parser[]` and `refiners: Refiner[]`.\n\n* First, each parser independently extracts patterns from input text input and create parsing results  ([ParsingResult](#parsedresult)).\n* Then, the parsing results are combined, sorted, and refined with the refiners. In the refining phase, the results can be filtered-out, merged, or attached with additional information.\n\n### Parser\n\n```typescript\ninterface Parser {\n    pattern: (context: ParsingContext) =\u003e RegExp,\n    extract: (context: ParsingContext, match: RegExpMatchArray) =\u003e\n        (ParsingComponents | ParsingResult | {[c in Component]?: number} | null)\n}\n```\n\nParser is a module for low-level pattern-based parsing. \nIdeally, each parser should be designed to handle a single specific date format. \n\nUser can create a new parser for supporting new date formats or languages\n by providing RegExp pattern `pattern()` and extracting result or components from the RegExp match `extract()`.\n\n```javascript\nconst custom = chrono.casual.clone();\ncustom.parsers.push({\n    pattern: () =\u003e { return /\\bChristmas\\b/i },\n    extract: (context, match) =\u003e {\n        return {\n            day: 25, month: 12\n        }\n    }\n});\n\ncustom.parseDate(\"I'll arrive at 2.30AM on Christmas night\");\n// Wed Dec 25 2013 02:30:00 GMT+0900 (JST)\n// 'at 2.30AM on Christmas'\n```\n\n### Refiner\n\n```typescript\ninterface Refiner {\n    refine: (context: ParsingContext, results: ParsingResult[]) =\u003e ParsingResult[]\n}\n```\n\nRefiner is a higher level module for improving or manipulating the results. User can add a new type of refiner to customize Chrono's results or to add some custom logic to Chrono.\n\n```javascript\nconst custom = chrono.casual.clone();\ncustom.refiners.push({\n    refine: (context, results) =\u003e {\n        // If there is no AM/PM (meridiem) specified,\n        //  let all time between 1:00 - 4:00 be PM (13.00 - 16.00)\n        results.forEach((result) =\u003e {\n            if (!result.start.isCertain('meridiem') \u0026\u0026\n                result.start.get('hour') \u003e= 1 \u0026\u0026 result.start.get('hour') \u003c 4) {\n\n                result.start.assign('meridiem', 1);\n                result.start.assign('hour', result.start.get('hour') + 12);\n            }\n        });\n        return results;\n    }\n});\n\n// This will be parsed as PM.\n// \u003e Tue Dec 16 2014 14:30:00 GMT-0600 (CST) \ncustom.parseDate(\"This is at 2.30\");\n\n// Unless the 'AM' part is specified\n// \u003e Tue Dec 16 2014 02:30:00 GMT-0600 (CST)\ncustom.parseDate(\"This is at 2.30 AM\");\n```\n\nIn the example, the custom refiner assigns PM to parsing results with ambiguous [meridiem](http://en.wikipedia.org/wiki/12-hour_clock). \nThe `refine` method of the refiner class will be called with parsing [results](#parsedresult) (from [parsers](#parser) or other previous refiners). \nThe method must return an array of the new results (which, in this case, we modified those results in place).\n\n### More documentation\n\nCheckout the Typescript Documentation in the project's [Github page](http://wanasit.github.io/chrono/).\n\n## Development Guides\n\nThis guide explains how to set up chrono project for prospective contributors.\n\n```bash\n# Clone and install library\n$ git clone https://github.com/wanasit/chrono.git chrono\n$ cd chrono\n$ npm install\n\n```\n\nParsing date from text is complicated. A small change can have effects on unexpected places. \nSo, Chrono is a heavily tested library. \nCommits that break a test shouldn't be allowed in any condition.\n\nChrono's unit testing is based-on [Jest](https://facebook.github.io/jest/). \n\n```bash\n# Run the test\n$ npm run test\n\n# Run the test in watch mode\n$ npm run watch\n```\n\nChrono's source files is in `src` directory. \nThe built bundle (`dist/*`) is created by running [Webpack](https://webpack.js.org/) via the following command \n\n```bash\n$ npm run build\n```\n\n","funding_links":[],"categories":["JavaScript","TypeScript","Uncategorized","others"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwanasit%2Fchrono","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwanasit%2Fchrono","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwanasit%2Fchrono/lists"}