OOP Course
Сьогодні

Підрозділ 12.1

Структура DateTime

Пояснює DateTime: створення дат і часу, MinValue, Now, UtcNow, Today, григоріанський календар, додавання й віднімання дат та стандартні формати виведення.

12.1. Структура DateTime

Дата і час — невід'ємна частина медичних інформаційних систем. Час прийому пацієнта, дата виписки, вік пацієнта в роках, тривалість госпіталізації, терміни зберігання аналізів — усе це вимагає роботи з датами. Центральний тип у .NET для цього завдання — структура DateTime з простору імен System.

DateTime — це структура (struct), тобто значущий тип (value type). На відміну від класів, екземпляр DateTime зберігається безпосередньо на стеку або всередині об'єкта і копіюється при присвоєнні — так само як int або double. Порівняння двох DateTime через == порівнює їхні значення, а не посилання.

Структура DateTime — внутрішня будова та ключові властивості

Внутрішнє представлення: тіки

Внутрішньо DateTime зберігає єдине 64-бітне ціле число — кількість тіків (ticks). Один тік дорівнює 100 наносекундам. Відлік іде від полудня 1 січня 0001 року (00:00:00.0000000) за григоріанським календарем. Доступ до тіків — через властивість Ticks:

DateTime admission = new DateTime(2026, 6, 11, 9, 30, 0);
Console.WriteLine(admission.Ticks); // 638 814 126 000 000 000

Знання про тіки важливе для двох причин: по-перше, всі операції порівняння і арифметика дат зводяться до порівняння та арифметики цих цілих чисел, що є дуже швидким; по-друге, TimeSpan (розд. 12.4) також зберігає тіки — тому два типи легко взаємодіють.

DateTimeKind: прив'язка до часового поясу

Кожен об'єкт DateTime має властивість Kind типу DateTimeKind — вона визначає, до якого часового поясу прив'язане значення:

Kind Значення Коли використовується
Unspecified Невідомо (за замовчуванням) Локальні розрахунки без прив'язки до поясу
Local Локальний час ОС Відображення в UI поточного сервера/комп'ютера
Utc Час UTC (Coordinated Universal Time) Зберігання у БД, API, аудит-журнали
DateTime local = DateTime.Now;        // Kind = Local
DateTime utc   = DateTime.UtcNow;     // Kind = Utc
DateTime unsp  = new DateTime(2026, 6, 11); // Kind = Unspecified

Чому це критично в медичних системах: якщо лікарня або телемедичний сервіс працює в кількох часових поясах, зберігання DateTime.Now (Local) у базі даних призводить до помилок при агрегації даних. Правило: завжди зберігати у БД UTC (DateTime.UtcNow), а конвертацію у локальний час виконувати на рівні UI.

UTC vs Local: практична пастка та конвертація

Порушення правила «зберігати UTC, відображати локальний час» призводить до важко діагностованих помилок:

Методи конвертації:

Метод Що робить
.ToUniversalTime() Local → UTC (або Unspecified → UTC припускаючи Local)
.ToLocalTime() UTC → Local
DateTime.SpecifyKind(dt, kind) Перепозначити Kind без зміни значення

Правило для медичних систем: все, що стосується аудиту, журналів, зберігання у БД, API — тільки UTC. Відображення у UI або при звітуванні — конвертувати у Local прямо перед виводом.

Конструктори DateTime

// Мінімальна дата (01.01.0001 00:00:00)
DateTime zero = new DateTime();
Console.WriteLine(DateTime.MinValue); // 01.01.0001 0:00:00

// Рік, місяць, день
DateTime birthDate = new DateTime(1958, 4, 15); // 15 квітня 1958 р.

// Рік, місяць, день, година, хвилина, секунда
DateTime admission = new DateTime(2026, 6, 11, 9, 30, 0); // 09:30:00

// Повна точність: + мілісекунди
DateTime precise  = new DateTime(2026, 6, 11, 9, 30, 0, 123); // 09:30:00.123

// З явним Kind
DateTime utc = new DateTime(2026, 6, 11, 7, 30, 0, DateTimeKind.Utc);

Статичні властивості

Властивість Що повертає
DateTime.Now Поточна дата і час (Kind=Local)
DateTime.UtcNow Поточна дата і час (Kind=Utc)
DateTime.Today Поточна дата, час = 00:00:00
DateTime.MinValue 01.01.0001 00:00:00
DateTime.MaxValue 31.12.9999 23:59:59
Console.WriteLine(DateTime.Now);    // 11.06.2026 11:43:33
Console.WriteLine(DateTime.UtcNow); // 11.06.2026  8:43:33 (UTC+3 → -3 год)
Console.WriteLine(DateTime.Today);  // 11.06.2026  0:00:00

Властивості екземпляра

Об'єкт DateTime надає доступ до кожного компоненту окремо:

Властивість Тип Опис
Year / Month / Day int Рік, місяць (1-12), день (1-31)
Hour / Minute / Second int Година (0-23), хвилина (0-59), секунда (0-59)
Millisecond int Мілісекунди (0-999)
DayOfWeek DayOfWeek День тижня (DayOfWeek.Monday тощо)
DayOfYear int Порядковий номер дня у році (1-366)
TimeOfDay TimeSpan Час доби від початку дня
Date DateTime Лише дата, час = 00:00:00
Kind DateTimeKind Тип часової прив'язки
Ticks long Кількість тіків
DateTime dt = new DateTime(2026, 6, 11, 14, 30, 25);

Console.WriteLine(dt.Year);        // 2026
Console.WriteLine(dt.DayOfWeek);   // Thursday
Console.WriteLine(dt.DayOfYear);   // 162
Console.WriteLine(dt.TimeOfDay);   // 14:30:25
Console.WriteLine(dt.Date);        // 11.06.2026 0:00:00

Арифметика дат: методи Add*

Усі методи Add* повертають новий об'єкт DateTime — не змінюють оригінал (структура є незмінним значенням у цьому сенсі):

Метод Опис
AddYears(n) Додати/відняти роки
AddMonths(n) Додати/відняти місяці
AddDays(n) Додати/відняти дні
AddHours(n) Додати/відняти години
AddMinutes(n) Додати/відняти хвилини
AddSeconds(n) Додати/відняти секунди
Add(TimeSpan) Додати довільний інтервал

Для віднімання передають від'ємне число:

DateTime admission = new DateTime(2026, 6, 11, 9, 30, 0);

DateTime discharge = admission.AddDays(7);        // виписка через 7 днів
DateTime nextVisit = discharge.AddMonths(1);       // повторний огляд за місяць
DateTime before    = admission.AddHours(-2);       // 2 години до прийому

Console.WriteLine(discharge);  // 18.06.2026 9:30:00
Console.WriteLine(nextVisit);  // 18.07.2026 9:30:00

Різниця між датами: Subtract і оператор –

Метод Subtract(DateTime) і оператор між двома датами повертають TimeSpan — об'єкт, що представляє тривалість інтервалу (розд. 12.4):

DateTime admission  = new DateTime(2026, 6, 1, 10, 0, 0);
DateTime discharge  = new DateTime(2026, 6, 8, 14, 30, 0);

TimeSpan stay = discharge - admission;          // або discharge.Subtract(admission)
Console.WriteLine(stay.Days);                   // 7
Console.WriteLine(stay.TotalHours);             // 172.5

Порівняння дат

Оператори >, <, >=, <=, ==, != для DateTime порівнюють значення хронологічно:

DateTime d1 = new DateTime(2026, 6, 1);
DateTime d2 = new DateTime(2026, 7, 1);

bool earlier = d1 < d2;  // true — червень раніше за липень
bool equal   = d1 == d1; // true

int cmp = DateTime.Compare(d1, d2); // -1 (d1 < d2), 0 (рівні), +1 (d1 > d2)

Для перевірки чи дата потрапляє у діапазон достатньо двох умов:

DateTime start = new DateTime(2026, 6, 1);
DateTime end   = new DateTime(2026, 6, 30);
DateTime today = DateTime.Today;

bool inRange = today >= start && today <= end;

Корисні статичні методи

// Перевірка високосного року
bool leap = DateTime.IsLeapYear(2024); // true

// Кількість днів у місяці
int days = DateTime.DaysInMonth(2024, 2); // 29 (2024 — високосний)

Дата народження та вік пацієнта — runnable приклад

Розрахунок віку пацієнта та основні операції з датами прийому:

Розклад прийомів у відділенні — runnable приклад

Робота з датами та часом в контексті розкладу пацієнтів:

Розроблено Tomka Yurii · © 2026 ·