summaryrefslogtreecommitdiff
path: root/src/rrulestr.rs
diff options
context:
space:
mode:
authorFredrik Meringdal <fmeringdal@hotmail.com>2020-10-26 20:21:57 +0100
committerFredrik Meringdal <fmeringdal@hotmail.com>2020-10-26 20:21:57 +0100
commit5394f1c753b2752fc9d6409088f0658c797286d6 (patch)
treeedef5c6a8700b8afd579fe31163614f1ec948395 /src/rrulestr.rs
parent0bbc006982cb88d53147bfaec9e1f466caaf5043 (diff)
downloadrust_rrule-5394f1c753b2752fc9d6409088f0658c797286d6.zip
timezones
Diffstat (limited to 'src/rrulestr.rs')
-rw-r--r--src/rrulestr.rs137
1 files changed, 98 insertions, 39 deletions
diff --git a/src/rrulestr.rs b/src/rrulestr.rs
index 1584306..ea3081b 100644
--- a/src/rrulestr.rs
+++ b/src/rrulestr.rs
@@ -1,9 +1,11 @@
use crate::options::*;
use crate::parse_options::parse_options;
use crate::rrule::RRule;
+use crate::datetime::DTime;
use crate::rruleset::RRuleSet;
use chrono::prelude::*;
use chrono::DateTime;
+use chrono_tz::{UTC, Tz};
use once_cell::sync::Lazy;
use regex::Regex;
@@ -16,9 +18,33 @@ static RRULE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?m)^(?:RRULE|EXRULE):"
-fn datestring_to_date(dt: &str) -> DateTime<Utc> {
+fn datestring_to_date(dt: &str, tz: &Tz) -> DTime {
let bits = DATESTR_RE.captures(dt).unwrap();
- return Utc
+ println!("Bits: {:?}", bits);
+ let t = tz
+ .ymd(
+ bits.get(1).unwrap().as_str().parse::<i32>().unwrap(),
+ bits.get(2).unwrap().as_str().parse::<u32>().unwrap(),
+ bits.get(3).unwrap().as_str().parse::<u32>().unwrap(),
+ )
+ .and_hms(
+ bits.get(5).unwrap().as_str().parse::<u32>().unwrap(),
+ bits.get(6).unwrap().as_str().parse::<u32>().unwrap(),
+ bits.get(7).unwrap().as_str().parse::<u32>().unwrap(),
+ );
+ let u = UTC
+ .ymd(
+ bits.get(1).unwrap().as_str().parse::<i32>().unwrap(),
+ bits.get(2).unwrap().as_str().parse::<u32>().unwrap(),
+ bits.get(3).unwrap().as_str().parse::<u32>().unwrap(),
+ )
+ .and_hms(
+ bits.get(5).unwrap().as_str().parse::<u32>().unwrap(),
+ bits.get(6).unwrap().as_str().parse::<u32>().unwrap(),
+ bits.get(7).unwrap().as_str().parse::<u32>().unwrap(),
+ );
+ println!("Diiference : {}", t.timestamp_millis() - u.timestamp_millis());
+ return tz
.ymd(
bits.get(1).unwrap().as_str().parse::<i32>().unwrap(),
bits.get(2).unwrap().as_str().parse::<u32>().unwrap(),
@@ -31,20 +57,35 @@ fn datestring_to_date(dt: &str) -> DateTime<Utc> {
);
}
+struct ParsedDateParam {
+ datetime: DateTime<Tz>,
+ timezone: Tz,
+}
+
+fn parse_date_param(s: &str, reg: Lazy<Regex>) -> ParsedDateParam {
+ let caps = reg.captures(s);
+
+ ParsedDateParam {
+ datetime: UTC.timestamp_nanos(0),
+ timezone: UTC
+ }
+}
+
fn parse_dtstart(s: &str) -> Option<PartialOptions> {
let caps = DTSTART_RE.captures(s);
- println!("captures -----------------------");
- println!("{:?}", caps);
+
match caps {
Some(caps) => {
- let mut options = PartialOptions::new();
- options.dtstart = Some(datestring_to_date(caps.get(2).unwrap().as_str()));
- options.tzid = if let Some(tzid) = caps.get(1) {
- Some(String::from(tzid.as_str()))
+ let tzid: Tz = if let Some(tzid) = caps.get(1) {
+ String::from(tzid.as_str()).parse().unwrap_or(UTC)
} else {
- Some(String::from("UTC"))
+ UTC
};
+
+ let mut options = PartialOptions::new();
+ options.dtstart = Some(datestring_to_date(caps.get(2).unwrap().as_str(), &tzid));
+ options.tzid = Some(tzid);
Some(options)
}
None => None,
@@ -71,14 +112,15 @@ fn parse_rrule(line: &str) -> PartialOptions {
line
};
-
+ println!("Stripped line: {}", stripped_line);
let mut options = parse_dtstart(stripped_line).unwrap_or(PartialOptions::new());
+ println!("Options from dtstart: {:?}", options);
let attrs = RRULE_RE.replace(line, "");
let attrs = attrs.split(";");
for attr in attrs {
- println!("Attr: {}", attr);
+
let l: Vec<&str> = attr.split("=").collect();
let key = l[0];
@@ -86,7 +128,7 @@ fn parse_rrule(line: &str) -> PartialOptions {
if l.len() > 1 {
value = l[1];
}
- println!("Ket: {}", key);
+
match key.to_uppercase().as_str() {
"FREQ" => {
options.freq = Some(from_str_to_freq(value).unwrap());
@@ -138,13 +180,12 @@ fn parse_rrule(line: &str) -> PartialOptions {
"DTSTART" | "TZID" => {
// for backwards compatibility
let dtstart_opts = parse_dtstart(line).unwrap();
- println!("After parsing tzid");
- println!("{:?}", dtstart_opts);
options.tzid = Some(dtstart_opts.tzid.unwrap());
options.dtstart = Some(dtstart_opts.dtstart.unwrap());
}
"UNTIL" => {
- options.until = Some(datestring_to_date(value));
+ // Until is always in UTC
+ options.until = Some(datestring_to_date(value, &UTC));
}
"BYEASTER" => {
options.byeaster = Some(value.parse::<isize>().unwrap());
@@ -189,6 +230,7 @@ fn parse_weekday(val: &str) -> Vec<usize> {
}
fn parse_line(rfc_string: &str) -> Option<PartialOptions> {
+ println!("Parse line: {}", rfc_string);
let re = Regex::new(r"(?m)^\s+|\s+$").unwrap();
let rfc_string = re.replace(rfc_string, "");
if rfc_string.is_empty() {
@@ -262,8 +304,6 @@ fn parse_string(rfc_string: &str) -> PartialOptions {
.collect();
if options.len() == 1 {
- println!("Options i got from str: {}", rfc_string);
- println!("{:?}", options[0]);
return options[0].clone();
}
@@ -273,11 +313,11 @@ fn parse_string(rfc_string: &str) -> PartialOptions {
#[derive(Debug)]
struct ParsedInput {
rrule_vals: Vec<PartialOptions>,
- rdate_vals: Vec<DateTime<Utc>>,
+ rdate_vals: Vec<DTime>,
exrule_vals: Vec<PartialOptions>,
- exdate_vals: Vec<DateTime<Utc>>,
- dtstart: Option<DateTime<Utc>>,
- tzid: Option<String>,
+ exdate_vals: Vec<DTime>,
+ dtstart: Option<DTime>,
+ tzid: Option<Tz>,
}
fn parse_input(s: &str) -> ParsedInput {
@@ -288,12 +328,13 @@ fn parse_input(s: &str) -> ParsedInput {
let PartialOptions {
dtstart,
- mut tzid,
+ tzid,
..
} = parse_dtstart(s).unwrap();
let lines: Vec<&str> = s.split("\n").collect();
+ println!("Lines: {:?}", lines);
for line in &lines {
let parsed_line = break_down_line(line);
match parsed_line.name.to_uppercase().as_str() {
@@ -307,20 +348,35 @@ fn parse_input(s: &str) -> ParsedInput {
rrule_vals.push(parse_string(line));
}
+ "EXRULE" => {
+ if !parsed_line.params.is_empty() {
+ panic!("Unsupported EXRULE value");
+ }
+ if parsed_line.value.is_empty() {
+ continue;
+ }
+
+ exrule_vals.push(parse_string(&parsed_line.value));
+ }
"RDATE" => {
let re = Regex::new(r"(?m)RDATE(?:;TZID=([^:=]+))?").unwrap();
let matches = re.captures(line).unwrap();
- if tzid.is_none() && matches.get(1).is_some() {
- tzid = Some(String::from(matches.get(1).unwrap().as_str()));
+ let mut tz = UTC;
+ if let Some(tzid) = matches.get(1) {
+ tz = String::from(tzid.as_str()).parse().unwrap_or(UTC);
}
- rdate_vals.append(&mut parse_rdate(&parsed_line.value, parsed_line.params));
- }
- "EXRULE" => {
- exrule_vals.push(parse_string(&parsed_line.value));
+ rdate_vals.append(&mut parse_rdate(&parsed_line.value, parsed_line.params, &tz));
}
"EXDATE" => {
- exdate_vals.append(&mut parse_rdate(&parsed_line.value, parsed_line.params));
+ let re = Regex::new(r"(?m)EXDATE(?:;TZID=([^:=]+))?").unwrap();
+ let matches = re.captures(line).unwrap();
+ let tz: Tz = if let Some(tzid) = matches.get(1) {
+ String::from(tzid.as_str()).parse().unwrap_or(UTC)
+ } else {
+ UTC
+ };
+ exdate_vals.append(&mut parse_rdate(&parsed_line.value, parsed_line.params, &tz));
}
"DTSTART" => (),
_ => panic!("Unsupported property: {}", parsed_line.name)
@@ -347,11 +403,16 @@ fn validate_date_param(params: Vec<&str>){
}
}
-fn parse_rdate(rdateval: &str, params: Vec<String>) -> Vec<DateTime<Utc>> {
+// ! works needs to be done here
+fn parse_rdate(rdateval: &str, params: Vec<String>, tz: &Tz) -> Vec<DTime> {
let params: Vec<&str> = params.iter().map(|p| p.as_str()).collect();
validate_date_param(params);
+ // let re_timezone = Regex::new(r"(?m)TZID=(.+):").unwrap();
+ // let caps = re_timezone.captures(text)
+ // let tzid = re_timezone
- rdateval.split(",").map(|datestr| datestring_to_date(datestr)).collect()
+
+ rdateval.split(",").map(|datestr| datestring_to_date(datestr, tz)).collect()
}
@@ -441,7 +502,7 @@ mod test {
#[test]
fn it_works_2() {
- let mut options = build_rruleset("RRULE:UNTIL=19990404T110000Z;DTSTART=19990104T110000Z;FREQ=WEEKLY;BYDAY=TU,WE");
+ let mut options = build_rrule("DTSTART:20120201T093000Z\nRRULE:FREQ=WEEKLY;INTERVAL=5;UNTIL=20130130T230000Z;BYDAY=MO,FR");
println!("?????????????=================?????????????");
println!("{:?}", options);
println!("?????????????=== ALLL ==============?????????????");
@@ -462,13 +523,11 @@ mod test {
#[test]
fn it_works_4() {
- let options = parse_string("RRULE:UNTIL=19990404T110000Z;DTSTART;TZID=America/New_York:19990104T110000Z;FREQ=WEEKLY;BYDAY=TU,WE");
- let parsed_opts = parse_options(&options);
- println!("?????????????=================?????????????");
- println!("{:?}", options);
- println!("?????????????=== PARSED ==============?????????????");
- println!("{:?}", parsed_opts);
- let all = crate::rrule::RRule::new(parsed_opts).all();
+ let mut set = build_rruleset("DTSTART:20120201T120000Z\nRRULE:FREQ=DAILY;COUNT=5\nEXDATE;TZID=Europe/Berlin:20120202T130000Z,20120203T130000Z");
+ println!("?????????????=================??======?????????????");
+ println!("{:?}", set.exdate.iter().map(|d| d.timestamp()).collect::<Vec<i64>>());
+ let all = set.all();
+ println!("{:?}", all.iter().map(|d| d.timestamp()).collect::<Vec<i64>>());
println!("------------------ alll ----------------");
println!("{:?}", all);
}