Datum en tijd

Elke programmeur krijgt bij het ontwikkelen van applicaties te maken met datum en tijd. De .NET Framework Class Library bevat de DateTime class die hiervoor gebruikt kan worden.

Een instantie van DateTime staat voor een moment in de tijd.

De range waartussen dit moment kan vallen is: 12:00:00 middernacht, januari 1, 0001 AD tot 11:59:59 PM, december 31 9999 AD

Je vindt een beschrijving van de DateTime class onder volgende link

Raadpleeg de beschrijving van de class DateTime bij het uitwerken van de oefeningen. Je vindt er immers handige methods in terug die je kan gebruiken bij het opstellen van je code.

Op het eerste zicht lijkt het gebruik van datum en tijd vrij vanzelfsprekend. Toch zijn er een aantal onverwachte valkuilen. In wat volgt zie je hoe je deze kan vermijden.

Constructors: Een DateTime instantie maken

Constructors van de DateTime class

Zoals je in de beschrijving van de DateTime class kan zien, zijn er verschillende overloaded constructors. Hieronder vind je enkele voorbeelden waarbij a.h.v. verschillende constructors een instantie van DateTime gemaakt wordt.

Voorbeeld 1: Een datum, zonder opgave van tijd

Gebruikte constructor: DateTime Constructor (Int32, Int32, Int32)

De volgorde van de argumenten van deze constructor is: jaar, maand, dag.

DateTime startDate = new DateTime(2020, 9, 1);
Console.WriteLine(startDate);

/* De uitvoer is afhankelijk van de landinstellingen van de computer.
Landinstelling met notatie Nederlands/België:
1/09/2020 0:00:00
Zoals je ziet wordt de korte datumnotatie gebruikt die bij de landinstelling hoort.
Merk eveneens op dat de tijd van de DateTime instantie op middernacht gezet wordt als
er in de constructor geen tijd meegegeven werd.
*/

Opmerking: door op het DateTime object de functie ToString() toe te passen kan het formaat waarin de datum en tijd op het scherm getoond worden beïnvloed worden.

Voorbeeld 2: Een datum, met opgave van tijd

Gebruikte constructor: DateTime Constructor (Int32, Int32, Int32, Int32, Int32, Int32)

De volgorde van de argumenten van deze constructor is: jaar, maand, dag, uur, minuut, seconde.

DateTime startDate = new DateTime(2020, 9, 1, 13, 50, 25);
Console.WriteLine(startDate.ToString());

/* De uitvoer is afhankelijk van de landinstellingen van de computer.
Landinstelling met notatie Nederlands/België:
1/09/2020 13:50:25
*/

Properties van DateTime

In de beschrijving van de DateTime class vind je een overzicht van de verschillende properties die tot de class behoren.

Voorbeeld: Opvragen op welke dag van de week een bepaalde datum valt a.h.v. de property DayOfWeek.

DateTime startDate = new DateTime(2020, 9, 1, 23, 50, 25);  
Console.WriteLine(startDate.ToString());
Console.WriteLine("This is a {0}", startDate.DayOfWeek);
/* De uitvoer is afhankelijk van de landinstellingen van de computer.
Landinstelling met notatie Nederlands/België:
1/09/2020 23:50:25
This is a Tuesday
*/

Time-zone informatie

Op wereldniveau zijn er verschillende tijdzones. Tegenwoordig is het noodzakelijk dat toepassingen hier rekening mee houden.

Zo kan een website vanuit verschillende tijdzones bekeken worden en natuurlijk wil de gebruiker de correcte tijd voor zijn tijdzone zien.

Daarnaast zijn er bijvoorbeeld internationale bedrijven met filialen die zich in verschillende tijdzones bevinden. Ook daar moeten toepassingen die gezamenlijk gebruikt worden rekening houden met het tijdsverschil, denk maar aan elektronische agenda’s om meetings te beleggen, enz.

Het is dus essentieel dat tijdsinformatie op een manier opgeslagen wordt, die niet enkel een correcte tijdsaanduiding toelaat, maar ook de gebruiker informatie in zijn tijdzone kan geven.

Om dit te bekomen is het aangeraden om programmatorisch met UTC te werken. UTC is een standaardtijd, gebaseerd op een atoomklok. Al de tijdzones in de wereld hebben een positieve of negatieve offset t.o.v. UTC. Door centraal met UTC te werken, wordt er een uniforme basis gebruikt. Tijden die door de gebruiker ingegeven worden, worden omgezet naar UTC. Tijden die in UTC opgeslagen zijn, kunnen achteraf dan weer omgerekend worden naar de tijdzone van de gebruiker en op die manier getoond worden. Op die manier ontstaat er een eenduidig (centraal UTC), maar ook flexibel (omrekening naar andere tijdzone voor de gebruikerinterface) systeem.

Omzetten van een DateTime object naar UTC

Voorbeeld: We maken een variabele dateNow die via de property Now geïnitialiseerd wordt op de huidige tijd van de computer (in de lokale tijdzone). Er zijn verschillende manieren om de variabele dateNow naar UTC te converteren:

  • Manier 1: toepassen van de method ToUniversalTime() uit de DateTime class op de variabele.
DateTime dateNow = DateTime.Now;
Console.WriteLine("The local date and time: {0}", dateNow);
Console.WriteLine("Converted to UTC: {0}", dateNow.ToUniversalTime());

/* Uitvoer:
The local date and time: 12/08/2018 16:55:56
Converted to UTC: 12/08/2018 14:55:56
*/
  • Manier 2: toepassen van de method ConvertTimeToUtc() uit de TimeZoneInfo class op de variabele.
DateTime dateNow = DateTime.Now;
Console.WriteLine("The local date and time: {0}", dateNow);
Console.WriteLine("Converted to UTC: {0}", TimeZoneInfo.ConvertTimeToUtc(dateNow));

/* Uitvoer:
The local date and time: 12/08/2018 16:55:56
Converted to UTC: 12/08/2018 14:55:56
*/

Op het eerste zicht zijn beide bovenstaande methodes gelijkwaardig. Toch is er een belangrijk verschil. Waar de method TimeZoneInfo.ConvertTimeToUtc() rekening houdt met onbestaande momenten, doen niet alle versies van DateTime.ToUniversalTime() dit. Dit kan problemen geven in gebieden waar Daylight Savings Time actief is.

In gebieden met Daylight Savings Time zal bijvoorbeeld de tijdspanne tussen 2 en 3 uur niet bestaan als er overgegaan wordt naar zomertijd.

Waar dateNow.ToUniversalTime() nog steeds de omzetting zal doen van deze onbestaande tijd, geeft TimeZoneInfo.ConvertTimeToUtc(dateNow) volgende exception: De opgegeven DateTime vertegenwoordigt een ongeldige tijd. Als de klok bijvoorbeeld voorwaarts wordt aangepast, is elke tijd in de overgeslagen periode ongeldig.

Met onderstaande functie kan je het verschil tussen beide methods uittesten en de exception genereren. Er wordt een instantie van DateTime gemaakt die niet bestaat, namelijk kwart na twee tijdens de overgang van zomer- naar winteruur.

De eerste functie houdt geen rekening met dit onbestaand moment in de tijd. De tweede functie geeft een melding (exception).

public static void NotCorrect()
{
    DateTime dt = new DateTime(2015, 3, 29, 2, 15, 0, DateTimeKind.Local);
    DateTime utc = dt.ToUniversalTime();
    Console.WriteLine(utc);
}

/* Uitvoer:
29/03/2015 1:15:00
*/

public static void ExceptionGenerated()
{
    DateTime dt = new DateTime(2015, 3, 29, 2, 15, 0, DateTimeKind.Local);
    DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt);  // throws exception!
    Console.WriteLine(utc);

}

/* Geen uitvoer, maar een exception: De opgegeven DateTime vertegenwoordigt een ongeldige tijd. Als de klok bijvoorbeeld voorwaarts wordt aangepast, is elke tijd in de overgeslagen periode ongeldig.
*/

Omzetten van UTC naar lokale tijd

In het onderstaande voorbeeld wordt een DateTime object gemaakt in UTC-tijd. D.m.v. de method ToLocalTime wordt dit object omgezet naar de lokale tijdzone van de gebruiker.

DateTime timeUtc = DateTime.UtcNow; // A DateTime object in UTC is created.
DateTime localTime = new DateTime();
localTime = timeUtc.ToLocalTime();
Console.WriteLine("The UTC-tijd: {0}", timeUtc);
Console.WriteLine("Converted to local time: {0}", localTime);

/* Uitvoer:
The UTC-tijd: 23/08/2018 8:11:54
Converted to local time: 23/08/2018 10:11:54
*/

De property Kind

Een handige property bij het omzetten van tijden naar verschillende tijdzones is Kind. Deze property kan local, unspecified of utc als waarde hebben.

De waarde die de property krijgt bij het maken van het object, is afhankelijk van de manier die gebruikt wordt om het object te maken. Onderstaand voorbeeld geeft hiervan een beeld:

DateTime date1 = new DateTime(2020, 9, 1, 23, 50, 25);
DateTime date2 = DateTime.Now;
DateTime date3 = DateTime.UtcNow;

Console.WriteLine("The timezone of date1: {0}", date1.Kind);
Console.WriteLine("The timezone of date2: {0}", date2.Kind);
Console.WriteLine("The timezone of date3: {0}", date3.Kind);

/* Uitvoer
The timezone of date1: Unspecified
The timezone of date2: Local
The timezone of date3: Utc
*/

Met de method SpecifyKind kan je property Kind instellen, zoals je in onderstaand voorbeeld ziet.

DateTime date1 = new DateTime(2020, 9, 1, 23, 50, 25);
Console.WriteLine("The timezone of date1: {0}", date1.Kind);

// Changing Kind from unspecified to Utc
date1 = DateTime.SpecifyKind(date1, DateTimeKind.Utc);
Console.WriteLine("The timezone of date1: {0}", date1.Kind);

/* Uitvoer
The timezone of date1: Unspecified
The timezone of date1: Utc
*/

Open het project oefening-datetime-1 en maak de oefeningenreeks


Previous section:
Navigatie