From a2fa0c11cb56c7265322f6a3db5caebec7c96c96 Mon Sep 17 00:00:00 2001 From: Claudio Schaad Date: Sat, 6 Sep 2025 21:37:59 +0200 Subject: [PATCH] Fix google calendar time zone --- .github/copilot-instructions.md | 7 +++++++ Services/ConfigurationService.cs | 11 ++++++++--- Services/GoogleCalendarService.cs | 18 +++++++----------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 467dd12..6fa9d76 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -170,6 +170,13 @@ void Foo(params IReadOnlyList values) => // actual implementation here.` - Use proper null checks in equality methods - Consider `ReferenceEquals` optimization for reference types +### Date, Time and TimeZone +- Don't use DateTime for a date with time, use DateTimeOffset instead +- When only a date is needed, use DateOnly +- When only a time is needed, use TimeOnly +- Always use a specific local timezone for the DateTimeOffset +- If nothing specified, use Europe/Zurich + ### Architecture - Proper separation of concerns - Following established patterns in the codebase diff --git a/Services/ConfigurationService.cs b/Services/ConfigurationService.cs index a4c7cac..aa2fe61 100644 --- a/Services/ConfigurationService.cs +++ b/Services/ConfigurationService.cs @@ -5,7 +5,7 @@ namespace ShiftScheduler.Services { public interface IConfigurationService { - string GetTimeZone(); + (DateTimeOffset StartTime, DateTimeOffset EndTime) GetZurichTime(DateOnly date, string timeRange); ApplicationConfiguration GetConfiguration(); void UpdateConfiguration(ApplicationConfiguration configuration); Task ExportConfigurationAsync(); @@ -32,9 +32,14 @@ namespace ShiftScheduler.Services private readonly TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Europe/Zurich"); - public string GetTimeZone() + public (DateTimeOffset StartTime, DateTimeOffset EndTime) GetZurichTime(DateOnly date, string timeRange) { - return localTimeZone.Id; + var times = timeRange.Split('-'); ; + var startTime = TimeOnly.Parse(times[0]); + var endTime = TimeOnly.Parse(times[1]); + + TimeSpan offset = localTimeZone.GetUtcOffset(DateTime.UtcNow); + return (new DateTimeOffset(date, startTime, offset), new DateTimeOffset(date, endTime, offset)); } public ConfigurationService(ApplicationConfiguration initialConfiguration) diff --git a/Services/GoogleCalendarService.cs b/Services/GoogleCalendarService.cs index 5c7186c..4fc9312 100644 --- a/Services/GoogleCalendarService.cs +++ b/Services/GoogleCalendarService.cs @@ -101,24 +101,22 @@ public class GoogleCalendarService(IHttpContextAccessor httpContextAccessor, ICo // Create morning event if it exists if (!string.IsNullOrEmpty(shift.MorningTime)) { - var morningEvent = CreateEventFromShift(shift, date, shift.MorningTime, shiftWithTransport.MorningTransport); + var (startTime, endTime) = configurationService.GetZurichTime(DateOnly.FromDateTime(date), shift.MorningTime); + var morningEvent = CreateEventFromShift(shift, startTime, endTime, shiftWithTransport.MorningTransport); await ExecuteWithRetryAsync(async () => await service.Events.Insert(morningEvent, calendarId).ExecuteAsync()); } // Create afternoon event if it exists if (!string.IsNullOrEmpty(shift.AfternoonTime)) { - var afternoonEvent = CreateEventFromShift(shift, date, shift.AfternoonTime, shiftWithTransport.AfternoonTransport); + var (startTime, endTime) = configurationService.GetZurichTime(DateOnly.FromDateTime(date), shift.AfternoonTime); + var afternoonEvent = CreateEventFromShift(shift, startTime, endTime, shiftWithTransport.AfternoonTransport); await ExecuteWithRetryAsync(async () => await service.Events.Insert(afternoonEvent, calendarId).ExecuteAsync()); } } - private Event CreateEventFromShift(Shift shift, DateTime date, string timeRange, TransportConnection? transport) + private Event CreateEventFromShift(Shift shift, DateTimeOffset startTime, DateTimeOffset endTime, TransportConnection? transport) { - var times = timeRange.Split('-'); - var startTime = date.Add(TimeSpan.Parse(times[0])); - var endTime = date.Add(TimeSpan.Parse(times[1])); - var summary = $"{shift.Name}"; var description = ""; @@ -134,13 +132,11 @@ public class GoogleCalendarService(IHttpContextAccessor httpContextAccessor, ICo Description = description, Start = new EventDateTime { - DateTimeDateTimeOffset = startTime, - TimeZone = configurationService.GetTimeZone() + DateTimeDateTimeOffset = startTime }, End = new EventDateTime { - DateTimeDateTimeOffset = endTime, - TimeZone = configurationService.GetTimeZone() + DateTimeDateTimeOffset = endTime }, ExtendedProperties = new Event.ExtendedPropertiesData {