diff --git a/src/internal/converters/ics/ics.go b/src/internal/converters/ics/ics.go index 0682e36ef..ce67b8908 100644 --- a/src/internal/converters/ics/ics.go +++ b/src/internal/converters/ics/ics.go @@ -106,7 +106,6 @@ func getUTCTime(ts, tz string) (time.Time, error) { // https://www.rfc-editor.org/rfc/rfc5545#section-3.3.10 // https://learn.microsoft.com/en-us/graph/api/resources/patternedrecurrence?view=graph-rest-1.0 // Ref: https://github.com/closeio/sync-engine/pull/381/files -// FIXME: When we have daily repeating task the last one is not getting added (due to timezone differences) func getRecurrencePattern( ctx context.Context, recurrence models.PatternedRecurrenceable, @@ -175,10 +174,19 @@ func getRecurrencePattern( case models.ENDDATE_RECURRENCERANGETYPE: end := rrange.GetEndDate() if end != nil { - // NOTE: We convert just a date into date+time in a - // different timezone which will cause it to not be just - // a date anymore. - endTime, err := getUTCTime(end.String(), ptr.Val(rrange.GetRecurrenceTimeZone())) + parsedTime, err := dttm.ParseTime(end.String()) + if err != nil { + return "", clues.Wrap(err, "parsing recurrence end date") + } + + // end date is always computed as end of the day and + // so add 23 hours 59 minutes 59 seconds as seconds is + // the resolution we need + parsedTime = parsedTime.Add(24*time.Hour - 1*time.Second) + + endTime, err := getUTCTime( + parsedTime.Format(string(dttm.M365DateTimeTimeZone)), + ptr.Val(rrange.GetRecurrenceTimeZone())) if err != nil { return "", clues.WrapWC(ctx, err, "parsing end time") } diff --git a/src/internal/converters/ics/ics_test.go b/src/internal/converters/ics/ics_test.go index 066e6c09d..787132d0b 100644 --- a/src/internal/converters/ics/ics_test.go +++ b/src/internal/converters/ics/ics_test.go @@ -192,6 +192,37 @@ func (suite *ICSUnitSuite) TestGetRecurrencePattern() { expect: "FREQ=DAILY;INTERVAL=1", errCheck: require.NoError, }, + { + name: "daily with end date in different timezone", + recurrence: func() models.PatternedRecurrenceable { + rec := models.NewPatternedRecurrence() + pat := models.NewRecurrencePattern() + + typ, err := models.ParseRecurrencePatternType("daily") + require.NoError(suite.T(), err) + + pat.SetTypeEscaped(typ.(*models.RecurrencePatternType)) + pat.SetInterval(ptr.To(int32(1))) + + rng := models.NewRecurrenceRange() + + rrtype, err := models.ParseRecurrenceRangeType("endDate") + require.NoError(suite.T(), err) + + rng.SetTypeEscaped(rrtype.(*models.RecurrenceRangeType)) + + edate := serialization.NewDateOnly(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)) + rng.SetEndDate(edate) + rng.SetRecurrenceTimeZone(ptr.To("India Standard Time")) + + rec.SetPattern(pat) + rec.SetRangeEscaped(rng) + + return rec + }, + expect: "FREQ=DAILY;INTERVAL=1;UNTIL=20210101T182959Z", + errCheck: require.NoError, + }, { name: "weekly", recurrence: func() models.PatternedRecurrenceable { @@ -239,7 +270,7 @@ func (suite *ICSUnitSuite) TestGetRecurrencePattern() { return rec }, - expect: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20210101T000000Z", + expect: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20210101T235959Z", errCheck: require.NoError, }, {