Initialisation des systèmes...

Baptiste.Dev
Retour aux notes
LangagesIntermédiaireSérie : C# / .NET

C# : DateOnly et TimeOnly

Les types dédiés à une date seule ou une heure seule (.NET 6+) : pourquoi ils existent, et comment les manipuler.

Par Baptiste Vidal
3 min de lecture
Mis à jour aujourd'hui
c#csharpdateonlytimeonlydotnet6dates

C# : DateOnly et TimeOnly

Depuis .NET 6, deux types répondent à un vrai manque : représenter une date sans heure ou une heure sans date. Avant, on bricolait avec un DateTime à minuit, ce qui traînait une heure et un fuseau parasites, source de bugs.

  • DateOnly : une date pure (anniversaire, échéance, date de facture).
  • TimeOnly : une heure d'horloge pure (ouverture d'un magasin, alarme).

Aucun des deux n'a de Kind ni de notion de fuseau : ils sont non ambigus par construction.


# DateOnly

DateOnly date = new DateOnly(2026, 9, 1);
DateOnly aujourdhui = DateOnly.FromDateTime(DateTime.Now);  // on jette l'heure
 
int annee = date.Year;               // 2026
DayOfWeek jour = date.DayOfWeek;     // DayOfWeek.Tuesday
int jourAnnee = date.DayOfYear;      // 244
int numero = date.DayNumber;         // nombre de jours depuis le 0001-01-01

L'arithmétique se fait en jours, mois ou années, et retourne une nouvelle valeur :

DateOnly echeance = date.AddDays(30);
DateOnly anniversaireProchain = date.AddYears(1);
 
int joursRestants = echeance.DayNumber - aujourdhui.DayNumber;  // un écart simple, en jours

La comparaison utilise les opérateurs habituels :

if (echeance < aujourdhui) { /* en retard */ }

# TimeOnly

TimeOnly ouverture = new TimeOnly(9, 0);        // 09:00
TimeOnly fermeture = new TimeOnly(18, 30);      // 18:30
TimeOnly maintenant = TimeOnly.FromDateTime(DateTime.Now);
 
int heure = ouverture.Hour;      // 9
int minute = ouverture.Minute;   // 0

Particularité : l'heure tourne sur 24 h. Ajouter du temps qui dépasse minuit repart de zéro :

TimeOnly tard = new TimeOnly(23, 30);
TimeOnly apres = tard.AddHours(2);   // 01:30, pas 25:30

IsBetween gère même les plages qui passent par minuit :

bool ouvert = maintenant.IsBetween(ouverture, fermeture);
 
TimeOnly debutNuit = new TimeOnly(22, 0);
TimeOnly finNuit = new TimeOnly(6, 0);
bool estLaNuit = maintenant.IsBetween(debutNuit, finNuit);  // vrai à 23h comme à 3h

# Combiner les deux

On reconstitue un DateTime complet en associant une date et une heure :

DateOnly date = new DateOnly(2026, 9, 1);
TimeOnly heure = new TimeOnly(14, 30);
 
DateTime rendezVous = date.ToDateTime(heure);   // 2026-09-01 14:30:00

Et inversement, on décompose un DateTime :

DateTime dt = DateTime.Now;
DateOnly d = DateOnly.FromDateTime(dt);
TimeOnly t = TimeOnly.FromDateTime(dt);

# Formater et parser

Mêmes symboles que DateTime, mais limités à la partie pertinente :

date.ToString("yyyy-MM-dd");     // "2026-09-01"
heure.ToString("HH:mm");         // "14:30"
 
DateOnly.Parse("2026-09-01");
TimeOnly.Parse("14:30");
 
// Robuste pour une entrée externe
if (DateOnly.TryParse(saisie, out DateOnly resultat)) { /* ... */ }

Choisir DateOnly pour une date de naissance ou TimeOnly pour un horaire, c'est rendre l'intention explicite dans le type : le compilateur t'empêche d'y coller une heure ou un fuseau qui n'ont rien à y faire.


# La suite