Skip to main content

chrono_node/
lib.rs

1//! A Rust port of [chrono-node](https://github.com/wanasit/chrono): natural-language date parsing.
2//!
3//! ```
4//! use chrono_node::{parse, JsDate, ReferenceInput};
5//!
6//! let reference = ReferenceInput::Date(JsDate::parse_iso("2012-08-10T09:00:00.000Z").unwrap());
7//! let results = parse("Let's meet", &reference);
8//! assert!(results.is_empty() || results[0].index > 0);
9//! ```
10//!
11//! The port follows upstream closely, file by file. The system time zone is always UTC: a
12//! reference without a time zone is read as UTC (see `PORTING.md`).
13
14// The README is the crates.io page: its usage example runs as a doc test.
15#[cfg(doctest)]
16#[doc = include_str!("../README.md")]
17struct ReadmeDoctests;
18
19pub mod calculation;
20pub mod common;
21pub mod core;
22pub mod locales;
23
24pub use crate::core::chrono::{Chrono, Extracted, Parser, Refiner};
25pub use crate::core::components::{Component, ParsingComponents};
26pub use crate::core::context::{ParsingContext, ParsingOption};
27pub use crate::core::js_date::JsDate;
28pub use crate::core::reference::{ParsingReference, ReferenceInput, ReferenceWithTimezone};
29pub use crate::core::result::ParsingResult;
30pub use crate::core::timezone::TimezoneInput;
31
32/// `chrono.casual` (English).
33pub fn casual() -> &'static Chrono {
34    locales::en::casual()
35}
36
37/// `chrono.strict` (English).
38pub fn strict() -> &'static Chrono {
39    locales::en::strict()
40}
41
42/// `chrono.parse(text, ref)` with the casual English configuration.
43pub fn parse(text: &str, reference: &ReferenceInput) -> Vec<ParsingResult> {
44    casual().parse(text, reference, &ParsingOption::default())
45}
46
47/// `chrono.parseDate(text, ref)` with the casual English configuration.
48pub fn parse_date(text: &str, reference: &ReferenceInput) -> Option<JsDate> {
49    casual().parse_date(text, reference, &ParsingOption::default())
50}
51
52/// The hand-scaffolded named configurations, in this order (then the generated ones).
53const NAMED: [&str; 16] = [
54    "en.casual",
55    "en.strict",
56    "en.GB.casual",
57    "en.GB.strict",
58    "de.casual",
59    "de.strict",
60    "fr.casual",
61    "fr.strict",
62    "sv.casual",
63    "sv.strict",
64    "pt.casual",
65    "pt.strict",
66    "es.casual",
67    "es.strict",
68    "ja.casual",
69    "ja.strict",
70];
71
72/// Every named configuration [`configuration`] knows: the hand-scaffolded ones, then the
73/// generated locales' (`harness/onboard/onboard.js`).
74pub fn configuration_names() -> Vec<&'static str> {
75    NAMED
76        .iter()
77        .copied()
78        .chain(locales::generated().map(|n| n.name))
79        .collect()
80}
81
82/// A named configuration: `en.casual`, `en.strict`, `en.GB.casual`, `en.GB.strict`, `de.casual`, ...
83/// (see [`configuration_names`]).
84pub fn configuration(name: &str) -> Option<&'static Chrono> {
85    match name {
86        "en.casual" => Some(locales::en::casual()),
87        "en.strict" => Some(locales::en::strict()),
88        "en.GB.casual" => Some(locales::en::gb()),
89        "en.GB.strict" => Some(locales::en::gb_strict()),
90        "de.casual" => Some(locales::de::casual()),
91        "de.strict" => Some(locales::de::strict()),
92        "fr.casual" => Some(locales::fr::casual()),
93        "fr.strict" => Some(locales::fr::strict()),
94        "sv.casual" => Some(locales::sv::casual()),
95        "sv.strict" => Some(locales::sv::strict()),
96        "pt.casual" => Some(locales::pt::casual()),
97        "pt.strict" => Some(locales::pt::strict()),
98        "es.casual" => Some(locales::es::casual()),
99        "es.strict" => Some(locales::es::strict()),
100        "ja.casual" => Some(locales::ja::casual()),
101        "ja.strict" => Some(locales::ja::strict()),
102        _ => locales::generated().find(|n| n.name == name).map(|n| (n.chrono)()),
103    }
104}