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. TimeOnlyje 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 do TimeOnly 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é zvolit DateTime.MinValue (0001-01-01), ale pokud jsou hodiny odečteny od DateTime hodnoty, může dojít k výjimce OutOfRange . 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é