From 4c5cf1dec7d8d41cf0e74d5af557a379d66633a1 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Mon, 2 Apr 2018 13:14:19 +0200 Subject: [PATCH] Added parsing of start/end dates (without time) --- src/calanonsync/caldav.go | 27 +++++++++++++++++++++------ src/calanonsync/caldav_test.go | 25 +++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/calanonsync/caldav.go b/src/calanonsync/caldav.go index 576dff4..2516809 100644 --- a/src/calanonsync/caldav.go +++ b/src/calanonsync/caldav.go @@ -53,7 +53,7 @@ func (i ICal) UID() string { // the event data of the ICal structure. Timezone information are ignored. // The time is therefore either a local time or a UTC time, depending on // the notation. -func (i ICal) getTimeField(f string) time.Time { +func (i ICal) getTimeField(f string) (t time.Time, isDate bool) { for _, s := range i.eventData { if strings.HasPrefix(s, f) { st := s[strings.LastIndex(s, ":")+1:] @@ -64,14 +64,21 @@ func (i ICal) getTimeField(f string) time.Time { st = st[:len(st)-1] zone = time.UTC } - t, err := time.ParseInLocation(ICAL_TIME, st, zone) + var err error + if strings.Contains(s, ";VALUE=DATE") { + t, err = time.ParseInLocation(ICAL_DATE, st, zone) + isDate = true + } else { + t, err = time.ParseInLocation(ICAL_TIME, st, zone) + isDate = false + } if err != nil { log.Printf("Cannot decode %s '%s': %s", f, st, err) } - return t + return } } - return time.Time{} + return time.Time{}, false } var fieldMatch = regexp.MustCompile(`^(\w+)[;:]`) @@ -133,12 +140,20 @@ func (ical *ICal) Update(newStart, newEnd time.Time, wholeDay bool) { // Retrieve the start time of the event. func (i ICal) Start() time.Time { - return i.getTimeField("DTSTART") + t, _ := i.getTimeField("DTSTART") + return t } // Retrieve the end time of the event. func (i ICal) End() time.Time { - return i.getTimeField("DTEND") + t, isDate := i.getTimeField("DTEND") + if isDate { + // If the end date is a date only, we need to move that to the + // 00:00 time one day ahead. + t = t.AddDate(0, 0, 1) + } + + return t } func (i *ICal) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { diff --git a/src/calanonsync/caldav_test.go b/src/calanonsync/caldav_test.go index fb4fc45..3fc26a5 100644 --- a/src/calanonsync/caldav_test.go +++ b/src/calanonsync/caldav_test.go @@ -71,6 +71,25 @@ func TestParseICal(t *testing.T) { t.Error("Last line is wrong") } }) + t.Run("Whole day", func(t *testing.T) { + i, err := ParseICal(strings.NewReader(icsWithDateOnly)) + if err != nil { + t.Fatalf("Parse failed: %s", err) + } + + start := i.Start() + end := i.End() + + expectedStart := time.Date(2018, 4, 7, 0, 0, 0, 0, time.Local) + expectedEnd := time.Date(2018, 4, 10, 0, 0, 0, 0, time.Local) + + if !start.Equal(expectedStart) { + t.Errorf("Unexpected start time (%s != %s)", start, expectedStart) + } + if !end.Equal(expectedEnd) { + t.Errorf("Unexpected end time (%s != %s)", end, expectedEnd) + } + }) } func TestICal_Update(t *testing.T) { @@ -88,7 +107,8 @@ func TestICal_Update(t *testing.T) { t.Error("End not updated correctly") } - if ical.getTimeField("DTSTAMP").Sub(time.Now()) > 5*time.Second { + stamp, _ := ical.getTimeField("DTSTAMP") + if stamp.Sub(time.Now()) > 5*time.Second { t.Error("Timestamp doesn't seem to be updated") } }) @@ -149,7 +169,8 @@ END:VCALENDAR` { t.Error("End not updated correctly") } - if ical.getTimeField("DTSTAMP").Sub(time.Now()) > 5*time.Second { + stamp, _ := ical.getTimeField("DTSTAMP") + if stamp.Sub(time.Now()) > 5*time.Second { t.Error("Timestamp doesn't seem to be updated") } })