Использование структур DateOnly и TimeOnly

TimeOnly Структуры DateOnly были представлены в .NET 6 и представляют определенную дату или время дня соответственно. До .NET 6 и всегда в платформа .NET Framework разработчики использовали DateTime тип (или другую альтернативу) для представления одного из следующих вариантов:

  • Целый день и время.
  • Дата, игнорирующая время.
  • Время, игнорирующее дату.

DateOnly и TimeOnly являются типами DateTime , представляющими эти определенные части типа.

Внимание

DateOnlyи TimeOnly типы недоступны в платформа .NET Framework.

Структура DateOnly

Структура DateOnly представляет определенную дату без времени. Поскольку он не имеет компонента времени, он представляет дату с начала дня до конца дня. Эта структура идеально подходит для хранения конкретных дат, таких как дата рождения, дата годовщины или даты, связанные с бизнесом.

Несмотря на то, что вы можете использовать DateTime при игнорировать компонент времени, существует несколько преимуществ использованияDateOnly:DateTime

  • Структура DateTime может свернуться в предыдущий или следующий день, если это смещение часового пояса. DateOnly не может быть смещение по часовой поясу, и всегда представляет дату, заданную.

  • Сериализация DateTime структуры включает компонент времени, который может скрыть намерение данных. Кроме того, DateOnly сериализует меньше данных.

  • При взаимодействии кода с базой данных, например SQL Server, все даты обычно хранятся как date тип данных, который не включает время. DateOnly лучше соответствует типу базы данных.

DateOnly имеет диапазон от 0001-01-01 до 9999-12-31, как DateTimeи . В конструкторе можно указать определенный DateOnly календарь. DateOnly Однако объект всегда представляет дату в пролептическом григорианском календаре, независимо от того, какой календарь использовался для его создания. Например, можно создать дату из еврейского календаря, но дата преобразуется в григорианский:

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

Примеры DateOnly

Используйте следующие примеры, чтобы узнать о DateOnlyследующем:

Преобразование DateTime в DateOnly

Используйте статический DateOnly.FromDateTime метод для создания DateOnly типа из DateTime типа, как показано в следующем коде:

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

Добавление или вычитание дней, месяцев, лет

Существует три метода, используемых для настройки DateOnly структуры: AddDays, AddMonthsи AddYears. Каждый метод принимает целочисленный параметр и увеличивает дату на это измерение. Если указано отрицательное число, дата уменьшается на это измерение. Методы возвращают новый экземпляр DateOnly, так как структура неизменяема.

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

Анализ и форматирование DateOnly

DateOnly можно проанализировать из строки так же, как DateTime и структура. Все стандартные маркеры синтаксического анализа дат .NET работают с DateOnly. При преобразовании DateOnly типа в строку можно использовать стандартные шаблоны форматирования на основе дат .NET. Дополнительные сведения о форматировании строк см. в строках стандартного формата даты и времени.

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

Сравнение DateOnly

DateOnly можно сравнить с другими экземплярами. Например, можно проверка, если дата находится до или после другой, или если дата сегодня соответствует определенной дате.

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

Структура TimeOnly

Структура TimeOnly представляет значение времени дня, например ежедневное будильник или время, когда вы едите обед каждый день. TimeOnlyограничен диапазоном от 00:00:00,0000000 - 23:59:59.9999999999, определенное время дня.

TimeOnly До введения типа программисты обычно используют DateTime тип или TimeSpan тип для представления определенного времени. Однако использование этих структур для имитации времени без даты может привести к некоторым проблемам, которые TimeOnly решают:

  • TimeSpan представляет истекшее время, например время, измеряемое с помощью стоп-часов. Верхний диапазон составляет более 29 000 лет, и его значение может быть отрицательным, чтобы указать, что перемещение назад во времени. Отрицательный TimeSpan не указывает определенное время дня.

  • Если TimeSpan используется в качестве времени суток, существует риск того, что он может быть манипулировать значением за пределами 24-часового дня. TimeOnly не имеет этого риска. Например, если смена работы сотрудника начинается с 18:00 и длится в течение 8 часов, добавление 8 часов в TimeOnly структуру выполняется до 2:00.

  • Использование DateTime в течение дня требует, чтобы произвольные даты были связаны с временем, а затем игнорировались позже. Обычно рекомендуется выбрать DateTime.MinValue (0001-01-01) в качестве даты, однако если часы вычитаются из DateTime значения, OutOfRange может возникнуть исключение. TimeOnly не имеет этой проблемы, так как время откатывается вперед и назад вокруг 24-часового интервала времени.

  • Сериализация DateTime структуры включает компонент даты, который может скрыть намерение данных. Кроме того, TimeOnly сериализует меньше данных.

Примеры TimeOnly

Используйте следующие примеры, чтобы узнать о TimeOnlyследующем:

Преобразование DateTime в TimeOnly

Используйте статический TimeOnly.FromDateTime метод для создания TimeOnly типа из DateTime типа, как показано в следующем коде:

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

Добавление или вычитание времени

Существует три метода, используемых для настройки TimeOnly структуры: AddHours, AddMinutesи Add. Оба AddHours параметра и AddMinutes принимает целочисленный параметр и настраивает значение соответствующим образом. Вы можете использовать отрицательное значение для вычитания и положительного значения для добавления. Методы возвращают новый экземпляр TimeOnly , так как структура неизменяема. Метод Add принимает TimeSpan параметр и добавляет или вычитает значение из TimeOnly значения.

Так как TimeOnly представляет собой только 24-часовой период, он выполняет перекат вперед или обратно при добавлении значений, предоставленных этим трем методам. Например, если вы используете значение 01:30:00 для представления 1:30, добавьте -4 часа с этого периода, он откатывается назад 21:30:00к , что составляет 9:30 вечера. Существуют перегрузки методов для AddHours, AddMinutesи Add это фиксирует количество дней, откатированных.

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

Анализ и форматирование TimeOnly

TimeOnly можно проанализировать из строки так же, как DateTime и структура. Все стандартные маркеры синтаксического анализа на основе времени .NET работают с TimeOnly. При преобразовании TimeOnly типа в строку можно использовать стандартные шаблоны форматирования на основе дат .NET. Дополнительные сведения о форматировании строк см. в строках стандартного формата даты и времени.

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

Сериализация типов DateOnly и TimeOnly

С помощью .NET 7+поддерживает System.Text.Json сериализацию и десериализацию DateOnly и TimeOnly типы. Рассмотрим следующий объект:

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

В следующем примере сериализуется Appointment объект, отображается результирующий json, а затем десериализирует его обратно в новый экземпляр Appointment типа. Наконец, исходные и недавно десериализированные экземпляры сравниваются для равенства, а результаты записываются в консоль:

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}")

В предыдущем коде:

  • Объект Appointment создается и назначается переменной appointment .
  • Экземпляр appointment сериализуется в JSON с помощью JsonSerializer.Serialize.
  • Результирующий json записывается в консоль.
  • JSON десериализирован обратно в новый экземпляр Appointment типа с помощью JsonSerializer.Deserialize.
  • Исходные и недавно десериализированные экземпляры сравниваются для равенства.
  • Результат сравнения записывается в консоль.

Дополнительные сведения см. в статье о сериализации и десериализации JSON в .NET.

Работа с TimeSpan и DateTime

TimeOnly можно создать из и преобразовать в объект TimeSpan. Кроме того, TimeOnly можно использовать для DateTimeсоздания экземпляра или для создания TimeOnlyDateTime экземпляра до тех пор, пока указана дата.

Следующий пример создает TimeOnly объект из объекта TimeSpan, а затем преобразует его обратно:

// 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

В следующем примере создается DateTime объект с TimeOnly выбранной произвольной датой:

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

Арифметические операторы и сравнение TimeOnly

Два TimeOnly экземпляра можно сравнить друг с другом, и можно использовать IsBetween метод для проверка, если время между двумя другими. При использовании TimeOnlyTimeSpan оператора добавления или вычитания для объекта возвращается значение, представляющее длительность времени.

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