Calendar events ported not passing

This commit is contained in:
Henry
2022-09-12 20:08:25 -05:00
parent 56b13b16fb
commit e7fc4a50d3
10 changed files with 757 additions and 629 deletions

View File

@@ -0,0 +1,313 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// package com.google.zxing.client.result;
// import java.text.DateFormat;
// import java.text.ParseException;
// import java.text.SimpleDateFormat;
// import java.util.Calendar;
// import java.util.Date;
// import java.util.GregorianCalendar;
// import java.util.Locale;
// import java.util.TimeZone;
// import java.util.regex.Matcher;
// import java.util.regex.Pattern;
use chrono::{DateTime, NaiveDateTime, Utc};
use regex::Regex;
use crate::exceptions::Exceptions;
use super::{
maybe_append_multiple, maybe_append_string, ParsedRXingResult, ParsedRXingResultType,
ResultParser,
};
const RFC2445_DURATION: &'static str =
"P(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?";
const RFC2445_DURATION_FIELD_UNITS: [i64; 5] = [
7 * 24 * 60 * 60 * 1000i64, // 1 week
24 * 60 * 60 * 1000i64, // 1 day
60 * 60 * 1000i64, // 1 hour
60 * 1000i64, // 1 minute
1000i64, // 1 second
];
const DATE_TIME: &'static str = "[0-9]{8}(T[0-9]{6}Z?)?";
/**
* Represents a parsed result that encodes a calendar event at a certain time, optionally
* with attendees and a location.
*
* @author Sean Owen
*/
pub struct CalendarParsedRXingResult {
summary: String,
start: i64,
startAllDay: bool,
end: i64,
endAllDay: bool,
location: String,
organizer: String,
attendees: Vec<String>,
description: String,
latitude: f64,
longitude: f64,
}
impl ParsedRXingResult for CalendarParsedRXingResult {
fn getType(&self) -> super::ParsedRXingResultType {
ParsedRXingResultType::CALENDAR
}
fn getDisplayRXingResult(&self) -> String {
let mut result = String::with_capacity(100);
maybe_append_string(&self.summary, &mut result);
maybe_append_string(
&Self::format_event(self.startAllDay, self.start),
&mut result,
);
maybe_append_string(&Self::format_event(self.endAllDay, self.end), &mut result);
maybe_append_string(&self.location, &mut result);
maybe_append_string(&self.organizer, &mut result);
maybe_append_multiple(&self.attendees, &mut result);
maybe_append_string(&self.description, &mut result);
result
}
}
impl CalendarParsedRXingResult {
pub fn new(
summary: String,
startString: String,
endString: String,
durationString: String,
location: String,
organizer: String,
attendees: Vec<String>,
description: String,
latitude: f64,
longitude: f64,
) -> Result<Self, Exceptions> {
let start = Self::parseDate(startString.clone())?;
let end = if endString.is_empty() {
let durationMS = Self::parseDurationMS(&durationString);
if durationMS < 0i64 {
-1i64
} else {
start + durationMS
}
} else {
Self::parseDate(endString.clone())?
};
let startAllDay;
let endAllDay;
// try {
// this.start = parseDate(startString);
// } catch (ParseException pe) {
// throw new IllegalArgumentException(pe.toString());
// }
// if (endString == null) {
// long durationMS = parseDurationMS(durationString);
// end = durationMS < 0L ? -1L : start + durationMS;
// } else {
// try {
// this.end = parseDate(endString);
// } catch (ParseException pe) {
// throw new IllegalArgumentException(pe.toString());
// }
// }
startAllDay = startString.len() == 8;
endAllDay = !endString.is_empty() && endString.len() == 8;
Ok(Self {
summary,
start,
startAllDay,
end,
endAllDay,
location,
organizer,
attendees,
description,
latitude,
longitude,
})
}
/**
* Parses a string as a date. RFC 2445 allows the start and end fields to be of type DATE (e.g. 20081021)
* or DATE-TIME (e.g. 20081021T123000 for local time, or 20081021T123000Z for UTC).
*
* @param when The string to parse
* @throws ParseException if not able to parse as a date
*/
fn parseDate(when: String) -> Result<i64, Exceptions> {
let date_time_regex = Regex::new(DATE_TIME).unwrap();
if !date_time_regex.is_match(&when) {
return Err(Exceptions::ParseException(when));
}
if when.len() == 8 {
// Show only year/month/day
let date_format_string = "%Y%m%d";
// 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);
// 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;
}
Self::parseDateTimeString(&when)
}
fn format_event(allDay: bool, date: i64) -> String {
if date < 0 {
return "".to_owned();
}
let format_string = if allDay { "%F" } else { "%c" };
// DateFormat format = allDay
// ? DateFormat.getDateInstance(DateFormat.MEDIUM)
// : DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
// return format.format(date);
NaiveDateTime::from_timestamp(date, 0)
.format(format_string)
.to_string()
}
fn parseDurationMS(durationString: &str) -> i64 {
if durationString.is_empty() {
return -1;
}
let regex = Regex::new(RFC2445_DURATION).unwrap();
if let Some(m) = regex.captures(durationString) {
let mut durationMS = 0i64;
for i in 0..RFC2445_DURATION_FIELD_UNITS.len() {
// for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.length; i++) {
let fieldValue = m.get(i + 1);
if fieldValue.is_some() {
let z = fieldValue.unwrap().as_str().parse::<i64>().unwrap();
durationMS += RFC2445_DURATION_FIELD_UNITS[i] * z;
}
}
durationMS
} else {
-1
}
// if (!m.matches()) {
// return -1L;
// }
// long durationMS = 0L;
// for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.length; i++) {
// String fieldValue = m.group(i + 1);
// if (fieldValue != null) {
// durationMS += RFC2445_DURATION_FIELD_UNITS[i] * Integer.parseInt(fieldValue);
// }
// }
// return durationMS;
}
fn parseDateTimeString(dateTimeString: &str) -> Result<i64, Exceptions> {
if let Ok(dtm) = DateTime::parse_from_str(dateTimeString, "%Y%m%dT%H%M%S") {
Ok(dtm.timestamp())
} else {
Err(Exceptions::ParseException(format!(
"Couldn't parse {}",
dateTimeString
)))
}
// DateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ENGLISH);
// return format.parse(dateTimeString).getTime();
}
pub fn getSummary(&self) -> &String {
&self.summary
}
/**
* @return start time
* @see #getEndTimestamp()
*/
pub fn getStartTimestamp(&self) -> i64 {
self.start
}
/**
* @return true if start time was specified as a whole day
*/
pub fn isStartAllDay(&self) -> bool {
self.startAllDay
}
/**
* @return event end {@link Date}, or -1 if event has no duration
* @see #getStartTimestamp()
*/
pub fn getEndTimestamp(&self) -> i64 {
self.end
}
/**
* @return true if end time was specified as a whole day
*/
pub fn isEndAllDay(&self) -> bool {
self.endAllDay
}
pub fn getLocation(&self) -> &str {
&self.location
}
pub fn getOrganizer(&self) -> &str {
&self.organizer
}
pub fn getAttendees(&self) -> &Vec<String> {
&self.attendees
}
pub fn getDescription(&self) -> &str {
&self.description
}
pub fn getLatitude(&self) -> f64 {
self.latitude
}
pub fn getLongitude(&self) -> f64 {
self.longitude
}
}