1. Wprowadzenie
Kiedyś w C# nie było osobnego typu tylko na datę albo tylko na czas. Więc nawet jeśli chciałeś przechować samą datę — na przykład urodziny — musiałeś używać DateTime i dodawać "domyślną godzinę". Stary sposób przechowywania samej daty przez DateTime:
DateTime birthday = new DateTime(1985, 4, 20); // 20 kwietnia 1985 roku, 00:00:00
Ale to jest niewygodne. Chcesz tylko datę, a dostajesz jeszcze czas — nawet jeśli zerowy. To może wprowadzać zamieszanie: na przykład przy porównywaniu dat program może brać pod uwagę też czas i dostaniesz nieoczekiwane wyniki.
To samo w drugą stronę: jeśli pracujesz tylko z czasem (np. grafik pracy od 08:00 do 17:00), i tak musiałeś "wymyślić" jakąś datę, chociaż w ogóle nie była potrzebna.
Teraz w .NET są specjalne typy DateOnly i TimeOnly, które rozwiązują ten bałagan.
Nowe przydatne typy DateOnly i TimeOnly
- DateOnly — tylko data kalendarzowa, bez godziny i bez informacji o strefie czasowej.
- TimeOnly — tylko godzina w ciągu dnia, bez roku, miesiąca, dnia i oczywiście bez strefy czasowej.
Tabela porównawcza typów czasu
| Typ | Data | Czas | Strefa czasowa | Do czego używać? |
|---|---|---|---|---|
|
✅ | ✅ | 🚫 | Prawie do wszystkiego (ale nie zawsze wygodne i bezpieczne) |
|
✅ | ✅ | ✅ | Kiedy potrzebny jest moment w czasie i strefa czasowa |
|
✅ | 🚫 | 🚫 | Urodziny, daty bez czasu |
|
🚫 | ✅ | 🚫 | Godziny pracy, grafiki, przedziały w ciągu dnia |
2. Praca z DateOnly
Deklaracja i tworzenie
Stworzyć obiekt DateOnly — jak zacząć nowy nawyk: prosto i szybko! Na przykład:
// Rok, miesiąc, dzień
DateOnly birthday = new DateOnly(1985, 4, 20);
Możesz użyć DateOnly.FromDateTime, jeśli już masz obiekt DateTime:
DateTime now = DateTime.Now;
DateOnly today = DateOnly.FromDateTime(now);
// teraz today zawiera tylko datę, czas jest odrzucony
Podstawowe właściwości i metody
- Year, Month, Day — tak samo jak w DateTime.
- .ToString() — formatuje datę, możesz podać własny format.
Console.WriteLine($"Data urodzenia: {birthday.Year} rok, {birthday.Month} miesiąc, {birthday.Day} dzień.");
Console.WriteLine(today.ToString("dd.MM.yyyy")); // Na przykład, 30.07.2024
Arytmetyka dat
Możesz łatwo dodawać dni/miesiące/lata:
DateOnly tomorrow = today.AddDays(1);
DateOnly nextMonth = today.AddMonths(1);
Spróbuj w swoim głównym projekcie zamienić pola typu DateTime, które przechowują tylko datę, na DateOnly — będziesz o krok bliżej do nowoczesnego .NET!
Porównywanie dat
Działa porównywanie przez <, >, ==:
if (birthday < today)
Console.WriteLine("Urodziny już były w tym roku albo dawno :)");
Nie będzie już błędów przez zbędne milisekundy i minuty.
Pobieranie dzisiejszej daty
DateOnly currentDate = DateOnly.FromDateTime(DateTime.Now);
3. Praca z TimeOnly
Teraz zajmiemy się czasem bez daty — bo który programista nie miał do czynienia z grafikami lunchów?
Tworzenie TimeOnly
TimeOnly startWork = new TimeOnly(9, 0); // 09:00
TimeOnly endWork = new TimeOnly(17, 30); // 17:30
Możemy pobrać tylko godziny, minuty, sekundy:
Console.WriteLine($"Dzień pracy: od {startWork.Hour}:{startWork.Minute:D2} do {endWork.Hour}:{endWork.Minute:D2}");
Pobierz czas z DateTime
DateTime now = DateTime.Now;
TimeOnly currentTime = TimeOnly.FromDateTime(now);
Console.WriteLine($"Teraz {currentTime}");
Arytmetyka czasu
TimeOnly breakStart = startWork.AddHours(4); // przerwa po 4 godzinach, czyli o 13:00
TimeOnly breakEnd = breakStart.AddMinutes(30); // 30 minut lunchu
Porównania i sprawdzenia
if (currentTime >= startWork && currentTime <= endWork)
Console.WriteLine("Czas pracować :)");
else
Console.WriteLine("Można odpocząć.");
4. Współpraca z innymi typami
Konwersja między DateOnly, TimeOnly i DateTime
Czasem trzeba znowu dostać DateTime (np. do przechowywania w starej bazie albo dla kompatybilności):
DateOnly datePart = new DateOnly(2024, 7, 30);
TimeOnly timePart = new TimeOnly(14, 15);
DateTime datetime = datePart.ToDateTime(timePart); // 2024-07-30 14:15:00
I odwrotnie:
DateTime dt = DateTime.Now;
DateOnly justDate = DateOnly.FromDateTime(dt);
TimeOnly justTime = TimeOnly.FromDateTime(dt);
Ważne cechy i typowe błędy
- Jeśli spróbujesz sparsować tylko datę albo tylko czas przez stare metody jak DateTime.Parse(), najprawdopodobniej dostaniesz błąd albo nie to, czego oczekiwałeś. Do takich przypadków są specjalne metody: używaj DateOnly.Parse() i TimeOnly.Parse() — one wiedzą, jak radzić sobie z "uciętymi" wartościami.
- Ważne: DateOnly i TimeOnly nie mają żadnego pojęcia o strefach czasowych. To po prostu data albo po prostu czas — bez powiązania ze strefą. Jeśli musisz brać pod uwagę strefy, przechowuj tę informację osobno.
GO TO FULL VERSION