diff --git a/Cargo.lock b/Cargo.lock index ef02a81..f46d9ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,12 +73,6 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - [[package]] name = "chrono" version = "0.4.19" @@ -92,28 +86,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "chrono-tz" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c01c1c607d25c71bbaa67c113d6c6b36c434744b4fd66691d711b5b1bc0c8b" -dependencies = [ - "chrono", - "chrono-tz-build", - "phf", -] - -[[package]] -name = "chrono-tz-build" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" -dependencies = [ - "parse-zoneinfo", - "phf", - "phf_codegen", -] - [[package]] name = "clap" version = "2.33.3" @@ -153,17 +125,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "heck" version = "0.3.3" @@ -225,15 +186,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -[[package]] -name = "parse-zoneinfo" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" -dependencies = [ - "regex", -] - [[package]] name = "pest" version = "2.1.3" @@ -277,51 +229,6 @@ dependencies = [ "sha-1", ] -[[package]] -name = "phf" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_codegen" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", - "uncased", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -364,61 +271,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - [[package]] name = "sha-1" version = "0.8.2" @@ -431,12 +283,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "siphasher" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" - [[package]] name = "strsim" version = "0.8.0" @@ -524,11 +370,11 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", - "chrono-tz", "pest", "pest_derive", "structopt", "thiserror", + "tzfile", ] [[package]] @@ -537,21 +383,22 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +[[package]] +name = "tzfile" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f59c22c42a2537e4c7ad21a4007273bbc5bebed7f36bc93730a5780e22a4592e" +dependencies = [ + "byteorder", + "chrono", +] + [[package]] name = "ucd-trie" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" -[[package]] -name = "uncased" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-segmentation" version = "1.8.0" diff --git a/Cargo.toml b/Cargo.toml index ebe71f7..d0f72cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,8 @@ edition = "2018" [dependencies] anyhow = "1.0.45" chrono = "0.4.19" -chrono-tz = "0.6.0" pest = "2.1.3" pest_derive = "2.1.0" structopt = "0.3.25" thiserror = "1.0.30" +tzfile = "0.1.3" diff --git a/src/files.rs b/src/files.rs index aed2955..0fbb151 100644 --- a/src/files.rs +++ b/src/files.rs @@ -2,7 +2,8 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::{fs, io, result}; -use chrono_tz::Tz; +use chrono::{DateTime, Utc}; +use tzfile::Tz; use self::commands::File; @@ -13,7 +14,7 @@ mod parse; #[derive(Debug)] pub struct Files { files: HashMap, - timezone: Option, + timezone: Tz, } #[derive(Debug, thiserror::Error)] @@ -25,9 +26,9 @@ pub enum Error { #[error("{file1} has time zone {tz1} but {file2} has time zone {tz2}")] TzConflict { file1: PathBuf, - tz1: Tz, + tz1: String, file2: PathBuf, - tz2: Tz, + tz2: String, }, } @@ -35,20 +36,15 @@ pub type Result = result::Result; impl Files { pub fn load(path: &Path) -> Result { - let mut new = Self { - files: HashMap::new(), - timezone: None, - }; - - new.load_file(path)?; - new.determine_timezone()?; - - Ok(new) + let mut files = HashMap::new(); + Self::load_file(&mut files, path)?; + let timezone = Self::determine_timezone(&files)?; + Ok(Self { files, timezone }) } - fn load_file(&mut self, path: &Path) -> Result<()> { + fn load_file(files: &mut HashMap, path: &Path) -> Result<()> { let canon_path = path.canonicalize()?; - if self.files.contains_key(&canon_path) { + if files.contains_key(&canon_path) { // We've already loaded this exact file. return Ok(()); } @@ -57,39 +53,43 @@ impl Files { let file = parse::parse(path, &content)?; let includes = file.includes.clone(); - self.files.insert(canon_path, file); + files.insert(canon_path, file); for include in includes { - self.load_file(&include)?; + Self::load_file(files, &include)?; } Ok(()) } - fn determine_timezone(&mut self) -> Result<()> { - let mut found: Option<(PathBuf, Tz)> = None; + fn determine_timezone(files: &HashMap) -> Result { + let mut found: Option<(PathBuf, String)> = None; - for file in self.files.values() { - if let Some(file_tz) = file.timezone { + for file in files.values() { + if let Some(file_tz) = &file.timezone { if let Some((found_name, found_tz)) = &found { - if *found_tz != file_tz { + if found_tz != file_tz { return Err(Error::TzConflict { file1: found_name.clone(), - tz1: *found_tz, + tz1: found_tz.clone(), file2: file.name.clone(), - tz2: file_tz, + tz2: file_tz.clone(), }); } } else { - found = Some((file.name.clone(), file_tz)); + found = Some((file.name.clone(), file_tz.clone())); } } } - if let Some((_, tz)) = found { - self.timezone = Some(tz); - } + Ok(if let Some((_, tz)) = found { + Tz::named(&tz)? + } else { + Tz::local()? + }) + } - Ok(()) + pub fn now(&self) -> DateTime<&Tz> { + Utc::now().with_timezone(&&self.timezone) } } diff --git a/src/files/commands.rs b/src/files/commands.rs index 79139f0..58dbd92 100644 --- a/src/files/commands.rs +++ b/src/files/commands.rs @@ -1,7 +1,6 @@ use std::path::PathBuf; use chrono::NaiveDate; -use chrono_tz::Tz; #[derive(Debug)] pub struct Time { @@ -331,6 +330,6 @@ pub enum Command { pub struct File { pub name: PathBuf, pub includes: Vec, - pub timezone: Option, + pub timezone: Option, pub commands: Vec, } diff --git a/src/files/parse.rs b/src/files/parse.rs index dbfe574..129ceda 100644 --- a/src/files/parse.rs +++ b/src/files/parse.rs @@ -2,7 +2,6 @@ use std::path::{Path, PathBuf}; use std::result; use chrono::NaiveDate; -use chrono_tz::Tz; use pest::error::ErrorVariant; use pest::iterators::Pair; use pest::prec_climber::{Assoc, Operator, PrecClimber}; @@ -38,15 +37,9 @@ fn parse_include(p: Pair) -> String { p.into_inner().next().unwrap().as_str().to_string() } -fn parse_timezone(p: Pair) -> Result { +fn parse_timezone(p: Pair) -> String { assert_eq!(p.as_rule(), Rule::timezone); - let span = p.as_span(); - p.into_inner() - .next() - .unwrap() - .as_str() - .parse() - .map_err(|_| error(span, "invalid timezone")) + p.into_inner().next().unwrap().as_str().trim().to_string() } fn parse_number(p: Pair) -> i32 { @@ -720,7 +713,7 @@ fn parse_command(p: Pair, file: &mut File) -> Result<()> { file.includes.push(parent.join(parse_include(p))); } Rule::timezone => match file.timezone { - None => file.timezone = Some(parse_timezone(p)?), + None => file.timezone = Some(parse_timezone(p)), Some(_) => fail(p.as_span(), "cannot set timezone multiple times")?, }, Rule::task => file.commands.push(Command::Task(parse_task(p)?)), diff --git a/src/main.rs b/src/main.rs index d800e6e..4db3574 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,6 @@ pub struct Opt { fn main() -> anyhow::Result<()> { let opt = Opt::from_args(); let files = Files::load(&opt.file)?; - println!("{:#?}", files); + println!("{}", files.now().format("%F %T %Z")); Ok(()) }