Partager via


Comment utiliser les structures DateOnly et TimeOnly

Les structures DateOnly et TimeOnly ont été introduites avec .NET 6 et représentent respectivement une date ou une heure spécifique. Avant .NET 6, et toujours dans .NET Framework, les développeurs ont utilisé le type DateTime (ou une autre alternative) pour représenter l’une des options suivantes :

  • Une date et une heure entières.
  • Une date, sans tenir compte de l'heure.
  • Une heure, sans tenir compte de la date.

DateOnly et TimeOnly sont des types qui représentent ces parties particulières d’un type DateTime.

Important

DateOnly et les types TimeOnly ne sont pas disponibles pour .NET Framework.

La structure DateOnly

La structure DateOnly représente une date spécifique, sans heure. Étant donné qu’il n’a pas de composant d’heure, il représente une date du début du jour à la fin du jour. Cette structure est idéale pour stocker des dates spécifiques, telles qu’une date de naissance, une date anniversaire ou des dates professionnelles.

Bien que vous puissiez utiliser DateTime tout en ignorant le composant de temps, il existe quelques avantages à utiliser DateOnly sur DateTime:

  • La structure DateTime peut passer au jour précédent ou suivant si elle est décalée par un fuseau horaire. DateOnly ne peut pas être décalé par un fuseau horaire et représente toujours la date définie.

  • La sérialisation d’une structure DateTime inclut le composant de temps, qui peut masquer l’intention des données. En outre, DateOnly sérialise moins de données.

  • Lorsque le code interagit avec une base de données, telle que SQL Server, les dates entières sont généralement stockées en tant que type de données date, ce qui n’inclut pas une heure. DateOnly correspond mieux au type de base de données.

DateOnly a une plage comprise entre 0001-01-01 et 9999-12-31, tout comme DateTime. Vous pouvez spécifier un calendrier spécifique dans le constructeur DateOnly. Toutefois, un objet DateOnly représente toujours une date dans le calendrier grégorien proleptique, quel que soit le calendrier utilisé pour la construire. Par exemple, vous pouvez générer la date à partir d’un calendrier hébreu, mais la date est convertie en grégorien :

var hebrewCalendar = new System.Globalization.HebrewCalendar();
var theDate = new DateOnly(5776, 2, 8, hebrewCalendar); // 8 Cheshvan 5776

Console.WriteLine(theDate);

/* This example produces the following output:
 *
 * 10/21/2015
*/
Dim hebrewCalendar = New System.Globalization.HebrewCalendar()
Dim theDate = New DateOnly(5776, 2, 8, hebrewCalendar) ' 8 Cheshvan 5776

Console.WriteLine(theDate)

' This example produces the following output
'
' 10/21/2015

Exemples de "DateOnly"

Utilisez les exemples suivants pour en savoir plus sur DateOnly:

Convertir DateTime en DateOnly

Utilisez la méthode statique DateOnly.FromDateTime pour créer un type DateOnly à partir d’un type DateTime, comme illustré dans le code suivant :

var today = DateOnly.FromDateTime(DateTime.Now);
Console.WriteLine($"Today is {today}");

/* This example produces output similar to the following:
 * 
 * Today is 12/28/2022
*/
Dim today = DateOnly.FromDateTime(DateTime.Now)
Console.WriteLine($"Today is {today}")

' This example produces output similar to the following
' 
' Today is 12/28/2022

Ajouter ou soustraire des jours, des mois, des années

Il existe trois méthodes utilisées pour ajuster une structure de DateOnly : AddDays, AddMonthset AddYears. Chaque méthode prend un paramètre entier et augmente la date par cette mesure. Si un nombre négatif est fourni, la date est réduite par cette mesure. Les méthodes retournent une nouvelle instance de DateOnly, car la structure est immuable.

var theDate = new DateOnly(2015, 10, 21);

var nextDay = theDate.AddDays(1);
var previousDay = theDate.AddDays(-1);
var decadeLater = theDate.AddYears(10);
var lastMonth = theDate.AddMonths(-1);

Console.WriteLine($"Date: {theDate}");
Console.WriteLine($" Next day: {nextDay}");
Console.WriteLine($" Previous day: {previousDay}");
Console.WriteLine($" Decade later: {decadeLater}");
Console.WriteLine($" Last month: {lastMonth}");

/* This example produces the following output:
 * 
 * Date: 10/21/2015
 *  Next day: 10/22/2015
 *  Previous day: 10/20/2015
 *  Decade later: 10/21/2025
 *  Last month: 9/21/2015
*/
Dim theDate = New DateOnly(2015, 10, 21)

Dim nextDay = theDate.AddDays(1)
Dim previousDay = theDate.AddDays(-1)
Dim decadeLater = theDate.AddYears(10)
Dim lastMonth = theDate.AddMonths(-1)

Console.WriteLine($"Date: {theDate}")
Console.WriteLine($" Next day: {nextDay}")
Console.WriteLine($" Previous day: {previousDay}")
Console.WriteLine($" Decade later: {decadeLater}")
Console.WriteLine($" Last month: {lastMonth}")

' This example produces the following output
' 
' Date: 10/21/2015
'  Next day: 10/22/2015
'  Previous day: 10/20/2015
'  Decade later: 10/21/2025
'  Last month: 9/21/2015

Analyser et formater DateOnly

DateOnly peuvent être analysés à partir d’une chaîne, comme la structure DateTime. Tous les éléments d'analyse standard basés sur la date fonctionnent avec DateOnly Lors de la conversion d’un type DateOnly en chaîne, vous pouvez également utiliser des modèles de mise en forme basés sur des dates .NET standard. Pour plus d'informations sur le formatage des chaînes, voir Chaînes de formatage standard de la date et de l'heure.

var theDate = DateOnly.ParseExact("21 Oct 2015", "dd MMM yyyy", CultureInfo.InvariantCulture);  // Custom format
var theDate2 = DateOnly.Parse("October 21, 2015", CultureInfo.InvariantCulture);

Console.WriteLine(theDate.ToString("m", CultureInfo.InvariantCulture));     // Month day pattern
Console.WriteLine(theDate2.ToString("o", CultureInfo.InvariantCulture));    // ISO 8601 format
Console.WriteLine(theDate2.ToLongDateString());

/* This example produces the following output:
 * 
 * October 21
 * 2015-10-21
 * Wednesday, October 21, 2015
*/
Dim theDate = DateOnly.ParseExact("21 Oct 2015", "dd MMM yyyy", CultureInfo.InvariantCulture) ' Custom format
Dim theDate2 = DateOnly.Parse("October 21, 2015", CultureInfo.InvariantCulture)

Console.WriteLine(theDate.ToString("m", CultureInfo.InvariantCulture))     ' Month day pattern
Console.WriteLine(theDate2.ToString("o", CultureInfo.InvariantCulture))    ' ISO 8601 format
Console.WriteLine(theDate2.ToLongDateString())

' This example produces the following output
' 
' October 21
' 2015-10-21
' Wednesday, October 21, 2015

Comparez DateOnly

DateOnly peut être comparé avec d'autres instances. Par exemple, vous pouvez vérifier si une date est antérieure ou postérieure à une autre, ou si une date correspond aujourd’hui à une date spécifique.

var theDate = DateOnly.ParseExact("21 Oct 2015", "dd MMM yyyy", CultureInfo.InvariantCulture);  // Custom format
var theDate2 = DateOnly.Parse("October 21, 2015", CultureInfo.InvariantCulture);
var dateLater = theDate.AddMonths(6);
var dateBefore = theDate.AddDays(-10);

Console.WriteLine($"Consider {theDate}...");
Console.WriteLine($" Is '{nameof(theDate2)}' equal? {theDate == theDate2}");
Console.WriteLine($" Is {dateLater} after? {dateLater > theDate} ");
Console.WriteLine($" Is {dateLater} before? {dateLater < theDate} ");
Console.WriteLine($" Is {dateBefore} after? {dateBefore > theDate} ");
Console.WriteLine($" Is {dateBefore} before? {dateBefore < theDate} ");

/* This example produces the following output:
 * 
 * Consider 10/21/2015
 *  Is 'theDate2' equal? True
 *  Is 4/21/2016 after? True
 *  Is 4/21/2016 before? False
 *  Is 10/11/2015 after? False
 *  Is 10/11/2015 before? True
*/
Dim theDate = DateOnly.ParseExact("21 Oct 2015", "dd MMM yyyy", CultureInfo.InvariantCulture) ' Custom format
Dim theDate2 = DateOnly.Parse("October 21, 2015", CultureInfo.InvariantCulture)
Dim dateLater = theDate.AddMonths(6)
Dim dateBefore = theDate.AddDays(-10)

Console.WriteLine($"Consider {theDate}...")
Console.WriteLine($" Is '{NameOf(theDate2)}' equal? {theDate = theDate2}")
Console.WriteLine($" Is {dateLater} after? {dateLater > theDate} ")
Console.WriteLine($" Is {dateLater} before? {dateLater < theDate} ")
Console.WriteLine($" Is {dateBefore} after? {dateBefore > theDate} ")
Console.WriteLine($" Is {dateBefore} before? {dateBefore < theDate} ")

' This example produces the following output
' 
' Consider 10/21/2015
'  Is 'theDate2' equal? True
'  Is 4/21/2016 after? True
'  Is 4/21/2016 before? False
'  Is 10/11/2015 after? False
'  Is 10/11/2015 before? True

La structure TimeOnly

La structure TimeOnly représente une valeur de temps de jour, telle qu’une horloge d’alarme quotidienne ou l’heure à laquelle vous mangez le déjeuner chaque jour. TimeOnly est limité à la plage de 00:00:00.0000000 - 23:59:59.99999999, une heure spécifique du jour.

Avant l’introduction du type TimeOnly, les programmeurs utilisaient généralement le type DateTime ou le type TimeSpan pour représenter une heure spécifique. Toutefois, l’utilisation de ces structures pour simuler une heure sans date peut entraîner des problèmes, ce qui TimeOnly résout :

  • TimeSpan représente le temps écoulé, tel que le temps mesuré avec un chronomètre. La plage supérieure est supérieure à 29 000 ans, et sa valeur peut être négative pour indiquer le recul dans le temps. Une TimeSpan négative n’indique pas une heure spécifique de la journée.

  • Si TimeSpan est utilisé comme heure de la journée, il existe un risque qu’il puisse être manipulé sur une valeur en dehors de la journée de 24 heures. TimeOnly n’a pas ce risque. Par exemple, si l'équipe de travail d'un employé commence à 18 heures et dure 8 heures, l'ajout de 8 heures à la structure TimeOnly se répercute sur 2 heures.

  • L’utilisation de DateTime pour une heure de la journée nécessite qu’une date arbitraire soit associée à l’heure, puis ignorée ultérieurement. Il est courant de choisir DateTime.MinValue (0001-01-01) comme date, toutefois, si des heures sont soustraites de la valeur DateTime, une exception OutOfRange peut se produire. TimeOnly n’a pas ce problème car le temps se déplace vers l’avant et l’arrière autour de la période de 24 heures.

  • La sérialisation d’une structure DateTime inclut le composant de date, qui peut masquer l’intention des données. En outre, TimeOnly sérialise moins de données.

Exemples TimeOnly

Utilisez les exemples suivants pour en savoir plus sur TimeOnly:

Convertir DateTime en TimeOnly

Utilisez la méthode statique TimeOnly.FromDateTime pour créer un type TimeOnly à partir d’un type DateTime, comme illustré dans le code suivant :

var now = TimeOnly.FromDateTime(DateTime.Now);
Console.WriteLine($"It is {now} right now");

/* This example produces output similar to the following:
 * 
 * It is 2:01 PM right now
*/
Dim now = TimeOnly.FromDateTime(DateTime.Now)
Console.WriteLine($"It is {now} right now")

' This example produces output similar to the following
' 
' It is 2:01 PM right now

Ajouter ou soustraire du temps

Il existe trois méthodes utilisées pour ajuster une structure de TimeOnly : AddHours, AddMinuteset Add. Les deux AddHours et AddMinutes prennent un paramètre entier et ajustent la valeur en conséquence. Vous pouvez utiliser une valeur négative pour soustraire et une valeur positive à ajouter. Les méthodes renvoient une nouvelle instance de TimeOnly, car la structure est immuable. La méthode Add prend un paramètre TimeSpan et ajoute ou soustrait la valeur de la valeur TimeOnly.

Étant donné que TimeOnly représente uniquement une période de 24 heures, elle bascule vers l’avant ou vers l’arrière correctement lors de l’ajout de valeurs fournies à ces trois méthodes. Par exemple, si vous utilisez la valeur 01:30:00 pour représenter 1 h 30 du matin, puis ajoutez -4 heures à partir de cette période, vous revenez en arrière jusqu'à 21:30:00, soit 21h30. Il existe des méthodes de surcharge pour AddHours, AddMinutes et Add qui capturent le nombre de jours reportés.

var theTime = new TimeOnly(7, 23, 11);

var hourLater = theTime.AddHours(1);
var minutesBefore = theTime.AddMinutes(-12);
var secondsAfter = theTime.Add(TimeSpan.FromSeconds(10));
var daysLater = theTime.Add(new TimeSpan(hours: 21, minutes: 200, seconds: 83), out int wrappedDays);
var daysBehind = theTime.AddHours(-222, out int wrappedDaysFromHours);

Console.WriteLine($"Time: {theTime}");
Console.WriteLine($" Hours later: {hourLater}");
Console.WriteLine($" Minutes before: {minutesBefore}");
Console.WriteLine($" Seconds after: {secondsAfter}");
Console.WriteLine($" {daysLater} is the time, which is {wrappedDays} days later");
Console.WriteLine($" {daysBehind} is the time, which is {wrappedDaysFromHours} days prior");

/* This example produces the following output:
 * 
 * Time: 7:23 AM
 *  Hours later: 8:23 AM
 *  Minutes before: 7:11 AM
 *  Seconds after: 7:23 AM
 *  7:44 AM is the time, which is 1 days later 
 *  1:23 AM is the time, which is -9 days prior
*/
Dim wrappedDays As Integer
Dim wrappedDaysFromHours As Integer

Dim theTime = New TimeOnly(7, 23, 11)

Dim hourLater = theTime.AddHours(1)
Dim minutesBefore = theTime.AddMinutes(-12)
Dim secondsAfter = theTime.Add(TimeSpan.FromSeconds(10))
Dim daysLater = theTime.Add(New TimeSpan(hours:=21, minutes:=200, seconds:=83), wrappedDays)
Dim daysBehind = theTime.AddHours(-222, wrappedDaysFromHours)

Console.WriteLine($"Time: {theTime}")
Console.WriteLine($" Hours later: {hourLater}")
Console.WriteLine($" Minutes before: {minutesBefore}")
Console.WriteLine($" Seconds after: {secondsAfter}")
Console.WriteLine($" {daysLater} is the time, which is {wrappedDays} days later")
Console.WriteLine($" {daysBehind} is the time, which is {wrappedDaysFromHours} days prior")

' This example produces the following output
' 
' Time: 7:23 AM
'  Hours later: 8:23 AM
'  Minutes before: 7:11 AM
'  Seconds after: 7:23 AM
'  7:44 AM is the time, which is 1 days later 
'  1:23 AM is the time, which is -9 days prior

Analyser et mettre en forme TimeOnly

TimeOnly peuvent être analysés à partir d’une chaîne, comme la structure DateTime. Tous les éléments d'analyse standard basés sur la date fonctionnent avec TimeOnly. Lors de la conversion d’un type TimeOnly en chaîne, vous pouvez également utiliser des modèles de mise en forme basés sur des dates .NET standard. Pour plus d'informations sur le formatage des chaînes, voir Chaînes de formatage standard de la date et de l'heure.

var theTime = TimeOnly.ParseExact("5:00 pm", "h:mm tt", CultureInfo.InvariantCulture);  // Custom format
var theTime2 = TimeOnly.Parse("17:30:25", CultureInfo.InvariantCulture);

Console.WriteLine(theTime.ToString("o", CultureInfo.InvariantCulture));     // Round-trip pattern.
Console.WriteLine(theTime2.ToString("t", CultureInfo.InvariantCulture));    // Long time format
Console.WriteLine(theTime2.ToLongTimeString());

/* This example produces the following output:
 * 
 * 17:00:00.0000000
 * 17:30
 * 5:30:25 PM
*/
Dim theTime = TimeOnly.ParseExact("5:00 pm", "h:mm tt", CultureInfo.InvariantCulture) ' Custom format
Dim theTime2 = TimeOnly.Parse("17:30:25", CultureInfo.InvariantCulture)

Console.WriteLine(theTime.ToString("o", CultureInfo.InvariantCulture))     ' Round-trip pattern.
Console.WriteLine(theTime2.ToString("t", CultureInfo.InvariantCulture))    ' Long time format
Console.WriteLine(theTime2.ToLongTimeString())

' This example produces the following output
' 
' 17:00:00.0000000
' 17:30
' 5:30:25 PM

Sérialiser les types DateOnly et TimeOnly

Avec .NET 7+, System.Text.Json prend en charge la sérialisation et la désérialisation des types DateOnly et TimeOnly. Considérez l’objet suivant :

sealed file record Appointment(
    Guid Id,
    string Description,
    DateOnly Date,
    TimeOnly StartTime,
    TimeOnly EndTime);
Public NotInheritable Class Appointment
    Public Property Id As Guid
    Public Property Description As String
    Public Property DateValue As DateOnly?
    Public Property StartTime As TimeOnly?
    Public Property EndTime As TimeOnly?
End Class

L’exemple suivant sérialise un objet Appointment, affiche le json obtenu, puis le désérialise dans une nouvelle instance du type Appointment. Enfin, les instances d’origine et nouvellement désérialisées sont comparées pour l’égalité et les résultats sont écrits dans la console :

Appointment originalAppointment = new(
    Id: Guid.NewGuid(),
    Description: "Take dog to veterinarian.",
    Date: new DateOnly(2002, 1, 13),
    StartTime: new TimeOnly(5,15),
    EndTime: new TimeOnly(5, 45));
string serialized = JsonSerializer.Serialize(originalAppointment);

Console.WriteLine($"Resulting JSON: {serialized}");

Appointment deserializedAppointment =
    JsonSerializer.Deserialize<Appointment>(serialized)!;

bool valuesAreTheSame = originalAppointment == deserializedAppointment;
Console.WriteLine($"""
    Original record has the same values as the deserialized record: {valuesAreTheSame}
    """);
        Dim originalAppointment As New Appointment With {
            .Id = Guid.NewGuid(),
            .Description = "Take dog to veterinarian.",
            .DateValue = New DateOnly(2002, 1, 13),
            .StartTime = New TimeOnly(5, 3, 1),
            .EndTime = New TimeOnly(5, 3, 1)
}
        Dim serialized As String = JsonSerializer.Serialize(originalAppointment)

        Console.WriteLine($"Resulting JSON: {serialized}")

        Dim deserializedAppointment As Appointment =
            JsonSerializer.Deserialize(Of Appointment)(serialized)

        Dim valuesAreTheSame As Boolean =
            (originalAppointment.DateValue = deserializedAppointment.DateValue AndAlso
            originalAppointment.StartTime = deserializedAppointment.StartTime AndAlso
            originalAppointment.EndTime = deserializedAppointment.EndTime AndAlso
            originalAppointment.Id = deserializedAppointment.Id AndAlso
            originalAppointment.Description = deserializedAppointment.Description)

        Console.WriteLine(
            $"Original object has the same values as the deserialized object: {valuesAreTheSame}")

Dans le code précédent :

  • Un objet Appointment est instancié et affecté à la variable appointment.
  • L’instance appointment est sérialisée en JSON à l’aide de JsonSerializer.Serialize.
  • Le json obtenu est écrit dans la console.
  • Le JSON est désérialisé dans une nouvelle instance du type Appointment à l’aide de JsonSerializer.Deserialize.
  • Les instances d’origine et nouvellement désérialisées sont comparées pour l’égalité.
  • Le résultat de la comparaison est écrit dans la console.

Pour plus d’informations, consultez Comment sérialiser et désérialiser JSON dans .NET.

Utiliser TimeSpan et DateTime

TimeOnlypeut être créé à partir d'un fichier TimeSpan. En outre, TimeOnly peut être utilisé avec un DateTime, soit pour créer une instance de TimeOnly, soit pour créer une instance de DateTime tant qu’une date est fournie.

L’exemple suivant crée un objet TimeOnly à partir d’un TimeSpan, puis le convertit en arrière :

// TimeSpan must in the range of 00:00:00.0000000 to 23:59:59.9999999
var theTime = TimeOnly.FromTimeSpan(new TimeSpan(23, 59, 59));
var theTimeSpan = theTime.ToTimeSpan();

Console.WriteLine($"Variable '{nameof(theTime)}' is {theTime}");
Console.WriteLine($"Variable '{nameof(theTimeSpan)}' is {theTimeSpan}");

/* This example produces the following output:
 * 
 * Variable 'theTime' is 11:59 PM
 * Variable 'theTimeSpan' is 23:59:59
*/
' TimeSpan must in the range of 00:00:00.0000000 to 23:59:59.9999999
Dim theTime = TimeOnly.FromTimeSpan(New TimeSpan(23, 59, 59))
Dim theTimeSpan = theTime.ToTimeSpan()

Console.WriteLine($"Variable '{NameOf(theTime)}' is {theTime}")
Console.WriteLine($"Variable '{NameOf(theTimeSpan)}' is {theTimeSpan}")

' This example produces the following output
' 
' Variable 'theTime' is 11:59 PM
' Variable 'theTimeSpan' is 23:59:59

L’exemple suivant crée un DateTime à partir d’un objet TimeOnly, avec une date arbitraire choisie :

var theTime = new TimeOnly(11, 25, 46);   // 11:25 AM and 46 seconds
var theDate = new DateOnly(2015, 10, 21); // October 21, 2015
var theDateTime = theDate.ToDateTime(theTime);
var reverseTime = TimeOnly.FromDateTime(theDateTime);

Console.WriteLine($"Date only is {theDate}");
Console.WriteLine($"Time only is {theTime}");
Console.WriteLine();
Console.WriteLine($"Combined to a DateTime type, the value is {theDateTime}");
Console.WriteLine($"Converted back from DateTime, the time is {reverseTime}");

/* This example produces the following output:
 * 
 * Date only is 10/21/2015
 * Time only is 11:25 AM
 * 
 * Combined to a DateTime type, the value is 10/21/2015 11:25:46 AM
 * Converted back from DateTime, the time is 11:25 AM
*/
Dim theTime = New TimeOnly(11, 25, 46) ' 11:   25 PM And 46 seconds
Dim theDate = New DateOnly(2015, 10, 21) ' October 21, 2015
Dim theDateTime = theDate.ToDateTime(theTime)
Dim reverseTime = TimeOnly.FromDateTime(theDateTime)

Console.WriteLine($"Date only is {theDate}")
Console.WriteLine($"Time only is {theTime}")
Console.WriteLine()
Console.WriteLine($"Combined to a DateTime type, the value is {theDateTime}")
Console.WriteLine($"Converted back from DateTime, the time is {reverseTime}")

' This example produces the following output
' 
' Date only is 10/21/2015
' Time only is 11:25 AM
' 
' Combined to a DateTime type, the value is 10/21/2015 11:25:46 AM
' Converted back from DateTime, the time is 11:25 AM

Opérateurs arithmétiques et comparaison de TimeOnly

Deux instances TimeOnly peuvent être comparées entre elles, et vous pouvez utiliser la méthode IsBetween pour vérifier si une heure est comprise entre deux autres heures. Lorsqu’un opérateur d’addition ou de soustraction est utilisé sur un TimeOnly, un TimeSpan est retourné, représentant une durée.

var start = new TimeOnly(10, 12, 01); // 10:12:01 AM
var end = new TimeOnly(14, 00, 53); // 02:00:53 PM

var outside = start.AddMinutes(-3);
var inside = start.AddMinutes(120);

Console.WriteLine($"Time starts at {start} and ends at {end}");
Console.WriteLine($" Is {outside} between the start and end? {outside.IsBetween(start, end)}");
Console.WriteLine($" Is {inside} between the start and end? {inside.IsBetween(start, end)}");
Console.WriteLine($" Is {start} less than {end}? {start < end}");
Console.WriteLine($" Is {start} greater than {end}? {start > end}");
Console.WriteLine($" Does {start} equal {end}? {start == end}");
Console.WriteLine($" The time between {start} and {end} is {end - start}");

/* This example produces the following output:
 * 
 * Time starts at 10:12 AM and ends at 2:00 PM
 *  Is 10:09 AM between the start and end? False
 *  Is 12:12 PM between the start and end? True
 *  Is 10:12 AM less than 2:00 PM? True
 *  Is 10:12 AM greater than 2:00 PM? False
 *  Does 10:12 AM equal 2:00 PM? False
 *  The time between 10:12 AM and 2:00 PM is 03:48:52
*/
Dim startDate = New TimeOnly(10, 12, 1) ' 10:12:01 AM
Dim endDate = New TimeOnly(14, 0, 53) ' 02:00:53 PM

Dim outside = startDate.AddMinutes(-3)
Dim inside = startDate.AddMinutes(120)

Console.WriteLine($"Time starts at {startDate} and ends at {endDate}")
Console.WriteLine($" Is {outside} between the start and end? {outside.IsBetween(startDate, endDate)}")
Console.WriteLine($" Is {inside} between the start and end? {inside.IsBetween(startDate, endDate)}")
Console.WriteLine($" Is {startDate} less than {endDate}? {startDate < endDate}")
Console.WriteLine($" Is {startDate} greater than {endDate}? {startDate > endDate}")
Console.WriteLine($" Does {startDate} equal {endDate}? {startDate = endDate}")
Console.WriteLine($" The time between {startDate} and {endDate} is {endDate - startDate}")

' This example produces the following output
' 
' Time starts at 10:12 AM And ends at 2:00 PM
'  Is 10:09 AM between the start And end? False
'  Is 12:12 PM between the start And end? True
'  Is 10:12 AM less than 2:00 PM? True
'  Is 10:12 AM greater than 2:00 PM? False
'  Does 10:12 AM equal 2:00 PM? False
'  The time between 10:12 AM and 2:00 PM is 03:48:52