Sdílet prostřednictvím


Postupy: Použití časových pásem v aritmetických operacích s daty a časy

Obvykle když provádíte aritmetické operace s datem a časem pomocí hodnot DateTime nebo DateTimeOffset, výsledek nezohledňuje žádná pravidla úpravy časových pásem. To platí i v případě, že časové pásmo hodnoty data a času je jasně identifikovatelné (například když vlastnost Kind je nastavena na hodnotu Local). Toto téma ukazuje, jak provádět aritmetické operace s hodnotami data a času, které patří do určitého časového pásma. Výsledky aritmetických operací budou reflektovat pravidla pro úpravu časového pásma.

Chcete-li aplikovat pravidla úprav pro aritmetické operace s daty a časem

  1. Implementujte některou metodu těsného spojení hodnoty data a času s příslušným časovým pásmem. Například deklarujte strukturu, která obsahuje hodnotu data a času a příslušnou hodnotu časového pásma. Následující příklad používá tento přístup k propojení hodnoty DateTime s příslušným časovým pásmem.

    ' Define a structure for DateTime values for internal use only
    Friend Structure TimeWithTimeZone
       Dim TimeZone As TimeZoneInfo
       Dim Time As Date
    End Structure
    
    // Define a structure for DateTime values for internal use only
    internal struct TimeWithTimeZone
    {
       TimeZoneInfo TimeZone;
       DateTime Time;
    }
    
  2. Převeďte čas na koordinovaný světový čas (standard UTC) voláním metody ConvertTimeToUtc nebo ConvertTime.

  3. Provádění aritmetických operací na čase UTC.

  4. Převeďte čas z času UTC na původní čas spojený s časovým pásmem voláním metody TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo).

Příklad

Následující příklad přidá dvě hodiny a 30 minut k hodnotě 9. března 2008 v 1:30 A.M. centrálního standardního času. K přechodu časového pásma na letní čas dojde o třicet minut později, ve 2:00 A.M. 9. března 2008. Protože příklad postupuje podle čtyř kroků uvedených v předchozím oddílu, správně hlásí výsledný čas jako 5:00 A.M. 9. března 2008.

Public Structure TimeZoneTime
   Public TimeZone As TimeZoneInfo
   Public Time As Date

   Public Sub New(tz As TimeZoneInfo, time As Date)
      If tz Is Nothing Then _
         Throw New ArgumentNullException("The time zone cannot be a null reference.")

      Me.TimeZone = tz
      Me.Time = time
   End Sub

   Public Function AddTime(interval As TimeSpan) As TimeZoneTime
      ' Convert time to UTC
      Dim utcTime As DateTime = TimeZoneInfo.ConvertTimeToUtc(Me.Time, _
                                                              Me.TimeZone)      
      ' Add time interval to time
      utcTime = utcTime.Add(interval)
      ' Convert time back to time in time zone
      Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, _
                              TimeZoneInfo.Utc, Me.TimeZone))
   End Function
End Structure

Module TimeArithmetic
   Public Const tzName As String = "Central Standard Time"

   Public Sub Main()
      Try
         Dim cstTime1, cstTime2 As TimeZoneTime

         Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
         Dim time1 As Date = #03/09/2008 1:30AM#
         Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

         cstTime1 = New TimeZoneTime(cst, time1)
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                    twoAndAHalfHours.ToString(), _ 
                                                    cstTime2.Time)  
      Catch
         Console.WriteLine("Unable to find {0}.", tzName)
      End Try   
   End Sub   
End Module
using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTime Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTime time)
   {
      if (tz == null) 
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;   
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(this.Time, this.TimeZone);
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime, 
                              TimeZoneInfo.Utc, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

         TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
         DateTime time1 = new DateTime(2008, 3, 9, 1, 30, 0);          
         TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

         cstTime1 = new TimeZoneTime(cst, time1);
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, 
                                                    twoAndAHalfHours.ToString(),  
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}

Obě hodnoty DateTime a DateTimeOffset nejsou přidružené k žádnému časovému pásmu, ke kterému by mohly patřit. K provádění aritmetických operací s datem a časem tak, aby se automaticky použila pravidla úprav časového pásma, časové pásmo, ke kterému hodnota data a času patří, musí být okamžitě identifikovatelné. To znamená, že datum a čas a jeho přidružené časové pásmo musí být pevně spojené. Existuje několik způsobů jak toto lze provést. Například následující:

  • Předpokládejme, že všechny časy použité v aplikaci vždy patří k určitému časovému pásmu. Ačkoli je toto v některých případech vhodné, tento přístup nabízí omezenou flexibilitu a případně i omezenou přenositelnost.

  • Definujte typ, který pevně spojuje datum a čas s jeho přidruženým časovým pásmem zahrnutím obojího jako pole typu. Tento přístup je použitý v příkladu kódu, který definuje strukturu pro uložení data a času a časového pásma ve dvou členských polích.

Příklad ukazuje, jak provádět aritmetické operace s hodnotami DateTime tak, aby byla na výsledek použita pravidla úpravy časového pásma. Avšak hodnoty DateTimeOffset lze použít stejně snadno. Následující příklad ukazuje, jak může být přizpůsoben kód v původním příkladu pro použití hodnoty DateTimeOffset místo hodnoty DateTime.

Public Structure TimeZoneTime
   Public TimeZone As TimeZoneInfo
   Public Time As DateTimeOffset

   Public Sub New(tz As TimeZoneInfo, time As DateTimeOffset)
      If tz Is Nothing Then _
         Throw New ArgumentNullException("The time zone cannot be a null reference.")

      Me.TimeZone = tz
      Me.Time = time
   End Sub

   Public Function AddTime(interval As TimeSpan) As TimeZoneTime
      ' Convert time to UTC
      Dim utcTime As DateTimeOffset = TimeZoneInfo.ConvertTime(Me.Time, TimeZoneInfo.Utc)      
      ' Add time interval to time
      utcTime = utcTime.Add(interval)
      ' Convert time back to time in time zone
      Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, Me.TimeZone))
   End Function
End Structure

Module TimeArithmetic
   Public Const tzName As String = "Central Standard Time"

   Public Sub Main()
      Try
         Dim cstTime1, cstTime2 As TimeZoneTime

         Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
         Dim time1 As Date = #03/09/2008 1:30AM#
         Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

         cstTime1 = New TimeZoneTime(cst, _
                        New DateTimeOffset(time1, cst.GetUtcOffset(time1)))
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                    twoAndAHalfHours.ToString(), _ 
                                                    cstTime2.Time)  
      Catch
         Console.WriteLine("Unable to find {0}.", tzName)
      End Try   
   End Sub   
End Module
using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTimeOffset Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTimeOffset time)
   {
      if (tz == null) 
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;   
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTimeOffset utcTime = TimeZoneInfo.ConvertTime(this.Time, TimeZoneInfo.Utc);      
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

         TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
         DateTime time1 = new DateTime(2008, 3, 9, 1, 30, 0);          
         TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

         cstTime1 = new TimeZoneTime(cst, 
                        new DateTimeOffset(time1, cst.GetUtcOffset(time1)));
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, 
                                                    twoAndAHalfHours.ToString(),  
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}

Všimněte si, pokud je toto přidání jednoduše provedeno pro hodnoty DateTimeOffset bez počátečního převodu na čas UTC, pak výsledek odráží konkrétní bod v čase, ale jeho posun toto nereflektuje od požadovaného časového pásma.

Probíhá kompilace kódu

Tento příklad vyžaduje:

  • Že bude do projektu přidán odkaz na System.Core.dll.

  • Že obor názvů System bude importován příkazem using (povinné v kódu jazyka C#).

Viz také

Koncepty

Provádění aritmetických operací s daty a časy

Další zdroje

Data, časy a časových pásem