From f8dfd9de23d54b8d21163f8d1436959fd6ae841c Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Thu, 15 Sep 2022 17:03:56 -0500 Subject: [PATCH] cal passes --- Cargo.toml | 3 +- src/client/result/CalendarParsedResult.rs | 72 ++++++++++++++----- .../result/CalendarParsedResultTestCase.rs | 2 +- src/client/result/VEventResultParser.rs | 16 ++++- 4 files changed, 73 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 66a5579..8105bc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,8 @@ encoding = "0.2" rand = "0.8.5" urlencoding = "2.1.2" uriparse = "0.6.4" -chrono = "0.4.22" +chrono = "0.4" +chrono-tz = "0.4" image = {version = "0.24.3", optional = true} imageproc = {version = "0.23.0", optional = true} diff --git a/src/client/result/CalendarParsedResult.rs b/src/client/result/CalendarParsedResult.rs index b11496c..60a612e 100644 --- a/src/client/result/CalendarParsedResult.rs +++ b/src/client/result/CalendarParsedResult.rs @@ -27,7 +27,8 @@ // import java.util.regex.Matcher; // import java.util.regex.Pattern; -use chrono::{DateTime, NaiveDateTime, Utc}; +use chrono::{Date, DateTime, NaiveDateTime, TimeZone, Utc}; +use chrono_tz::Tz; use regex::Regex; use crate::exceptions::Exceptions; @@ -110,7 +111,7 @@ impl CalendarParsedRXingResult { if durationMS < 0i64 { -1i64 } else { - start + durationMS + start + (durationMS / 1000) } } else { Self::parseDate(endString.clone())? @@ -167,29 +168,66 @@ impl CalendarParsedRXingResult { } if when.len() == 8 { // Show only year/month/day - let date_format_string = "%Y%m%d"; + let date_format_string = "%Y%m%dT%H%M%SZ"; // DateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH); // For dates without a time, for purposes of interacting with Android, the resulting timestamp // needs to be midnight of that day in GMT. See: // http://code.google.com/p/android/issues/detail?id=8330 - let dtm = DateTime::parse_from_str(&when, date_format_string).unwrap(); - let dtm = dtm.with_timezone(&Utc); + return match Utc.datetime_from_str(&format!("{}T000000Z", &when,), date_format_string) { + Ok(dtm) => Ok(dtm.timestamp()), + Err(e) => panic!("{}", e), + // Err(e) => Err(Exceptions::ParseException(format!( + // "couldn't parse string: {}", + // e + // ))), + }; + // let dtm = DateTime::parse_from_str(&when, date_format_string).unwrap(); + // let dtm = dtm.with_timezone(&Utc); - // format.setTimeZone(TimeZone.getTimeZone("GMT")); - // return format.parse(when).getTime(); - return Ok(dtm.timestamp()); + // // format.setTimeZone(TimeZone.getTimeZone("GMT")); + // // return format.parse(when).getTime(); + // return Ok(dtm.timestamp()); } // The when string can be local time, or UTC if it ends with a Z if when.len() == 16 && when.chars().nth(15).unwrap() == 'Z' { - let milliseconds = Self::parseDateTimeString(&when[0..15]); - // Calendar calendar = new GregorianCalendar(); - // // Account for time zone difference - // milliseconds += calendar.get(Calendar.ZONE_OFFSET); - // // Might need to correct for daylight savings time, but use target time since - // // now might be in DST but not then, or vice versa - // calendar.setTime(new Date(milliseconds)); - // return milliseconds + calendar.get(Calendar.DST_OFFSET); - return milliseconds; + return match Utc.datetime_from_str(&when, "%Y%m%dT%H%M%SZ") { + Ok(dtm) => Ok(dtm.with_timezone(&Utc).timestamp()), + Err(e) => Err(Exceptions::ParseException(format!( + "couldn't parse string: {}", + e + ))), + }; + // let dtm = DateTime::parse_from_str(&when, "%Y%m%dT%H%M%S").unwrap().with_timezone(&Utc); + // //let milliseconds = Self::parseDateTimeString(&when[0..15]); + // // Calendar calendar = new GregorianCalendar(); + // // // Account for time zone difference + // // milliseconds += calendar.get(Calendar.ZONE_OFFSET); + // // // Might need to correct for daylight savings time, but use target time since + // // // now might be in DST but not then, or vice versa + // // calendar.setTime(new Date(milliseconds)); + // // return milliseconds + calendar.get(Calendar.DST_OFFSET); + // return Ok(dtm.timestamp()); + } + // Try once more, with weird tz formatting + if when.len() > 16 { + let time_part = &when[..15]; + let tz_part = &when[15..]; + let tz_parsed: Tz = match tz_part.parse() { + Ok(time_zone) => time_zone, + Err(e) => { + return Err(Exceptions::ParseException(format!( + "couldn't parse timezone '{}': {}", + tz_part, e + ))) + } + }; + return match Utc.datetime_from_str(time_part, "%Y%m%dT%H%M%S") { + Ok(dtm) => Ok(dtm.with_timezone(&tz_parsed).timestamp()), + Err(e) => Err(Exceptions::ParseException(format!( + "couldn't parse string: {}", + e + ))), + }; } Self::parseDateTimeString(&when) } diff --git a/src/client/result/CalendarParsedResultTestCase.rs b/src/client/result/CalendarParsedResultTestCase.rs index 720f091..cfaf4bc 100644 --- a/src/client/result/CalendarParsedResultTestCase.rs +++ b/src/client/result/CalendarParsedResultTestCase.rs @@ -217,7 +217,7 @@ fn doTest( assert_eq!(description, calRXingResult.getDescription()); assert_eq!(summary, calRXingResult.getSummary()); assert_eq!(location, calRXingResult.getLocation()); - let dateFormat = "%c"; //makeGMTFormat(); + let dateFormat = "%Y%m%dT%H%M%SZ"; //makeGMTFormat(); assert_eq!( startString, format_date_string(calRXingResult.getStartTimestamp(), dateFormat) // dateFormat.format(calRXingResult.getStartTimestamp()) diff --git a/src/client/result/VEventResultParser.rs b/src/client/result/VEventResultParser.rs index f4a3e61..05d51ae 100644 --- a/src/client/result/VEventResultParser.rs +++ b/src/client/result/VEventResultParser.rs @@ -130,7 +130,21 @@ fn matchSingleVCardPrefixedField(prefix: &str, rawText: &str) -> String { if values.is_empty() { "".to_owned() } else { - values.get(0).unwrap().clone() + let tz_mod = if values.len() > 1 { + if let Some(v) = values.get(values.len()-2) { + if let Some(tz_loc) = v.find("TZID=") { + v[tz_loc+5..].to_owned() + }else { + "".to_owned() + } + }else { + "".to_owned() + } + }else { + "".to_owned() + }; + let root_time = values.last().unwrap().clone(); + format!("{}{}",root_time,tz_mod) } } else { "".to_owned()