edtf_core/lib.rs
1//! EDTF (Extended Date/Time Format, ISO 8601-2:2019 Annex A) parsing,
2//! validation, level classification, calendar bounds, three-valued temporal
3//! relations, and canonical formatting — conformance levels 0–2, complete.
4//!
5//! `#![no_std]` (requires `alloc`), zero runtime dependencies; JSON support
6//! behind the optional `serde` feature.
7//!
8//! ```
9//! use edtf_core::{Edtf, Bound};
10//!
11//! assert!(edtf_core::is_valid("1985-04-12")); // level 0
12//! assert!(edtf_core::is_valid("2004-06~-11")); // level 2 group qualification
13//! assert!(!edtf_core::is_valid("1985-02-30")); // no such calendar day
14//!
15//! let d = Edtf::parse("1985-04-12?").unwrap();
16//! assert_eq!(d.level(), 1);
17//! assert!(d.is_uncertain());
18//!
19//! // Every expression maps to earliest/latest calendar-day bounds:
20//! let decade = Edtf::parse("156X").unwrap().bounds();
21//! assert_eq!(format!("{}", match decade.earliest { Bound::Date(d) => d, _ => panic!() }), "1560-01-01");
22//! assert_eq!(format!("{}", match decade.latest { Bound::Date(d) => d, _ => panic!() }), "1569-12-31");
23//!
24//! // Display renders the canonical (spec-preferred) form:
25//! let messy = Edtf::parse("?2004-?06-?11").unwrap();
26//! assert_eq!(messy.to_string(), "2004-06-11?");
27//!
28//! // Three-valued comparison under uncertainty (see docs/spec-notes.md D23):
29//! use edtf_core::Relation;
30//! let a = Edtf::parse("1985~").unwrap();
31//! let b = Edtf::parse("199X").unwrap();
32//! assert_eq!(a.relation(&b).definite(), Some(Relation::Before));
33//! ```
34//!
35//! The grammar and every validation decision are documented with ISO section
36//! citations in `docs/spec-notes.md` at the repository root.
37#![no_std]
38
39extern crate alloc;
40
41mod bounds;
42mod display;
43mod parser;
44mod relation;
45mod types;
46
47pub use bounds::{Bound, BoundDate, Bounds};
48pub use relation::{Modality, Relation, Relations};
49pub use types::{
50 Date, DateField, DateTime, Edtf, Interval, IntervalEndpoint, ParseError, Precision, Qualifier,
51 Set, SetElement, SetKind, Time, TimeShift, Year, YearKind,
52};
53
54/// Returns true if `input` is a valid EDTF string (levels 0–2).
55pub fn is_valid(input: &str) -> bool {
56 Edtf::parse(input).is_ok()
57}
58
59/// Parse `input` and return its minimum EDTF conformance level (0, 1 or 2),
60/// or `None` if it is not valid EDTF.
61pub fn level(input: &str) -> Option<u8> {
62 Edtf::parse(input).ok().map(|e| e.level())
63}