JavaRush /Курси /C# SELF /Обчислення та допоміжні класи для дат і часу

Обчислення та допоміжні класи для дат і часу

C# SELF
Рівень 15 , Лекція 4
Відкрита

1. Основні завдання під час роботи з датою та часом

Робота з датами й часом часто викликає легке, а іноді й зовсім не легке, відчуття паніки навіть у досвідчених розробників. Треба порівнювати дати, обчислювати інтервали, додавати або віднімати дні, місяці, роки, рахувати вік, визначати день тижня — і ще багато всього.

Усе це — типові завдання для трекерів завдань і календарів, обліку абонементів чи підписок, фінансових розрахунків, статистичних звітів і, звісно, для задач на співбесідах (наприклад, «порахувати кількість робочих днів між двома датами»).

У C# і .NET для цього є вбудовані класи й методи. А головне — більшість обчислень виконується через обʼєктно-орієнтований, максимально безпечний і зрозумілий API.

2. Структура TimeSpan — вимірюємо інтервали часу

Усе починається зі структури TimeSpan. Це «шматочок» часу: наприклад, 5 днів, 3 години, 7 хвилин і 21 секунда.

Як створити TimeSpan?

Можна «відняти» дві дати або створити його явно:

// Різниця між двома датами завжди TimeSpan!
DateTime start = new DateTime(2025, 5, 1, 7, 0, 0);
DateTime end = new DateTime(2025, 5, 2, 11, 30, 0);

TimeSpan duration = end - start; // Повна магія!
Console.WriteLine(duration); // 1.04:30:00 (1 день, 4 години, 30 хвилин)

Можна створити TimeSpan явно через параметри конструктора:

TimeSpan span = new TimeSpan(2, 14, 18, 0); // 2 дні, 14 годин, 18 хвилин, 0 секунд
Console.WriteLine(span); // 2.14:18:00

Альтернативний спосіб — статичні методи, які зазвичай читабельніші:

TimeSpan fiveMinutes = TimeSpan.FromMinutes(5);
TimeSpan twoHours = TimeSpan.FromHours(2);
TimeSpan oneWeek = TimeSpan.FromDays(7);

Які властивості є у TimeSpan?

Властивість Опис
Days
Ціла кількість днів
Hours
Годинна частина
Minutes
Хвилинна частина
Seconds
Секундна частина
TotalDays
Час у днях (із дробовою частиною)
TotalHours
Час у годинах (із дробовою частиною)
TotalMinutes
Час у хвилинах (із дробовою частиною)
TotalSeconds
Час у секундах (із дробовою частиною)
Console.WriteLine($"Днів: {duration.Days}, усього годин: {duration.TotalHours}");

Як додати/відняти TimeSpan з дати?

DateTime now = DateTime.Now;
DateTime future = now.Add(duration); // Додали duration до now
DateTime past = now.Subtract(TimeSpan.FromDays(10)); // Мінус 10 днів

Console.WriteLine(future);
Console.WriteLine(past);

3. Калькулятор дат: обчислюємо різницю між датами

Навичка, яка стане в пригоді майже завжди. Наприклад, хтось хоче знати, скільки залишилося до відпустки, а хтось — коли закінчується безкоштовний період.

DateTime today = DateTime.Today;
DateTime vacation = new DateTime(2025, 8, 1);
TimeSpan untilVacation = vacation - today;

Console.WriteLine($"До відпустки залишилося {untilVacation.Days} днів!");

Зверніть увагу: якщо у відніманні беруть участь лише «дати» без часу (через DateTime.Date або DateTime.Today), то результат завжди ціле число днів. А якщо хоча б одна дата містить час, різниця — дробова.


int days = (vacation - today).TotalDays; // Помилка компіляції! TotalDays — double

Якщо потрібне ціле число — використовуйте .Days або перетворіть значення на цілий тип: (int)TotalDays.

4. Додавання і віднімання часу: методи AddDays, AddMonths, AddHours, ...

C# не вимагає ручного підрахунку днів у кожному місяці, високосних років і подібних дрібниць. Просто скористайтеся:

DateTime orderDate = new DateTime(2024, 4, 20);
DateTime deliveryDate = orderDate.AddDays(14); // Через 2 тижні

Console.WriteLine($"Товар буде доставлено {deliveryDate.ToShortDateString()}");
Метод Що додає (або віднімає при відʼємному числі)
AddDays(double)
Дні (підтримка дробів, наприклад 1,5 дня)
AddMonths(int)
Місяці (автоматично враховує довжину місяця)
AddYears(int)
Роки (з урахуванням високосних років)
AddHours(double)
Години
AddMinutes(double)
Хвилини
AddSeconds(double)
Секунди
DateTime birthday = new DateTime(2000, 2, 29);
DateTime nextYear = birthday.AddYears(1); // 2001-02-28 (а не 29-го, адже 2001 рік невисокосний)
Console.WriteLine(nextYear.ToShortDateString()); // 28.02.2001

Памʼятайте: усі методи повертають новий екземпляр дати, початкова дата не змінюється!

var dt = DateTime.Now;
dt.AddDays(5); // Це НЕ змінить dt!
dt = dt.AddDays(5); // Тепер зміниться

5. Допоміжні методи для обчислень

Визначення дня тижня

У більшості випадків можна використовувати властивість .DayOfWeek:

DateTime examDate = new DateTime(2025, 6, 19);
DayOfWeek day = examDate.DayOfWeek;
Console.WriteLine(day); // Wednesday

Можна перетворити на ціле число:

int number = (int)day; // Sunday == 0, Monday == 1, і так далі

Перевірка «сьогодні», «вчора», «завтра»

Найпростіші порівняння:

DateTime date = new DateTime(2025, 6, 18);

if (date.Date == DateTime.Today)
    Console.WriteLine("Сьогодні!");
else if (date.Date == DateTime.Today.AddDays(-1))
    Console.WriteLine("Вчора!");
else if (date.Date == DateTime.Today.AddDays(1))
    Console.WriteLine("Завтра!");

Обчислення віку

Одна з найчастіших задач — коректно обчислити вік людини. Просте віднімання років не завжди працює правильно:

public static int CalculateAge(DateTime birthDate, DateTime currentDate)
{
    int age = currentDate.Year - birthDate.Year;
    
    // Якщо день народження ще не настав у цьому році
    if (currentDate.Month < birthDate.Month || 
        (currentDate.Month == birthDate.Month && currentDate.Day < birthDate.Day))
    {
        age--;
    }
    
    return age;
}

// Використання
DateTime birth = new DateTime(1990, 8, 15);
DateTime today = DateTime.Today;
int age = CalculateAge(birth, today);
Console.WriteLine($"Вік: {age} років");

Робота з робочими днями

Часто потрібно підрахувати кількість робочих днів між датами, виключаючи вихідні:

public static int CountWorkingDays(DateTime startDate, DateTime endDate)
{
    int workingDays = 0;
    DateTime current = startDate;
    
    while (current <= endDate)
    {
        if (current.DayOfWeek != DayOfWeek.Saturday && 
            current.DayOfWeek != DayOfWeek.Sunday)
        {
            workingDays++;
        }
        current = current.AddDays(1);
    }
    
    return workingDays;
}

6. Як повʼязані основні класи

graph TD
A(DateTime) --віднімання--> B(TimeSpan)
A2(DateTime) --AddDays, AddMonths--> A
A --ToLocalTime/ToUniversalTime--> C(DateTimeOffset)
D(DateOnly) --ToDateTime--> A
E(TimeOnly) --ToTimeSpan--> B
A --DayOfWeek, Day, Month, Year--> F(Числові властивості)
B(TimeSpan) --TotalDays, TotalHours, ...-->G(Властивості тривалості)

7. Швидкий «довідник»: що робити, якщо…

Завдання Що використовувати Приклад
Дізнатися різницю між датами
TimeSpan duration = d2 - d1
(d2 - d1).Days
Додати 2 тижні до дати
date.AddDays(14)
date.AddDays(14)
Обчислити вік Формула з
.Year
і перевіркою місяця/дня
Див. розділ вище
Отримати/встановити лише дату
DateOnly
DateOnly.FromDateTime(DateTime.Now)
Отримати/встановити лише час
TimeOnly
TimeOnly.FromDateTime(DateTime.Now)
Порівняти дати Оператори
<
,
>
,
==
,
.CompareTo()
if (d1 < d2) ...
Перевести до іншого часового поясу
DateTimeOffset + ToOffset
dto.ToOffset(TimeSpan.FromHours(3))
Дізнатися номер тижня у році
Calendar.GetWeekOfYear()
див. документацію
Дізнатися день тижня
date.DayOfWeek
Порахувати робочі дні Цикл із перевіркою
DayOfWeek
Див. розділ вище
1
Опитування
Робота з датами, рівень 15, лекція 4
Недоступний
Робота з датами
Робота з датами, часом і таймзонами
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ