Compare commits
11 Commits
1d958e8a52
...
3c132528e3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c132528e3 | ||
|
|
1639286189 | ||
|
|
2a04a030f7 | ||
|
|
931edec4a4 | ||
|
|
4154e1aad8 | ||
|
|
4f4e7fd907 | ||
|
|
a627223e8a | ||
|
|
00813e39a9 | ||
|
|
66f533a210 | ||
|
|
233967e177 | ||
|
|
282f653c75 |
301
pttodoer/Cargo.lock
generated
301
pttodoer/Cargo.lock
generated
@@ -2,6 +2,83 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.97"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
|
||||
|
||||
[[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.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "croner"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "516aad5374ea0ea75a0f0f4512fb4e7ad46c5eeff9971cb8ebc8fd74f1cd16c1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
@@ -14,6 +91,29 @@ version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
@@ -30,6 +130,48 @@ version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.154"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.81"
|
||||
@@ -43,6 +185,9 @@ dependencies = [
|
||||
name = "pttodoer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"croner",
|
||||
"regex",
|
||||
"serde_yaml",
|
||||
]
|
||||
|
||||
@@ -55,6 +200,35 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
@@ -116,3 +290,130 @@ name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
@@ -6,4 +6,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.38"
|
||||
croner = "2.0.4"
|
||||
regex = "1.10.4"
|
||||
serde_yaml = "0.9.34"
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
use serde_yaml;
|
||||
use chrono::{DateTime, Local};
|
||||
use chrono::naive::NaiveDateTime;
|
||||
use regex::Regex;
|
||||
use croner;
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", Task::new())
|
||||
@@ -7,25 +11,407 @@ fn main() {
|
||||
#[derive(Debug)]
|
||||
struct Task(serde_yaml::Mapping);
|
||||
//pub todo: String,
|
||||
//pub when: Option<When>,
|
||||
//pub detail: Option<String>,
|
||||
//pub sub: Vec<Task>,
|
||||
|
||||
impl Task {
|
||||
fn new() -> Task {
|
||||
Task(serde_yaml::Mapping::new())
|
||||
}
|
||||
|
||||
fn is_due(&self) -> bool {
|
||||
assert!(false);
|
||||
false
|
||||
self.is_due_now(TS::now())
|
||||
}
|
||||
|
||||
fn is_due_now(&self, now: TS) -> bool {
|
||||
match self.when() {
|
||||
Some(when) => {
|
||||
now.unix() >= when.next(self.ts()).unix()
|
||||
},
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[derive(Debug, Clone)]
|
||||
fn when(&self) -> Option<When> {
|
||||
match self.get("schedule".to_string()) {
|
||||
Some(v) => match When::new(v) {
|
||||
Ok(when) => Some(when),
|
||||
Err(msg) => {
|
||||
eprintln!("Task.when(): {}", msg);
|
||||
return None;
|
||||
},
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn ts(&self) -> TS {
|
||||
match self.get("ts".to_string()) {
|
||||
Some(v) => match TS::new(v) {
|
||||
Ok(ts) => ts,
|
||||
Err(_) => TS::from_unix(0),
|
||||
},
|
||||
None => TS::from_unix(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, k: String) -> Option<String> {
|
||||
match self.0.get(k) {
|
||||
Some(v) => Some(
|
||||
serde_yaml::to_string(v)
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.trim()
|
||||
.trim_start_matches('\'')
|
||||
.trim_end_matches( '\'')
|
||||
.to_string()
|
||||
),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, k: String, v: String) {
|
||||
self.0.insert(
|
||||
serde_yaml::Value::String(k),
|
||||
serde_yaml::Value::String(v)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_task {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn crud() {
|
||||
let mut t = Task::new();
|
||||
t.set("k".to_string(), "v".to_string());
|
||||
assert_eq!(
|
||||
t.get("k".to_string()),
|
||||
Some("v".to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_due_duration() {
|
||||
let mut t = Task::new();
|
||||
assert!(t.is_due());
|
||||
let then = TS::new("2000-01-02T15:00Z".to_string()).unwrap();
|
||||
let now = TS::new("2000-01-02T16:00Z".to_string()).unwrap();
|
||||
t.set("ts".to_string(), then.to_string());
|
||||
t.set("schedule".to_string(), "1h".to_string());
|
||||
assert!(!t.is_due_now(TS::from_unix(now.unix()-1)));
|
||||
assert!(t.is_due_now(TS::from_unix(now.unix())));
|
||||
assert!(t.is_due_now(TS::from_unix(now.unix()+1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_due_schedule() {
|
||||
let mut t = Task::new();
|
||||
assert!(t.is_due());
|
||||
let then = TS::new("2000-01-02T15:00Z".to_string()).unwrap();
|
||||
let now = TS::new("2000-01-02T16:00Z".to_string()).unwrap();
|
||||
t.set("ts".to_string(), then.to_string());
|
||||
t.set("schedule".to_string(), "2000-01-02T16:00Z".to_string());
|
||||
assert!(!t.is_due_now(TS::from_unix(now.unix()-1)));
|
||||
assert!(t.is_due_now(TS::from_unix(now.unix())));
|
||||
assert!(t.is_due_now(TS::from_unix(now.unix()+1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_due_cron() {
|
||||
let mut t = Task::new();
|
||||
assert!(t.is_due());
|
||||
let then = TS::new("2000-01-02T15:00Z".to_string()).unwrap();
|
||||
let now = TS::new("2000-01-02T16:00Z".to_string()).unwrap();
|
||||
t.set("ts".to_string(), then.to_string());
|
||||
t.set("schedule".to_string(), "0 16 * * *".to_string());
|
||||
assert!(!t.is_due_now(TS::from_unix(now.unix()-1)));
|
||||
assert!(t.is_due_now(TS::from_unix(now.unix())));
|
||||
assert!(t.is_due_now(TS::from_unix(now.unix()+1)));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct When(String);
|
||||
|
||||
impl When {
|
||||
fn is_due(&self) -> bool {
|
||||
assert!(false);
|
||||
false
|
||||
fn new(src: String) -> Result<When, String> {
|
||||
match Self::new_duration(src.clone()) {
|
||||
Some(x) => { return Ok(x); },
|
||||
None => {},
|
||||
};
|
||||
match Self::new_ts(src.clone()) {
|
||||
Some(x) => { return Ok(x); },
|
||||
None => {},
|
||||
};
|
||||
match Self::new_cron(src.clone()) {
|
||||
Some(x) => { return Ok(x); },
|
||||
None => {},
|
||||
};
|
||||
Err(format!("cannot parse when: {}", src))
|
||||
}
|
||||
|
||||
fn new_duration(src: String) -> Option<When> {
|
||||
match Duration::new(src.clone()) {
|
||||
Ok(_) => Some(When{0: src.clone()}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_ts(src: String) -> Option<When> {
|
||||
match TS::new(src.clone()) {
|
||||
Ok(_) => Some(When{0: src.clone()}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_cron(src: String) -> Option<When> {
|
||||
match Cron::new(src.clone()) {
|
||||
Ok(_) => Some(When{0: src.clone()}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&self, now: TS) -> TS {
|
||||
match Duration::new(self.0.clone()) {
|
||||
Ok(duration) => {
|
||||
return TS::from_unix(
|
||||
now.unix() + duration.0
|
||||
);
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
match TS::new(self.0.clone()) {
|
||||
Ok(ts) => {
|
||||
return ts;
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
match Cron::new(self.0.clone()) {
|
||||
Ok(x) => {
|
||||
return x.next(now);
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
assert!(false, "invalid when cooked");
|
||||
now
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_when {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse() {
|
||||
match When::new("1d2h3m".to_string()) {
|
||||
Ok(when) => {
|
||||
assert_eq!(
|
||||
1714521600 + 60*3 + 60*60*2 + 60*60*24*1,
|
||||
when.next(
|
||||
TS::new("2024-05-01T00".to_string())
|
||||
.unwrap()
|
||||
).unix()
|
||||
);
|
||||
},
|
||||
Err(err) => assert!(false, "failed to parse when: {}", err),
|
||||
};
|
||||
match When::new("2024-05-01T00:00Z".to_string()) {
|
||||
Ok(when) => {
|
||||
assert_eq!(
|
||||
1714521600 ,
|
||||
when.next(
|
||||
TS::new("2024-05-01T00".to_string())
|
||||
.unwrap()
|
||||
).unix()
|
||||
);
|
||||
},
|
||||
Err(err) => assert!(false, "failed to parse when: {}", err),
|
||||
};
|
||||
match When::new("0 1 * * *".to_string()) {
|
||||
Ok(when) => {
|
||||
assert_eq!(
|
||||
1714521600 + 60*60,
|
||||
when.next(TS::from_unix(1714521600)).unix()
|
||||
);
|
||||
},
|
||||
Err(err) => assert!(false, "failed to parse when: {}", err),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Cron(String);
|
||||
|
||||
impl Cron {
|
||||
fn new(src: String) -> Result<Cron, String> {
|
||||
match croner::Cron::new(src.as_str()).parse() {
|
||||
Ok(_) => Ok(Cron{0: src}),
|
||||
Err(msg) => Err(format!("bad cron: {}", msg)),
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&self, now: TS) -> TS {
|
||||
match croner::Cron::new(self.0.as_str()).parse() {
|
||||
Ok(c) => match c.find_next_occurrence(
|
||||
&DateTime::from_timestamp(now.unix() as i64, 0).unwrap(),
|
||||
true,
|
||||
) {
|
||||
Ok(dt) => {
|
||||
return TS::from_unix(dt.timestamp() as u64);
|
||||
},
|
||||
Err(_) => TS::from_unix(0),
|
||||
},
|
||||
_ => TS::from_unix(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_cron {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse() {
|
||||
match Cron::new("* * * * *".to_string()) {
|
||||
Ok(c) => {}
|
||||
Err(err) => assert!(false, "failed to parse cron: {}", err),
|
||||
};
|
||||
match Cron::new("1 * * * *".to_string()) {
|
||||
Ok(c) => assert_eq!(1714525200+60, c.next(TS::from_unix(1714525200)).unix()),
|
||||
Err(err) => assert!(false, "failed to parse cron: {}", err),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Duration(u64);
|
||||
|
||||
impl Duration {
|
||||
fn new(src: String) -> Result<Duration, String> {
|
||||
if src.len() == 0 {
|
||||
return Err("no empty duration".to_string());
|
||||
}
|
||||
let duration = Regex::new(r"^([0-9]+d)?([0-9]+h)?([0-9]+m)?$").unwrap();
|
||||
match duration.is_match(&src) {
|
||||
false => { return Err("ill formatted duration".to_string()); },
|
||||
_ => {},
|
||||
};
|
||||
let caps = duration.captures(&src).unwrap();
|
||||
let mut sum: u64 = 0;
|
||||
match caps.get(1) {
|
||||
Some(d) => { sum += 60 * 60 * 24 * Self::to_n(d.as_str()); },
|
||||
_ => {},
|
||||
};
|
||||
match caps.get(2) {
|
||||
Some(h) => { sum += 60 * 60 * Self::to_n(h.as_str()); },
|
||||
_ => {},
|
||||
};
|
||||
match caps.get(3) {
|
||||
Some(m) => { sum += 60 * Self::to_n(m.as_str()); },
|
||||
_ => {},
|
||||
};
|
||||
Ok(Duration{0: sum})
|
||||
}
|
||||
|
||||
fn to_n(s: &str) -> u64 {
|
||||
let s = s.to_string();
|
||||
let (s, _) = s.split_at(s.len()-1);
|
||||
match s.parse::<u64>() {
|
||||
Ok(n) => n,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_duration {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse() {
|
||||
match Duration::new("1d2h3m".to_string()) {
|
||||
Ok(d) => assert_eq!(60*60*24 + 60*60*2 + 60*3, d.0),
|
||||
Err(err) => assert!(false, "failed to parse duration: {}", err),
|
||||
};
|
||||
match Duration::new("1d".to_string()) {
|
||||
Ok(d) => assert_eq!(60*60*24, d.0),
|
||||
Err(err) => assert!(false, "failed to parse duration: {}", err),
|
||||
};
|
||||
match Duration::new("2h".to_string()) {
|
||||
Ok(d) => assert_eq!(60*60*2, d.0),
|
||||
Err(err) => assert!(false, "failed to parse duration: {}", err),
|
||||
};
|
||||
match Duration::new("3m".to_string()) {
|
||||
Ok(d) => assert_eq!(60*3, d.0),
|
||||
Err(err) => assert!(false, "failed to parse duration: {}", err),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TS(u64);
|
||||
|
||||
impl TS {
|
||||
fn now() -> TS {
|
||||
Self::from_unix(Local::now().timestamp() as u64)
|
||||
}
|
||||
|
||||
fn from_unix(src: u64) -> TS {
|
||||
TS{0: src}
|
||||
}
|
||||
|
||||
fn new(src: String) -> Result<TS, String> {
|
||||
match DateTime::parse_from_str(
|
||||
&format!("{} +0000", src),
|
||||
"%Y-%m-%dT%H:%MZ %z",
|
||||
) {
|
||||
Ok(v) => { return Ok(TS(v.timestamp() as u64)) },
|
||||
_ => {},
|
||||
};
|
||||
match NaiveDateTime::parse_from_str(
|
||||
&format!("{}:00", src),
|
||||
"%Y-%m-%dT%H:%M",
|
||||
) {
|
||||
Ok(v) => { return Ok(TS(v.timestamp() as u64)) },
|
||||
_ => {},
|
||||
};
|
||||
Err(format!("cannot parse date format from {}", src))
|
||||
}
|
||||
|
||||
fn unix(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn to_string(&self) -> String {
|
||||
DateTime::from_timestamp(self.0 as i64, 0)
|
||||
.unwrap()
|
||||
.format("%Y-%m-%dT%H:%MZ")
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_ts {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse() {
|
||||
match TS::new("2024-05-01T00:00Z".to_string()) {
|
||||
Ok(ts) => {
|
||||
assert_eq!(1714521600, ts.unix());
|
||||
assert_eq!("2024-05-01T00:00Z", ts.to_string());
|
||||
},
|
||||
Err(err) => assert!(false, "failed to parse ts: {}", err),
|
||||
};
|
||||
match TS::new("2024-05-01T00".to_string()) {
|
||||
Ok(ts) => {
|
||||
assert_eq!(1714521600, ts.unix());
|
||||
assert_eq!("2024-05-01T00:00Z", ts.to_string());
|
||||
},
|
||||
Err(err) => assert!(false, "failed to parse ts: {}", err),
|
||||
};
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user