Tasks include a COMPLETED timestamp

This commit is contained in:
daladim 2021-04-14 23:09:41 +02:00
parent 8e35f4c579
commit 092765f769
3 changed files with 51 additions and 26 deletions

View file

@ -3,7 +3,7 @@
use std::error::Error;
use chrono::{DateTime, Utc};
use ics::properties::{LastModified, Status, Summary};
use ics::properties::{Completed, LastModified, Status, Summary};
use ics::{ICalendar, ToDo};
use crate::item::Item;
@ -26,6 +26,10 @@ pub fn build_from(item: &Item) -> Result<String, Box<dyn Error>> {
match item {
Item::Task(t) => {
t.completion_date().map(|dt| todo.push(
Completed::new(format_date_time(dt))
));
let status = if t.completed() { Status::completed() } else { Status::needs_action() };
todo.push(status);
},
@ -53,11 +57,13 @@ mod tests {
#[test]
fn test_ical_from_task() {
let cal_id = "http://my.calend.ar/id".parse().unwrap();
let now = format_date_time(&Utc::now());
let now = Utc::now();
let s_now = format_date_time(&now);
let task = Item::Task(Task::new(
let mut task = Item::Task(Task::new(
String::from("This is a task with ÜTF-8 characters"), true, &cal_id
));
task.unwrap_task_mut().set_completed_on(Some(now));
let expected_ical = format!("BEGIN:VCALENDAR\r\n\
VERSION:2.0\r\n\
PRODID:-//{}//{}//EN\r\n\
@ -65,9 +71,10 @@ mod tests {
UID:{}\r\n\
DTSTAMP:{}\r\n\
SUMMARY:This is a task with ÜTF-8 characters\r\n\
COMPLETED:{}\r\n\
STATUS:COMPLETED\r\n\
END:VTODO\r\n\
END:VCALENDAR\r\n", ORG_NAME, PRODUCT_NAME, task.uid(), now);
END:VCALENDAR\r\n", ORG_NAME, PRODUCT_NAME, task.uid(), s_now, s_now);
let ical = build_from(&task);
assert_eq!(ical.unwrap(), expected_ical);

View file

@ -33,6 +33,7 @@ pub fn parse(content: &str, item_id: ItemId, sync_status: SyncStatus) -> Result<
let mut uid = None;
let mut completed = false;
let mut last_modified = None;
let mut completion_date = None;
for prop in &todo.properties {
if prop.name == "SUMMARY" {
name = prop.value.clone();
@ -53,15 +54,12 @@ pub fn parse(content: &str, item_id: ItemId, sync_status: SyncStatus) -> Result<
if prop.name == "DTSTAMP" {
// this property specifies the date and time that the information associated with
// the calendar component was last revised in the calendar store.
last_modified = prop.value.as_ref()
.and_then(|s| {
parse_date_time(s)
.map_err(|err| {
log::warn!("Invalid DTSTAMP: {}", s);
err
})
.ok()
})
last_modified = parse_date_time_from_property(&prop.value)
}
if prop.name == "COMPLETED" {
// this property specifies the date and time that the information associated with
// the calendar component was last revised in the calendar store.
completion_date = parse_date_time_from_property(&prop.value)
}
}
let name = match name {
@ -76,8 +74,13 @@ pub fn parse(content: &str, item_id: ItemId, sync_status: SyncStatus) -> Result<
Some(dt) => dt,
None => return Err(format!("Missing DTSTAMP for item {}, but this is required by RFC5545", item_id).into()),
};
if completion_date.is_none() && completed ||
completion_date.is_some() && !completed
{
log::warn!("Inconsistant iCal data: completion date is {:?} but completion status is {:?}", completion_date, completed);
}
Item::Task(Task::new_with_parameters(name, completed, uid, item_id, sync_status, last_modified))
Item::Task(Task::new_with_parameters(name, uid, item_id, sync_status, last_modified, completion_date))
},
};
@ -94,6 +97,17 @@ fn parse_date_time(dt: &str) -> Result<DateTime<Utc>, chrono::format::ParseError
Utc.datetime_from_str(dt, "%Y%m%dT%H%M%S")
}
fn parse_date_time_from_property(value: &Option<String>) -> Option<DateTime<Utc>> {
value.as_ref()
.and_then(|s| {
parse_date_time(s)
.map_err(|err| {
log::warn!("Invalid timestamp: {}", s);
err
})
.ok()
})
}
enum CurrentType<'a> {