ticker/libticker/src/ics/mod.rs

75 lines
1.9 KiB
Rust

use std::collections::HashMap;
use std::str::FromStr;
use chrono::{NaiveDate, NaiveDateTime};
mod tokenizer;
mod parser;
pub use parser::Parser;
pub trait GetValue<'a, R: 'a> {
fn get(&'a self, key: &'_ str) -> Option<R>;
}
pub type Props = Vec<(String, String)>;
#[derive(Debug, PartialEq)]
pub struct Object {
pub name: String,
pub content: HashMap<String, (Props, String)>,
pub children: Vec<Box<Object>>,
}
impl<'a> GetValue<'a, &'a str> for Object {
fn get(&'a self, key: &'_ str) -> Option<&'a str> {
self.content.get(key)
.map(|(_props, value)| value.as_ref())
}
}
impl<'a> GetValue<'a, String> for Object {
fn get(&self, key: &'_ str) -> Option<String> {
self.content.get(key)
.map(|(_props, value)| value.clone())
}
}
// TODO: TZID, offset
impl<'a> GetValue<'a, Timestamp> for Object {
fn get(&self, key: &'_ str) -> Option<Timestamp> {
let s = self.get(key)?;
Timestamp::from_str(s)
.map_err(|e| println!("Cannot parse date: {:?}", e))
.ok()
}
}
#[derive(Debug, Clone)]
pub enum Timestamp {
Date(NaiveDate),
DateTime(NaiveDateTime),
}
impl FromStr for Timestamp {
type Err = String;
fn from_str(s: &'_ str) -> Result<Self, Self::Err> {
NaiveDateTime::parse_from_str(s, "%Y%m%dT%H%M%SZ")
.or_else(|_| NaiveDateTime::parse_from_str(s, "%Y%m%dT%H%M%S"))
.map(Timestamp::DateTime)
.or_else(|_|
NaiveDate::parse_from_str(s, "%Y%m%d")
.map(Timestamp::Date)
)
.map_err(|e| format!("Cannot parse date: {:?}", e))
}
}
impl Timestamp {
pub fn or_hms(self, hour: u32, min: u32, sec: u32) -> NaiveDateTime {
match self {
Timestamp::Date(date) => date.and_hms(hour, min, sec),
Timestamp::DateTime(date_time) => date_time,
}
}
}