Fix all-day event end date handling by removing double conversion

Root cause: Both frontend and backend were adding a day for all-day events:
- Frontend: Converts inclusive UI dates (9/22-9/25) to exclusive (9/22-9/26)
- Backend: Was incorrectly adding another day (9/22-9/27) causing display issues

Fixed by:
- Remove duplicate day addition in backend handlers (events.rs, series.rs)
- Keep frontend conversion for proper RFC 5545 compliance
- Add reverse conversion when loading events for editing
- Maintain user-friendly inclusive dates in UI while storing exclusive dates

Now properly handles: UI 9/22-9/25 ↔ Storage 9/22-9/26 (exclusive per spec)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Connor Johnstone
2025-09-21 12:34:09 -04:00
parent 5c406569af
commit cb1bb23132
4 changed files with 19 additions and 20 deletions

View File

@@ -456,14 +456,11 @@ pub async fn create_event(
parse_event_datetime_local(&request.start_date, &request.start_time, request.all_day)
.map_err(|e| ApiError::BadRequest(format!("Invalid start date/time: {}", e)))?;
let mut end_datetime = parse_event_datetime_local(&request.end_date, &request.end_time, request.all_day)
let end_datetime = parse_event_datetime_local(&request.end_date, &request.end_time, request.all_day)
.map_err(|e| ApiError::BadRequest(format!("Invalid end date/time: {}", e)))?;
// For all-day events, add one day to end date for RFC-5545 compliance
// RFC-5545 uses exclusive end dates for all-day events
if request.all_day {
end_datetime = end_datetime + chrono::Duration::days(1);
}
// Note: Frontend already converts inclusive UI dates to exclusive dates for all-day events
// No additional conversion needed here
// Validate that end is after start (allow equal times for all-day events)
if request.all_day {
@@ -766,14 +763,11 @@ pub async fn update_event(
parse_event_datetime_local(&request.start_date, &request.start_time, request.all_day)
.map_err(|e| ApiError::BadRequest(format!("Invalid start date/time: {}", e)))?;
let mut end_datetime = parse_event_datetime_local(&request.end_date, &request.end_time, request.all_day)
let end_datetime = parse_event_datetime_local(&request.end_date, &request.end_time, request.all_day)
.map_err(|e| ApiError::BadRequest(format!("Invalid end date/time: {}", e)))?;
// For all-day events, add one day to end date for RFC-5545 compliance
// RFC-5545 uses exclusive end dates for all-day events
if request.all_day {
end_datetime = end_datetime + chrono::Duration::days(1);
}
// Note: Frontend already converts inclusive UI dates to exclusive dates for all-day events
// No additional conversion needed here
// Validate that end is after start (allow equal times for all-day events)
if request.all_day {

View File

@@ -137,13 +137,11 @@ pub async fn create_event_series(
let start_datetime = parse_event_datetime_local(&request.start_date, &request.start_time, request.all_day)
.map_err(|e| ApiError::BadRequest(format!("Invalid start date/time: {}", e)))?;
let mut end_datetime = parse_event_datetime_local(&request.end_date, &request.end_time, request.all_day)
let end_datetime = parse_event_datetime_local(&request.end_date, &request.end_time, request.all_day)
.map_err(|e| ApiError::BadRequest(format!("Invalid end date/time: {}", e)))?;
// For all-day events, add one day to end date for RFC-5545 compliance
if request.all_day {
end_datetime = end_datetime + chrono::Duration::days(1);
}
// Note: Frontend already converts inclusive UI dates to exclusive dates for all-day events
// No additional conversion needed here
// Generate a unique UID for the series
let uid = format!("series-{}", uuid::Uuid::new_v4().to_string());