diff --git a/backend/src/calendar.rs b/backend/src/calendar.rs index 00153ab..a6adf7b 100644 --- a/backend/src/calendar.rs +++ b/backend/src/calendar.rs @@ -733,18 +733,124 @@ impl CalDAVClient { } } + // Try parsing with timezone offset (e.g., 20231225T120000-0500) + if let Ok(dt) = DateTime::parse_from_str(datetime_part, "%Y%m%dT%H%M%S%z") { + return Ok(dt.with_timezone(&Utc)); + } + + // Try ISO format with timezone offset (e.g., 2023-12-25T12:00:00-05:00) + if let Ok(dt) = DateTime::parse_from_str(datetime_part, "%Y-%m-%dT%H:%M:%S%z") { + return Ok(dt.with_timezone(&Utc)); + } + + // Try ISO format with Z suffix (e.g., 2023-12-25T12:00:00Z) + if let Ok(dt) = DateTime::parse_from_str(datetime_part, "%Y-%m-%dT%H:%M:%SZ") { + return Ok(dt.with_timezone(&Utc)); + } + // Try parsing as naive datetime if let Ok(naive_dt) = chrono::NaiveDateTime::parse_from_str(datetime_part, format) { // If we have timezone information, convert accordingly if let Some(tz_id) = timezone_id { - if let Ok(tz) = tz_id.parse::() { + let tz_result = if tz_id.starts_with("/mozilla.org/") { + // Mozilla/Thunderbird format: /mozilla.org/20070129_1/Europe/London + tz_id.split('/').last().and_then(|tz_name| tz_name.parse::().ok()) + } else if tz_id.contains('/') { + // Standard timezone format: America/New_York, Europe/London + tz_id.parse::().ok() + } else { + // Try common abbreviations and Windows timezone names + match tz_id { + // Standard abbreviations + "EST" => Some(Tz::America__New_York), + "PST" => Some(Tz::America__Los_Angeles), + "MST" => Some(Tz::America__Denver), + "CST" => Some(Tz::America__Chicago), + + // North America - Windows timezone names to IANA mapping + "Mountain Standard Time" => Some(Tz::America__Denver), + "Eastern Standard Time" => Some(Tz::America__New_York), + "Central Standard Time" => Some(Tz::America__Chicago), + "Pacific Standard Time" => Some(Tz::America__Los_Angeles), + "Mountain Daylight Time" => Some(Tz::America__Denver), + "Eastern Daylight Time" => Some(Tz::America__New_York), + "Central Daylight Time" => Some(Tz::America__Chicago), + "Pacific Daylight Time" => Some(Tz::America__Los_Angeles), + "Hawaiian Standard Time" => Some(Tz::Pacific__Honolulu), + "Alaskan Standard Time" => Some(Tz::America__Anchorage), + "Alaskan Daylight Time" => Some(Tz::America__Anchorage), + "Atlantic Standard Time" => Some(Tz::America__Halifax), + "Newfoundland Standard Time" => Some(Tz::America__St_Johns), + + // Europe + "GMT Standard Time" => Some(Tz::Europe__London), + "Greenwich Standard Time" => Some(Tz::UTC), + "W. Europe Standard Time" => Some(Tz::Europe__Berlin), + "Central Europe Standard Time" => Some(Tz::Europe__Warsaw), + "Romance Standard Time" => Some(Tz::Europe__Paris), + "Central European Standard Time" => Some(Tz::Europe__Belgrade), + "E. Europe Standard Time" => Some(Tz::Europe__Bucharest), + "FLE Standard Time" => Some(Tz::Europe__Helsinki), + "GTB Standard Time" => Some(Tz::Europe__Athens), + "Russian Standard Time" => Some(Tz::Europe__Moscow), + "Turkey Standard Time" => Some(Tz::Europe__Istanbul), + + // Asia + "China Standard Time" => Some(Tz::Asia__Shanghai), + "Tokyo Standard Time" => Some(Tz::Asia__Tokyo), + "Korea Standard Time" => Some(Tz::Asia__Seoul), + "Singapore Standard Time" => Some(Tz::Asia__Singapore), + "India Standard Time" => Some(Tz::Asia__Kolkata), + "Pakistan Standard Time" => Some(Tz::Asia__Karachi), + "Bangladesh Standard Time" => Some(Tz::Asia__Dhaka), + "Thailand Standard Time" => Some(Tz::Asia__Bangkok), + "SE Asia Standard Time" => Some(Tz::Asia__Bangkok), + "Myanmar Standard Time" => Some(Tz::Asia__Yangon), + "Sri Lanka Standard Time" => Some(Tz::Asia__Colombo), + "Nepal Standard Time" => Some(Tz::Asia__Kathmandu), + "Central Asia Standard Time" => Some(Tz::Asia__Almaty), + "West Asia Standard Time" => Some(Tz::Asia__Tashkent), + "N. Central Asia Standard Time" => Some(Tz::Asia__Novosibirsk), + "North Asia Standard Time" => Some(Tz::Asia__Krasnoyarsk), + "North Asia East Standard Time" => Some(Tz::Asia__Irkutsk), + "Yakutsk Standard Time" => Some(Tz::Asia__Yakutsk), + "Vladivostok Standard Time" => Some(Tz::Asia__Vladivostok), + "Magadan Standard Time" => Some(Tz::Asia__Magadan), + + // Australia & Pacific + "AUS Eastern Standard Time" => Some(Tz::Australia__Sydney), + "AUS Central Standard Time" => Some(Tz::Australia__Adelaide), + "W. Australia Standard Time" => Some(Tz::Australia__Perth), + "Tasmania Standard Time" => Some(Tz::Australia__Hobart), + "New Zealand Standard Time" => Some(Tz::Pacific__Auckland), + "Fiji Standard Time" => Some(Tz::Pacific__Fiji), + "Tonga Standard Time" => Some(Tz::Pacific__Tongatapu), + + // Africa & Middle East + "South Africa Standard Time" => Some(Tz::Africa__Johannesburg), + "Egypt Standard Time" => Some(Tz::Africa__Cairo), + "Israel Standard Time" => Some(Tz::Asia__Jerusalem), + "Iran Standard Time" => Some(Tz::Asia__Tehran), + "Arabic Standard Time" => Some(Tz::Asia__Baghdad), + "Arab Standard Time" => Some(Tz::Asia__Riyadh), + + // South America + "SA Eastern Standard Time" => Some(Tz::America__Sao_Paulo), + "Argentina Standard Time" => Some(Tz::America__Buenos_Aires), + "SA Western Standard Time" => Some(Tz::America__La_Paz), + "SA Pacific Standard Time" => Some(Tz::America__Bogota), + + _ => None, + } + }; + + if let Some(tz) = tz_result { // Convert from the specified timezone to UTC if let Some(local_dt) = tz.from_local_datetime(&naive_dt).single() { - let utc_dt = local_dt.with_timezone(&Utc); - return Ok(utc_dt); + return Ok(local_dt.with_timezone(&Utc)); } } - // If timezone parsing fails, log and fall back to UTC + // If timezone parsing fails, fall back to UTC } // No timezone info or parsing failed - treat as UTC return Ok(Utc.from_utc_datetime(&naive_dt));