Volba mezi DateTime, DateOnly, DateTimeOffset, TimeSpan, TimeOnly a TimeZoneInfo
Aplikace .NET můžou informace o datu a čase používat několika způsoby. Mezi nejběžnější způsoby použití informací o datu a čase patří:
- Pokud chcete odrážet pouze datum, aby informace o čase nebyly důležité.
- Chcete-li odrážet pouze čas, aby informace o datu nebyly důležité.
- Aby se projevilo abstraktní datum a čas, které nejsou svázané s konkrétním časem a místem (například většina obchodů v mezinárodním řetězci otevřená v pracovní dny v 9:00).
- Pokud chcete načíst informace o datu a čase ze zdrojů mimo .NET, obvykle tam, kde jsou informace o datu a čase uložené v jednoduchém datovém typu.
- Jedinečně a jednoznačně identifikovat jeden bod v čase. Některé aplikace vyžadují, aby datum a čas byly jednoznačné pouze v hostitelském systému. Jiné aplikace vyžadují, aby byl jednoznačný v systémech (tj. datum serializované v jednom systému může být smysluplně deserializováno a používáno v jiném systému kdekoli na světě).
- Chcete-li zachovat více souvisejících časů (například místní čas žadatele a čas přijetí webového požadavku serveru).
- Chcete-li provést aritmetické aritmetické hodnoty data a času, pravděpodobně s výsledkem, který jednoznačně a jednoznačně identifikuje jeden bod v čase.
.NET obsahuje DateTime, , , DateTimeOffsetDateOnly, TimeSpanTimeOnly, a TimeZoneInfo typy, které lze použít k vytváření aplikací, které pracují s kalendářními daty a časy.
Poznámka:
Tento článek se nezabírá TimeZone , protože jeho funkce je téměř zcela začleněna do TimeZoneInfo třídy. Kdykoli je to možné, použijte TimeZoneInfo místo třídy třídu TimeZone .
DateTimeOffset – struktura
Struktura DateTimeOffset představuje hodnotu data a času společně s posunem, který označuje, kolik se tato hodnota liší od času UTC. Proto hodnota vždy jednoznačně identifikuje jeden bod v čase.
Tento DateTimeOffset typ zahrnuje všechny funkce DateTime typu spolu s povědomím o časovém pásmu. To je vhodné pro aplikace, které:
- Jedinečně a jednoznačně identifikujte jeden bod v čase. Typ DateTimeOffset lze použít k jednoznačnému definování významu "now", k protokolování časů transakcí, k protokolování časů událostí systému nebo aplikace a k zaznamenání času vytváření a úpravy souborů.
- Proveďte aritmetické aritmetické operace obecného data a času.
- Zachovávejte více souvisejících časů, pokud jsou tyto časy uloženy jako dvě samostatné hodnoty nebo jako dva členy struktury.
Poznámka:
Tato použití pro DateTimeOffset hodnoty jsou mnohem častější než u DateTime hodnot. V důsledku toho zvažte DateTimeOffset jako výchozí typ data a času pro vývoj aplikací.
Hodnota DateTimeOffset není svázaná s určitým časovým pásmem, ale může pocházet z různých časových pásem. Následující příklad uvádí časová pásma, do kterých může patřit určitý počet DateTimeOffset hodnot (včetně místního tichomoří standardního času).
using System;
using System.Collections.ObjectModel;
public class TimeOffsets
{
public static void Main()
{
DateTime thisDate = new DateTime(2007, 3, 10, 0, 0, 0);
DateTime dstDate = new DateTime(2007, 6, 10, 0, 0, 0);
DateTimeOffset thisTime;
thisTime = new DateTimeOffset(dstDate, new TimeSpan(-7, 0, 0));
ShowPossibleTimeZones(thisTime);
thisTime = new DateTimeOffset(thisDate, new TimeSpan(-6, 0, 0));
ShowPossibleTimeZones(thisTime);
thisTime = new DateTimeOffset(thisDate, new TimeSpan(+1, 0, 0));
ShowPossibleTimeZones(thisTime);
}
private static void ShowPossibleTimeZones(DateTimeOffset offsetTime)
{
TimeSpan offset = offsetTime.Offset;
ReadOnlyCollection<TimeZoneInfo> timeZones;
Console.WriteLine("{0} could belong to the following time zones:",
offsetTime.ToString());
// Get all time zones defined on local system
timeZones = TimeZoneInfo.GetSystemTimeZones();
// Iterate time zones
foreach (TimeZoneInfo timeZone in timeZones)
{
// Compare offset with offset for that date in that time zone
if (timeZone.GetUtcOffset(offsetTime.DateTime).Equals(offset))
Console.WriteLine(" {0}", timeZone.DisplayName);
}
Console.WriteLine();
}
}
// This example displays the following output to the console:
// 6/10/2007 12:00:00 AM -07:00 could belong to the following time zones:
// (GMT-07:00) Arizona
// (GMT-08:00) Pacific Time (US & Canada)
// (GMT-08:00) Tijuana, Baja California
//
// 3/10/2007 12:00:00 AM -06:00 could belong to the following time zones:
// (GMT-06:00) Central America
// (GMT-06:00) Central Time (US & Canada)
// (GMT-06:00) Guadalajara, Mexico City, Monterrey - New
// (GMT-06:00) Guadalajara, Mexico City, Monterrey - Old
// (GMT-06:00) Saskatchewan
//
// 3/10/2007 12:00:00 AM +01:00 could belong to the following time zones:
// (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
// (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
// (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
// (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
// (GMT+01:00) West Central Africa
Imports System.Collections.ObjectModel
Module TimeOffsets
Public Sub Main()
Dim thisTime As DateTimeOffset
thisTime = New DateTimeOffset(#06/10/2007#, New TimeSpan(-7, 0, 0))
ShowPossibleTimeZones(thisTime)
thisTime = New DateTimeOffset(#03/10/2007#, New TimeSpan(-6, 0, 0))
ShowPossibleTimeZones(thisTime)
thisTime = New DateTimeOffset(#03/10/2007#, New TimeSpan(+1, 0, 0))
ShowPossibleTimeZones(thisTime)
End Sub
Private Sub ShowPossibleTimeZones(offsetTime As DateTimeOffset)
Dim offset As TimeSpan = offsetTime.Offset
Dim timeZones As ReadOnlyCollection(Of TimeZoneInfo)
Console.WriteLine("{0} could belong to the following time zones:", _
offsetTime.ToString())
' Get all time zones defined on local system
timeZones = TimeZoneInfo.GetSystemTimeZones()
' Iterate time zones
For Each timeZone As TimeZoneInfo In timeZones
' Compare offset with offset for that date in that time zone
If timeZone.GetUtcOffset(offsetTime.DateTime).Equals(offset) Then
Console.WriteLine(" {0}", timeZone.DisplayName)
End If
Next
Console.WriteLine()
End Sub
End Module
' This example displays the following output to the console:
' 6/10/2007 12:00:00 AM -07:00 could belong to the following time zones:
' (GMT-07:00) Arizona
' (GMT-08:00) Pacific Time (US & Canada)
' (GMT-08:00) Tijuana, Baja California
'
' 3/10/2007 12:00:00 AM -06:00 could belong to the following time zones:
' (GMT-06:00) Central America
' (GMT-06:00) Central Time (US & Canada)
' (GMT-06:00) Guadalajara, Mexico City, Monterrey - New
' (GMT-06:00) Guadalajara, Mexico City, Monterrey - Old
' (GMT-06:00) Saskatchewan
'
' 3/10/2007 12:00:00 AM +01:00 could belong to the following time zones:
' (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
' (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
' (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
' (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
' (GMT+01:00) West Central Africa
Výstup ukazuje, že každá hodnota data a času v tomto příkladu může patřit alespoň do tří různých časových pásem. Hodnota DateTimeOffset 10. 6. 2007 ukazuje, že pokud hodnota data a času představuje letní čas, jeho posun od UTC nemusí ani nutně odpovídat základnímu posunu UTC původu nebo posunu od utc nalezeného v jeho zobrazovaném názvu. Vzhledem k tomu, že jedna DateTimeOffset hodnota není úzce spojená s časovým pásmem, nemůže odrážet přechod časového pásma do a z letního času. To může být problematické, když se k manipulaci s DateTimeOffset hodnotou používá aritmetika data a času. Diskuzi o tom, jak provádět aritmetické aritmetické operace s kalendářními daty a časem způsobem, který bere v úvahu pravidla úpravy časového pásma, najdete v tématu Provádění aritmetických operací s daty a časy.
Struktura DateTime
Hodnota DateTime definuje konkrétní datum a čas. Kind Obsahuje vlastnost, která poskytuje omezené informace o časovém pásmu, do kterého patří dané datum a čas. Hodnota DateTimeKind vrácená Kind vlastností určuje, zda DateTime hodnota představuje místní čas (DateTimeKind.Local), koordinovaný univerzální čas (UTC) (DateTimeKind.Utc) nebo nezadanou dobu (DateTimeKind.Unspecified).
Struktura DateTime je vhodná pro aplikace s jednou nebo více z následujících charakteristik:
- Práce s abstraktními daty a časy
- Práce s daty a časy, u kterých chybí informace o časovém pásmu
- Pracovat pouze s daty a časy UTC.
- Provádění aritmetických aritmetických dat a času, ale zabývá se obecnými výsledky. Například v operaci sčítání, která přidává šest měsíců k určitému datu a času, není často důležité, zda je výsledek upraven pro letní čas.
Pokud konkrétní DateTime hodnota nepředstavuje UTC, je tato hodnota data a času často nejednoznačná nebo omezená ve své přenositelnosti. Pokud DateTime například hodnota představuje místní čas, je přenosná v rámci tohoto místního časového pásma (to znamená, že pokud je hodnota deserializována v jiném systému ve stejném časovém pásmu, tato hodnota stále jednoznačně identifikuje jeden bod v čase). Mimo místní časové pásmo může mít tato DateTime hodnota více interpretací. Pokud je DateTimeKind.Unspecifiedvlastnost hodnoty Kind ještě méně přenosná: nyní je nejednoznačný ve stejném časovém pásmu a možná i ve stejném systému, kde byla poprvé serializována. Pouze pokud DateTime hodnota představuje UTC, tato hodnota jednoznačně identifikuje jeden bod v čase bez ohledu na systém nebo časové pásmo, ve kterém se hodnota používá.
Důležité
Při ukládání nebo sdílení DateTime dat použijte UTC a nastavte DateTime vlastnost hodnoty Kind na DateTimeKind.Utc.
DateOnly – struktura
Struktura DateOnly představuje konkrétní datum bez času. Vzhledem k tomu, že nemá žádnou časovou komponentu, představuje datum od začátku dne do konce dne. Tato struktura je ideální pro ukládání konkrétních kalendářních dat, jako jsou datum narození, datum výročí, svátek nebo datum související s podnikáním.
I když byste mohli použít DateTime
při ignorování časové komponenty, existuje několik výhod, které můžete použítDateOnly
:DateTime
- Pokud
DateTime
je struktura posunutá časovým pásmem, může se vrátit do předchozího nebo následujícího dne.DateOnly
nemůže být posunut časovým pásmem a vždy představuje datum, které bylo nastaveno. - Serializace
DateTime
struktury zahrnuje časovou komponentu, která může zakrýt záměr dat.DateOnly
Serializuje také méně dat. - Když kód komunikuje s databází, jako je SQL Server, jsou všechna kalendářní data obecně uložena jako
date
datový typ, který nezahrnuje čas.DateOnly
odpovídá lepšímu typu databáze.
Další informace o DateOnly
, viz Jak používat DateOnly a TimeOnly struktury.
Důležité
DateOnly
není k dispozici v rozhraní .NET Framework.
Struktura TimeSpan
Struktura TimeSpan představuje časový interval. Mezi její dvě typické použití patří:
- Reflexe časový interval mezi dvěma hodnotami data a času. Například odečtení jedné DateTime hodnoty od druhé vrátí TimeSpan hodnotu.
- Měření uplynulé doby. Například vlastnost vrátí TimeSpan hodnotu, Stopwatch.Elapsed která odráží časový interval, který uplynul od volání jedné z Stopwatch metod, které začínají měřit uplynulý čas.
Hodnotu TimeSpan lze také použít jako náhradu DateTime za hodnotu, pokud tato hodnota odráží čas bez odkazu na konkrétní den. Toto použití se podobá vlastnostem DateTime.TimeOfDay a DateTimeOffset.TimeOfDay vrací TimeSpan hodnotu, která představuje čas bez odkazu na datum. Strukturu lze například TimeSpan použít k vyjádření denního otevření nebo uzavření obchodu, případně lze použít k vyjádření času, kdy dojde k jakékoli běžné události.
Následující příklad definuje StoreInfo
strukturu, která obsahuje TimeSpan objekty pro otevření a uzavření úložiště, stejně jako TimeZoneInfo objekt, který představuje časové pásmo úložiště. Struktura obsahuje také dvě metody a IsOpenAt
, který označuje, IsOpenNow
zda je úložiště otevřeno v době určené uživatelem, který se předpokládá, že je v místním časovém pásmu.
using System;
public struct StoreInfo
{
public String store;
public TimeZoneInfo tz;
public TimeSpan open;
public TimeSpan close;
public bool IsOpenNow()
{
return IsOpenAt(DateTime.Now.TimeOfDay);
}
public bool IsOpenAt(TimeSpan time)
{
TimeZoneInfo local = TimeZoneInfo.Local;
TimeSpan offset = TimeZoneInfo.Local.BaseUtcOffset;
// Is the store in the same time zone?
if (tz.Equals(local)) {
return time >= open & time <= close;
}
else {
TimeSpan delta = TimeSpan.Zero;
TimeSpan storeDelta = TimeSpan.Zero;
// Is it daylight saving time in either time zone?
if (local.IsDaylightSavingTime(DateTime.Now.Date + time))
delta = local.GetAdjustmentRules()[local.GetAdjustmentRules().Length - 1].DaylightDelta;
if (tz.IsDaylightSavingTime(TimeZoneInfo.ConvertTime(DateTime.Now.Date + time, local, tz)))
storeDelta = tz.GetAdjustmentRules()[tz.GetAdjustmentRules().Length - 1].DaylightDelta;
TimeSpan comparisonTime = time + (offset - tz.BaseUtcOffset).Negate() + (delta - storeDelta).Negate();
return comparisonTime >= open & comparisonTime <= close;
}
}
}
Public Structure StoreInfo
Dim store As String
Dim tz As TimeZoneInfo
Dim open As TimeSpan
Dim close As TimeSpan
Public Function IsOpenNow() As Boolean
Return IsOpenAt(Date.Now.TimeOfDay)
End Function
Public Function IsOpenAt(time As TimeSpan) As Boolean
Dim local As TimeZoneInfo = TimeZoneInfo.Local
Dim offset As TimeSpan = TimeZoneInfo.Local.BaseUtcOffset
' Is the store in the same time zone?
If tz.Equals(local) Then
Return time >= open AndAlso time <= close
Else
Dim delta As TimeSpan = TimeSpan.Zero
Dim storeDelta As TimeSpan = TimeSpan.Zero
' Is it daylight saving time in either time zone?
If local.IsDaylightSavingTime(Date.Now.Date + time) Then
delta = local.GetAdjustmentRules(local.GetAdjustmentRules().Length - 1).DaylightDelta
End If
If tz.IsDaylightSavingTime(TimeZoneInfo.ConvertTime(Date.Now.Date + time, local, tz))
storeDelta = tz.GetAdjustmentRules(tz.GetAdjustmentRules().Length - 1).DaylightDelta
End If
Dim comparisonTime As TimeSpan = time + (offset - tz.BaseUtcOffset).Negate() + (delta - storeDelta).Negate
Return (comparisonTime >= open AndAlso comparisonTime <= close)
End If
End Function
End Structure
Strukturu StoreInfo
pak může použít klientský kód, jako je následující.
public class Example
{
public static void Main()
{
// Instantiate a StoreInfo object.
var store103 = new StoreInfo();
store103.store = "Store #103";
store103.tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
// Store opens at 8:00.
store103.open = new TimeSpan(8, 0, 0);
// Store closes at 9:30.
store103.close = new TimeSpan(21, 30, 0);
Console.WriteLine("Store is open now at {0}: {1}",
DateTime.Now.TimeOfDay, store103.IsOpenNow());
TimeSpan[] times = { new TimeSpan(8, 0, 0), new TimeSpan(21, 0, 0),
new TimeSpan(4, 59, 0), new TimeSpan(18, 31, 0) };
foreach (var time in times)
Console.WriteLine("Store is open at {0}: {1}",
time, store103.IsOpenAt(time));
}
}
// The example displays the following output:
// Store is open now at 15:29:01.6129911: True
// Store is open at 08:00:00: True
// Store is open at 21:00:00: False
// Store is open at 04:59:00: False
// Store is open at 18:31:00: False
Module Example
Public Sub Main()
' Instantiate a StoreInfo object.
Dim store103 As New StoreInfo()
store103.store = "Store #103"
store103.tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
' Store opens at 8:00.
store103.open = new TimeSpan(8, 0, 0)
' Store closes at 9:30.
store103.close = new TimeSpan(21, 30, 0)
Console.WriteLine("Store is open now at {0}: {1}",
Date.Now.TimeOfDay, store103.IsOpenNow())
Dim times() As TimeSpan = {New TimeSpan(8, 0, 0),
New TimeSpan(21, 0, 0),
New TimeSpan(4, 59, 0),
New TimeSpan(18, 31, 0)}
For Each time In times
Console.WriteLine("Store is open at {0}: {1}",
time, store103.IsOpenAt(time))
Next
End Sub
End Module
' The example displays the following output:
' Store is open now at 15:29:01.6129911: True
' Store is open at 08:00:00: True
' Store is open at 21:00:00: False
' Store is open at 04:59:00: False
' Store is open at 18:31:00: False
TimeOnly – struktura
Struktura TimeOnly představuje denní hodnotu, například denní budík nebo čas, kdy každý den sníte oběd. TimeOnly
je omezena na rozsah 00:00:00.000000 - 23:59:59.999999999, určitý čas dne.
Před uvedením TimeOnly
typu programátoři obvykle použili DateTime typ nebo TimeSpan typ k vyjádření určitého času. Použití těchto struktur k simulaci času bez data však může představovat některé problémy, které TimeOnly
řeší:
TimeSpan
představuje uplynulý čas, například čas měřený pomocí stopek. Horní oblast je více než 29 000 let a její hodnota může být záporná, aby bylo možné označit posun v čase zpět. ZápornáTimeSpan
hodnota neuvádí konkrétní čas dne.- Pokud
TimeSpan
se používá jako denní čas, existuje riziko, že může být manipulováno s hodnotou mimo 24hodinový den.TimeOnly
tohle riziko nemá. Pokud například pracovní směna zaměstnance začíná v 18:00 a trvá 8 hodin, přidání 8 hodin doTimeOnly
struktury se převrací na 2:00. - Použití
DateTime
pro čas dne vyžaduje, aby bylo k času přidruženo libovolné datum a později ignorováno. Jako datum je běžné zvolitDateTime.MinValue
(0001-01-01), ale pokud jsou hodiny odečteny odDateTime
hodnoty, může dojít k výjimceOutOfRange
.TimeOnly
nemá tento problém, protože se čas posunuje dopředu a dozadu kolem 24hodinového časového rámce. - Serializace
DateTime
struktury zahrnuje komponentu data, která může překrývat záměr dat.TimeOnly
Serializuje také méně dat.
Další informace o TimeOnly
, viz Jak používat DateOnly a TimeOnly struktury.
Důležité
TimeOnly
není k dispozici v rozhraní .NET Framework.
TimeZoneInfo – třída
Třída TimeZoneInfo představuje libovolné časové pásmo Země a umožňuje převod libovolného data a času v jednom časovém pásmu na ekvivalent v jiném časovém pásmu. Třída TimeZoneInfo umožňuje pracovat s kalendářními daty a časy, aby jakákoli hodnota data a času jednoznačně identifikovala jeden bod v čase. Třída TimeZoneInfo je také rozšiřitelná. I když závisí na informacích o časovém pásmu poskytovaných pro systémy Windows a definovaných v registru, podporuje vytváření vlastních časových pásem. Podporuje také serializaci a deserializaci informací o časovém pásmu.
V některých případech může plné využití TimeZoneInfo této třídy vyžadovat další vývojovou práci. Pokud hodnoty data a času nejsou úzce svázané s časovými pásmy, do kterých patří, vyžaduje se další práce. Pokud vaše aplikace neposkytuje nějaký mechanismus pro propojení data a času s přidruženým časovým pásmem, je snadné zrušit přidružení konkrétní hodnoty data a času od časového pásma. Jednou z metod propojení těchto informací je definovat třídu nebo strukturu, která obsahuje hodnotu data i času a přidružený objekt časového pásma.
Chcete-li využít podporu časového pásma v rozhraní .NET, musíte znát časové pásmo, do kterého patří hodnota data a času při vytvoření instance tohoto objektu data a času. Časové pásmo není často známo, zejména ve webových nebo síťových aplikacích.
Viz také
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro