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.
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.
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.
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
*/
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
*/
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.
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:
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
*/
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.
*/
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
*/
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