diff --git a/src/utils/datetime.rs b/src/utils/datetime.rs index b477be4..a70abb2 100644 --- a/src/utils/datetime.rs +++ b/src/utils/datetime.rs @@ -67,7 +67,13 @@ pub fn parse_datetime_with_timezone( ) -> Result { let timezone = timezone.unwrap_or(DEFAULT_CHURCH_TIMEZONE); - if datetime_str.ends_with('Z') || datetime_str.contains('+') || datetime_str.contains('-') { + // Check if this looks like RFC3339 with timezone info (ends with Z, contains +, or has timezone offset after T) + let has_timezone = datetime_str.ends_with('Z') || + datetime_str.contains('+') || + (datetime_str.contains('T') && + datetime_str.split('T').nth(1).map_or(false, |time_part| time_part.contains('-'))); + + if has_timezone { let dt = DateTime::parse_from_rfc3339(datetime_str) .map_err(|_| ApiError::BadRequest("Invalid RFC3339 datetime".to_string()))?; DateTimeWithTimezone::new(dt.with_timezone(&Utc), timezone) diff --git a/src/utils/multipart_helpers.rs b/src/utils/multipart_helpers.rs index 501ba9c..3727e8f 100644 --- a/src/utils/multipart_helpers.rs +++ b/src/utils/multipart_helpers.rs @@ -71,20 +71,20 @@ impl MultipartProcessor { pub fn get_datetime(&self, field_name: &str) -> Result> { let datetime_str = self.get_required_string(field_name)?; - // First try the shared timezone-aware parsing function - if let Ok(utc_time) = crate::utils::datetime::parse_event_datetime_to_utc(&datetime_str) { - return Ok(utc_time); + // Try parsing as RFC3339 first (already has timezone info) + if let Ok(dt) = DateTime::parse_from_rfc3339(&datetime_str) { + return Ok(dt.to_utc()); } - // Fallback to legacy formats for backward compatibility - // These will now be treated as EST/EDT times and converted to UTC + // Try flexible local formats for backward compatibility + // These will be treated as EST/EDT times and converted to UTC let formats = [ - "%Y-%m-%dT%H:%M", - "%Y-%m-%dT%H:%M:%S", - "%Y-%m-%d %H:%M", - "%Y-%m-%d %H:%M:%S", - "%m/%d/%Y %H:%M", - "%m/%d/%Y %I:%M %p", + "%Y-%m-%dT%H:%M", // 2025-10-08T00:09 + "%Y-%m-%dT%H:%M:%S", // 2025-10-08T00:09:00 + "%Y-%m-%d %H:%M", // 2025-10-08 00:09 + "%Y-%m-%d %H:%M:%S", // 2025-10-08 00:09:00 + "%m/%d/%Y %H:%M", // 10/08/2025 00:09 + "%m/%d/%Y %I:%M %p", // 10/08/2025 12:09 AM ]; for format in &formats { @@ -95,9 +95,9 @@ impl MultipartProcessor { } } - // Try parsing as RFC3339 (already has timezone info) - if let Ok(dt) = DateTime::parse_from_rfc3339(&datetime_str) { - return Ok(dt.to_utc()); + // Last resort: try the shared timezone-aware parsing function + if let Ok(utc_time) = crate::utils::datetime::parse_event_datetime_to_utc(&datetime_str) { + return Ok(utc_time); } Err(ApiError::ValidationError(format!(