Fix: Correction complète du décalage horaire d'1 heure dans le calendrier

Problèmes corrigés:
- Ajout de fonctions utilitaires toLocalDateTimeString() et toParisISO()
  pour gérer correctement les conversions de timezone Europe/Paris
- Correction des valeurs par défaut des champs datetime-local lors de la
  création d'événements (utilisaient toISOString().slice() incorrectement)
- Correction des valeurs par défaut lors de l'édition d'événements
- Correction de la soumission des formulaires (création et édition)
  pour envoyer les dates ISO correctes avec timezone Europe/Paris

Les dates sont désormais:
1. Affichées correctement en heure Europe/Paris dans les formulaires
2. Converties correctement lors de l'envoi au backend
3. Stockées et récupérées sans décalage horaire

Fichiers modifiés:
- src/pages/Index.tsx: Ajout des fonctions utilitaires et correction
  de toutes les conversions de dates pour les événements du calendrier
This commit is contained in:
Claude committed 2025-11-16 11:06:21 +00:00
1 parent 3c786fe75f
commit c103a517c8
1 file changed
+78 -8
+78 -8
View File
@@ -32,6 +32,76 @@ import { ConfirmModal } from "@/components/modals/ConfirmModal";
import { InputModal } from "@/components/modals/InputModal"; import { InputModal } from "@/components/modals/InputModal";
import { AddUserModal } from "@/components/modals/AddUserModal"; import { AddUserModal } from "@/components/modals/AddUserModal";
// ===== FONCTIONS UTILITAIRES TIMEZONE EUROPE/PARIS =====
/**
* Convertit une date ISO/UTC en format datetime-local pour Europe/Paris
* @param date - Date ISO string ou Date object
* @returns String au format "YYYY-MM-DDTHH:mm" en heure Europe/Paris
*/
function toLocalDateTimeString(date: string | Date): string {
const d = typeof date === 'string' ? new Date(date) : date;
// Formater en heure Europe/Paris
const formatter = new Intl.DateTimeFormat('fr-FR', {
timeZone: 'Europe/Paris',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false
});
const parts = formatter.formatToParts(d);
const year = parts.find(p => p.type === 'year')?.value;
const month = parts.find(p => p.type === 'month')?.value;
const day = parts.find(p => p.type === 'day')?.value;
const hour = parts.find(p => p.type === 'hour')?.value;
const minute = parts.find(p => p.type === 'minute')?.value;
return `${year}-${month}-${day}T${hour}:${minute}`;
}
/**
* Convertit une valeur datetime-local en ISO string pour Europe/Paris
* @param localDateTimeString - String au format "YYYY-MM-DDTHH:mm" (sans timezone)
* @returns ISO string représentant cette heure en Europe/Paris
*/
function toParisISO(localDateTimeString: string): string {
// Le champ datetime-local renvoie une string locale (ex: "2024-11-16T14:30")
// On doit l'interpréter comme étant en Europe/Paris, puis convertir en ISO
// Parser les composants de la date
const [datePart, timePart] = localDateTimeString.split('T');
const [year, month, day] = datePart.split('-').map(Number);
const [hour, minute] = timePart.split(':').map(Number);
// Créer une date "fictive" en UTC avec ces valeurs
const utcDate = new Date(Date.UTC(year, month - 1, day, hour, minute, 0));
// Formater cette date en tant que date Paris
const parisTime = utcDate.toLocaleString('en-US', {
timeZone: 'Europe/Paris',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
// Calculer la différence entre l'heure voulue et l'heure obtenue
const parisDate = new Date(parisTime);
const diff = utcDate.getTime() - parisDate.getTime();
// Créer la date finale en ajustant
const finalDate = new Date(utcDate.getTime() - diff);
return finalDate.toISOString();
}
interface UserType { interface UserType {
id: number; id: number;
username: string; username: string;
@@ -2061,8 +2131,8 @@ const Index = () => {
const eventData = { const eventData = {
title: formData.get('title') as string, title: formData.get('title') as string,
description: formData.get('description') as string || undefined, description: formData.get('description') as string || undefined,
startDateTime: new Date(formData.get('startDateTime') as string).toISOString(), startDateTime: toParisISO(formData.get('startDateTime') as string),
endDateTime: new Date(formData.get('endDateTime') as string).toISOString(), endDateTime: toParisISO(formData.get('endDateTime') as string),
location: formData.get('location') as string || undefined, location: formData.get('location') as string || undefined,
attendees: (formData.get('attendees') as string || '').split(',').map(e => e.trim()).filter(e => e), attendees: (formData.get('attendees') as string || '').split(',').map(e => e.trim()).filter(e => e),
reminders: reminderMinutes && reminderMinutes !== '0' ? [ reminders: reminderMinutes && reminderMinutes !== '0' ? [
@@ -2105,7 +2175,7 @@ const Index = () => {
name="startDateTime" name="startDateTime"
type="datetime-local" type="datetime-local"
required required
defaultValue={new Date(Date.now() + 60*60*1000).toISOString().slice(0, 16)} defaultValue={toLocalDateTimeString(new Date(Date.now() + 60*60*1000))}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
@@ -2115,7 +2185,7 @@ const Index = () => {
name="endDateTime" name="endDateTime"
type="datetime-local" type="datetime-local"
required required
defaultValue={new Date(Date.now() + 2*60*60*1000).toISOString().slice(0, 16)} defaultValue={toLocalDateTimeString(new Date(Date.now() + 2*60*60*1000))}
/> />
</div> </div>
</div> </div>
@@ -2239,8 +2309,8 @@ const Index = () => {
const eventData = { const eventData = {
title: formData.get('title') as string, title: formData.get('title') as string,
description: formData.get('description') as string || undefined, description: formData.get('description') as string || undefined,
startDateTime: new Date(formData.get('startDateTime') as string).toISOString(), startDateTime: toParisISO(formData.get('startDateTime') as string),
endDateTime: new Date(formData.get('endDateTime') as string).toISOString(), endDateTime: toParisISO(formData.get('endDateTime') as string),
location: formData.get('location') as string || undefined, location: formData.get('location') as string || undefined,
attendees: (formData.get('attendees') as string || '').split(',').map(e => e.trim()).filter(e => e), attendees: (formData.get('attendees') as string || '').split(',').map(e => e.trim()).filter(e => e),
reminders: reminderMinutes && reminderMinutes !== '0' ? [ reminders: reminderMinutes && reminderMinutes !== '0' ? [
@@ -2282,7 +2352,7 @@ const Index = () => {
name="startDateTime" name="startDateTime"
type="datetime-local" type="datetime-local"
required required
defaultValue={editEventModal.event ? new Date(editEventModal.event.start_time).toISOString().slice(0, 16) : ''} defaultValue={editEventModal.event ? toLocalDateTimeString(editEventModal.event.start_time) : ''}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
@@ -2292,7 +2362,7 @@ const Index = () => {
name="endDateTime" name="endDateTime"
type="datetime-local" type="datetime-local"
required required
defaultValue={editEventModal.event ? new Date(editEventModal.event.end_time).toISOString().slice(0, 16) : ''} defaultValue={editEventModal.event ? toLocalDateTimeString(editEventModal.event.end_time) : ''}
/> />
</div> </div>
</div> </div>