Crates.io | edtf |
lib.rs | edtf |
version | 0.2.0 |
source | src |
created_at | 2021-09-10 09:26:10.476835 |
updated_at | 2021-10-05 10:02:58.981995 |
description | EDTF parser |
homepage | |
repository | https://github.com/cormacrelf/edtf-rs |
max_upload_size | |
id | 449165 |
size | 232,215 |
This crate implements the Extended Date/Time Format as of the 2019-02 specification. It contains separate implementations for each level 0, 1 (and 2, but not yet). Notes on the choices made in each level are found in in the module level documentation.
[dependencies]
edtf = "0.2.0"
Edtf
object, down to the
leap year.features = ["chrono"]
. Similarly, provides optional
serde implementations under the serde
feature.It is probably not stated often enough that EDTF and ISO 8601 support only one calendar system, a modified proleptic Gregorian calendar with a year zero. ⚠️ This means your old historical records may have to be converted from a different calendar system to be used with EDTF accurately.
Here's a summary for EDTF use:
Years written with BCE
are off by one. 1BCE is year 0000 in EDTF. 100BCE
is -0099 in EDTF.
Positive years (aka CE) are correct already.
Be careful transcribing complete dates written down before the local adoption of the Gregorian calendar. You may be unwittingly transcribing a Julian date, or some other calendar, which will be reinterpreted by EDTF as a proleptic Gregorian date and behave incorrectly.
Check the local adoption of the Gregorian calendar where the historical record was created. Many western jurisdictions adopted it in 1582, but e.g. the UK didn't switch over until 1752-09.
Note that, especially if you're attempting to use EDTF naïvely as a dumb storage area for a year/month/day combination, then you may unwittingly write an invalid ISO date due to the removal of every 25th or so leap year before its adoption. This library validates that parsed EDTF dates actually exist in the ISO calendar.
Here is an online Julian <-> Gregorian converter, made by Stephen P. Morse, the man who designed the Intel 8086 chip. More conversion tools and detailed information about a selection of calendar systems are available on his awesome One Step Webpages site.
One useful piece of info on there is that the Julian calendar year does not generally increment on the January 1. In the UK it increments on 25 March, which used to be the end of the fiscal year there, until they switched to Gregorian and dropped 11 days in the process. Since then, tax day is April 5! Julian dates between 1 January and 25 March are often 'dual dated', i.e.:
... two years separated by a slash. The first year was the year in the Julian calendar in use in that locality, and the second was the year that it would have been if they had changed the year number on January 1.
E.g. 19 February 1683/4.
edtf
crateuse edtf::level_0::Edtf;
let edtf = Edtf::parse("2019-01-07/2020-01").unwrap();
match edtf {
Edtf::Date(d) => println!("date: {}", d),
Edtf::Interval(from, to) => {
println!("interval: {} to {}", from, to);
println!("year parts: {} to {}", from.year(), to.year());
}
Edtf::DateTime(dt) => println!("datetime: {}", dt),
}
// prints:
// interval: 2019-01-07 to 2020-01
// year parts: 2019 to 2020
use edtf::level_1::{Date, Edtf, Certainty, Precision, Terminal};
use edtf::{DateTime, Time, DateComplete, TzOffset};
let edtf = Edtf::parse("2021-07-15");
assert_eq!(edtf, Ok(Edtf::Date(Date::from_ymd(2021, 07, 15))));
let edtf = Edtf::parse("2019-01-XX?").unwrap();
match edtf {
Edtf::Date(date) => {
// precision deconstructs a date into variants like
// 2019, 2019-01, 2019-01-01, 20XX, 201X, 2019-XX, 2019-01-XX, 2019-XX-XX.
// certainty is the ? (Uncertain) / ~ (Approximate) / % (Both) value.
assert_eq!(date.precision(), Precision::DayOfMonth(2019, 01));
assert_eq!(date.certainty(), Certainty::Uncertain);
}
_ => panic!("not matched")
}
let edtf = Edtf::parse("2019-XX/..").unwrap();
match edtf {
Edtf::IntervalFrom(from_date, terminal) => {
assert_eq!(from_date.precision(), Precision::MonthOfYear(2019));
assert_eq!(terminal, Terminal::Open);
}
_ => panic!("not matched"),
}
let edtf = Edtf::parse("Y-12000").unwrap();
match edtf {
Edtf::YYear(yy) => assert_eq!(yy.value(), -12000i64),
_ => panic!("not matched"),
}
let edtf = Edtf::parse("2012-11-30T12:04:56Z").unwrap();
match edtf {
Edtf::DateTime(dt) => {
assert_eq!(dt.date(), DateComplete::from_ymd(2012, 11, 30));
assert_eq!(dt.time(), Time::from_hmsz(12, 04, 56, TzOffset::Utc));
},
_ => panic!("not matched"),
}
// Edtf's parsing + Display implementation is lossless, so you can render back
// out the same string.
let string = "2019-01-XX~/2020-XX";
assert_eq!(Edtf::parse(string).unwrap().to_string(), string);
License: MPL-2.0