Use Cases

Gérer correctement les dates et heures avec Claude Code

Découvrez la gestion correcte des dates et heures avec Claude Code. Exemples de code pratiques inclus.

Implémenter correctement le traitement des dates et heures avec Claude Code

Le traitement des dates et heures est un domaine plein de pièges inattendus : fuseaux horaires, formatage, support des locales. Avec Claude Code, vous pouvez implémenter efficacement un traitement de dates robuste suivant les bonnes pratiques.

Choix de la bibliothèque

> Crée un utilitaire de traitement des dates et heures.
> Utilise day.js avec conversion de fuseaux horaires, affichage du temps relatif,
> formatage français et calcul des jours ouvrés.
  • day.js : léger (2KB) avec une API compatible Moment.js
  • date-fns : basé sur les fonctions, optimal pour le Tree-shaking
  • Temporal API : future API standard (encore au stade de proposition)

Implémentation de l’utilitaire de dates

// src/lib/date-utils.ts
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/fr';

dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(relativeTime);
dayjs.locale('fr');

// Fuseau horaire par défaut
const DEFAULT_TZ = 'Europe/Paris';

// Préréglages de format
export const DATE_FORMATS = {
  full: 'dddd D MMMM YYYY HH:mm',
  date: 'D MMMM YYYY',
  dateShort: 'DD/MM',
  time: 'HH:mm',
  iso: 'YYYY-MM-DDTHH:mm:ssZ',
  api: 'YYYY-MM-DD',
} as const;

/**
 * Formater une date UTC selon le fuseau horaire local
 */
export function formatDate(
  date: string | Date,
  format: keyof typeof DATE_FORMATS = 'date'
): string {
  return dayjs(date).tz(DEFAULT_TZ).format(DATE_FORMATS[format]);
}

/**
 * Retourne le temps relatif (« il y a 3 minutes », « il y a 2 heures », « hier », etc.)
 */
export function timeAgo(date: string | Date): string {
  const d = dayjs(date);
  const now = dayjs();
  const diffHours = now.diff(d, 'hour');

  if (diffHours < 1) {
    const diffMinutes = now.diff(d, 'minute');
    if (diffMinutes < 1) return 'à l\'instant';
    return `il y a ${diffMinutes} min`;
  }
  if (diffHours < 24) return `il y a ${diffHours}h`;
  if (diffHours < 48) return 'hier';
  if (diffHours < 168) return `il y a ${Math.floor(diffHours / 24)} jours`;

  return formatDate(date, 'date');
}

/**
 * Conversion de fuseau horaire
 */
export function convertTimezone(
  date: string | Date,
  fromTz: string,
  toTz: string
): dayjs.Dayjs {
  return dayjs.tz(date, fromTz).tz(toTz);
}

/**
 * Déterminer si c'est un jour ouvré
 */
export function isBusinessDay(date: string | Date): boolean {
  const d = dayjs(date);
  const dayOfWeek = d.day();
  return dayOfWeek !== 0 && dayOfWeek !== 6; // dimanche=0, samedi=6
}

/**
 * Obtenir la date N jours ouvrés plus tard
 */
export function addBusinessDays(date: string | Date, days: number): dayjs.Dayjs {
  let current = dayjs(date);
  let remaining = days;

  while (remaining > 0) {
    current = current.add(1, 'day');
    if (isBusinessDay(current.toDate())) {
      remaining--;
    }
  }

  return current;
}

Formatage natif avec l’API Intl

Même sans bibliothèque, l’API Intl du navigateur permet de nombreux formatages.

// src/lib/intl-date.ts

/**
 * Formatage de date avec Intl.DateTimeFormat
 */
export function formatDateIntl(date: Date, style: 'long' | 'short' = 'long'): string {
  return new Intl.DateTimeFormat('fr-FR', {
    year: 'numeric',
    month: style === 'long' ? 'long' : 'numeric',
    day: 'numeric',
    weekday: style === 'long' ? 'short' : undefined,
  }).format(date);
}

/**
 * Afficher la différence entre deux dates de manière lisible
 */
export function formatDateRange(start: Date, end: Date): string {
  return new Intl.DateTimeFormat('fr-FR', {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
  }).formatRange(start, end);
}

/**
 * Formatage du temps relatif
 */
export function formatRelative(date: Date): string {
  const rtf = new Intl.RelativeTimeFormat('fr', { numeric: 'auto' });
  const now = new Date();
  const diffMs = date.getTime() - now.getTime();
  const diffSec = Math.round(diffMs / 1000);
  const diffMin = Math.round(diffSec / 60);
  const diffHour = Math.round(diffMin / 60);
  const diffDay = Math.round(diffHour / 24);

  if (Math.abs(diffSec) < 60) return rtf.format(diffSec, 'second');
  if (Math.abs(diffMin) < 60) return rtf.format(diffMin, 'minute');
  if (Math.abs(diffHour) < 24) return rtf.format(diffHour, 'hour');
  return rtf.format(diffDay, 'day');
}

Utilisation dans les composants React

// src/components/TimeDisplay.tsx
'use client';
import { useState, useEffect } from 'react';
import { timeAgo } from '@/lib/date-utils';

export function TimeDisplay({ date }: { date: string }) {
  const [display, setDisplay] = useState(timeAgo(date));

  useEffect(() => {
    const interval = setInterval(() => {
      setDisplay(timeAgo(date));
    }, 60000); // Mise à jour toutes les minutes
    return () => clearInterval(interval);
  }, [date]);

  return (
    <time dateTime={date} title={new Date(date).toLocaleString('fr-FR')}>
      {display}
    </time>
  );
}

Pièges courants

  • Fuseau horaire non pris en compte : quand serveur et client ont des fuseaux différents, toujours stocker en UTC et convertir côté client
  • Heure d’été : attention lors du support d’utilisateurs dans des pays avec changement d’heure
  • Comportement de Date.parse() : des différences existent entre navigateurs, utilisez dayjs ou similaire pour le parsing

Articles connexes

Pour l’internationalisation en général, consultez le guide d’implémentation i18n, et pour le formatage des devises, consultez Implémentation du formatage des devises.

La documentation officielle de day.js (day.js.org) fournit la liste des plugins.

#Claude Code #dates #fuseaux horaires #day.js #Intl