使用日期和時間執行算術運算Performing arithmetic operations with dates and times

DateTime 雖然DateTimeOffset和結構都會提供對其值執行算數運算的成員, 但算數運算的結果會非常不同。Although both the DateTime and the DateTimeOffset structures provide members that perform arithmetic operations on their values, the results of arithmetic operations are very different. 本主題將探討這些差異、將它們與日期和時間資料中的時區感知程度產生關聯, 並討論如何使用日期和時間資料執行全時區感知作業。This topic examines those differences, relates them to degrees of time zone awareness in date and time data, and discusses how to perform fully time zone aware operations using date and time data.

使用 DateTime 值的比較和算數運算Comparisons and arithmetic operations with DateTime values

屬性可讓您DateTimeKind將值指派給日期和時間, 以指出它是否代表當地時間、國際標準時間 (UTC) 或未指定時區DateTime.Kind的時間。The DateTime.Kind property allows a DateTimeKind value to be assigned to the date and time to indicate whether it represents local time, Coordinated Universal Time (UTC), or the time in an unspecified time zone. 不過, 比較或在值上DateTimeKind執行日期和時間運算時, 會忽略這個有限的時區資訊。However, this limited time zone information is ignored when comparing or performing date and time arithmetic on DateTimeKind values. 下列範例會比較目前當地時間與目前 UTC 時間,以說明這點。The following example, which compares the current local time with the current UTC time, illustrates this.

using System;

public enum TimeComparison
{
   EarlierThan = -1,
   TheSameAs = 0,
   LaterThan = 1
}

public class DateManipulation
{
   public static void Main()
   {
      DateTime localTime = DateTime.Now;
      DateTime utcTime = DateTime.UtcNow;
      
      Console.WriteLine("Difference between {0} and {1} time: {2}:{3} hours", 
                        localTime.Kind.ToString(), 
                        utcTime.Kind.ToString(), 
                        (localTime - utcTime).Hours, 
                        (localTime - utcTime).Minutes);
      Console.WriteLine("The {0} time is {1} the {2} time.", 
                        localTime.Kind.ToString(), 
                        Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime)), 
                        utcTime.Kind.ToString());  
   }
}
// If run in the U.S. Pacific Standard Time zone, the example displays 
// the following output to the console:
//    Difference between Local and Utc time: -7:0 hours
//    The Local time is EarlierThan the Utc time.                                                    
Public Enum TimeComparison As Integer
   EarlierThan = -1
   TheSameAs = 0
   LaterThan = 1
End Enum

Module DateManipulation
   Public Sub Main()
      Dim localTime As Date = Date.Now
      Dim utcTime As Date = Date.UtcNow
      
      Console.WriteLine("Difference between {0} and {1} time: {2}:{3} hours", _
                        localTime.Kind.ToString(), _
                        utcTime.Kind.ToString(), _
                        (localTime - utcTime).Hours, _
                        (localTime - utcTime).Minutes)
      Console.WriteLine("The {0} time is {1} the {2} time.", _
                        localTime.Kind.ToString(), _ 
                        [Enum].GetName(GetType(TimeComparison), localTime.CompareTo(utcTime)), _
                        utcTime.Kind.ToString())  
      ' If run in the U.S. Pacific Standard Time zone, the example displays 
      ' the following output to the console:
      '    Difference between Local and Utc time: -7:0 hours
      '    The Local time is EarlierThan the Utc time.                                                    
   End Sub
End Module

CompareTo(DateTime)方法會報告當地時間早于 (或小於) utc 時間, 而減法運算會指出 utc 與當地時間之間的差異, 這是美國的系統太平洋標準時間時區系統來說相差七個小時。The CompareTo(DateTime) method reports that the local time is earlier than (or less than) the UTC time, and the subtraction operation indicates that the difference between UTC and the local time for a system in the U.S. Pacific Standard Time zone is seven hours. 但因為這兩個值提供單一時間點的不同表示,所以在此情況下,此時間間隔很明顯地完全歸因於當地時區與 UTC 的位移。But because these two values provide different representations of a single point in time, it is clear in this case that this time interval is completely attributable to the local time zone's offset from UTC.

更常見的是DateTime.Kind , 屬性不會影響Kind比較和算術方法所傳回的結果 (如果兩個相同時間點的比較指出), 雖然它可能會影響這些結果的轉譯。More generally, the DateTime.Kind property does not affect the results returned by Kind comparison and arithmetic methods (as the comparison of two identical points in time indicates), although it can affect the interpretation of those results. 例如:For example:

  • 在兩個日期和時間值上執行的任何算數運算結果DateTime.Kind , 其屬性DateTimeKind都相等反映兩個值之間的實際時間間隔。The result of any arithmetic operation performed on two date and time values whose DateTime.Kind properties both equal DateTimeKind reflects the actual time interval between the two values. 同樣地,兩個這類日期和時間值的比較會精確地反映時間的關聯性。Similarly, the comparison of two such date and time values accurately reflects the relationship between times.

  • 在兩個日期和時間值上執行的任何算術或比較運算結果DateTime.Kind , 其屬性DateTimeKind等於或在具有不同DateTime.Kind屬性值的兩個日期和時間值上, 會反映時鐘時間的差異這兩個值之間。The result of any arithmetic or comparison operation performed on two date and time values whose DateTime.Kind properties both equal DateTimeKind or on two date and time values with different DateTime.Kind property values reflects the difference in clock time between the two values.

  • 當地日期和時間值的算術或比較作業不會考慮特定值是不明確或無效,也不會考慮當地時區與日光節約時間之轉換所產生的任何調整規則的影響。Arithmetic or comparison operations on local date and time values do not consider whether a particular value is ambiguous or invalid, nor do they take account of the effect of any adjustment rules that result from the local time zone's transition to or from daylight saving time.

  • 任何比較或計算 UTC 與當地時間之差異的作業,都會在結果中包含等於當地時區與 UTC 之位移的時間間隔。Any operation that compares or calculates the difference between UTC and a local time includes a time interval equal to the local time zone's offset from UTC in the result.

  • 任何比較或計算未指定時間與 UTC 或當地時間之差異的作業,都會反映簡單時鐘時間。Any operation that compares or calculates the difference between an unspecified time and either UTC or the local time reflects simple clock time. 不考慮時區差異,而且結果不會反映如何套用時區調整規則。Time zone differences are not considered, and the result does not reflect the application of time zone adjustment rules.

  • 任何比較或計算兩個未指定時間之差異的作業都可能包含未知間隔,而未知間隔反映兩個不同時區的時間差異。Any operation that compares or calculates the difference between two unspecified times may include an unknown interval that reflects the difference between the time in two different time zones.

在許多情況下, 時區差異不會影響日期和時間計算 (如需其中一些的討論, 請參閱在DateTime、DateTimeOffset、TimeSpan 和 TimeZoneInfo 之間進行選擇) 或日期和時間資料的內容定義比較或算數運算的意義。There are many scenarios in which time zone differences do not affect date and time calculations (for a discussion of some of these, see Choosing between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo) or in which the context of the date and time data defines the meaning of comparison or arithmetic operations.

使用 DateTimeOffset 值的比較和算數運算Comparisons and arithmetic operations with DateTimeOffset values

DateTimeOffset值不僅包含日期和時間, 也包括明確定義相對於 UTC 之日期和時間的位移。A DateTimeOffset value includes not only a date and time, but also an offset that unambiguously defines that date and time relative to UTC. 這可讓您定義與值稍有不同的DateTimeOffset相等性。This makes it possible to define equality somewhat differently than for DateTimeOffset values. 如果DateTime值具有相同的日期和時間值, 則它們會相等DateTimeOffset , 而如果兩者都參考相同的時間點, 則值會相等。Whereas DateTime values are equal if they have the same date and time value, DateTimeOffset values are equal if they both refer to the same point in time. 這可讓DateTimeOffset您在比較中使用, 以及在判斷兩個日期和時間之間間隔的大部分算數運算中, 以更精確且更不需要解讀。This makes a DateTimeOffset value more accurate and less in need of interpretation when used in comparisons and in most arithmetic operations that determine the interval between two dates and times. 下列範例 ( DateTimeOffset等同于先前的範例, 也就是比較本機和 UTC DateTimeOffset值) 會說明行為的差異。The following example, which is the DateTimeOffset equivalent to the previous example that compared local and UTC DateTimeOffset values, illustrates this difference in behavior.

using System;

public enum TimeComparison
{
   EarlierThan = -1,
   TheSameAs = 0,
   LaterThan = 1
}

public class DateTimeOffsetManipulation
{
   public static void Main()
   {
      DateTimeOffset localTime = DateTimeOffset.Now;
      DateTimeOffset utcTime = DateTimeOffset.UtcNow;
      
      Console.WriteLine("Difference between local time and UTC: {0}:{1:D2} hours", 
                        (localTime - utcTime).Hours, 
                        (localTime - utcTime).Minutes);
      Console.WriteLine("The local time is {0} UTC.", 
                        Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime)));  
   }
}
// Regardless of the local time zone, the example displays 
// the following output to the console:
//    Difference between local time and UTC: 0:00 hours.
//    The local time is TheSameAs UTC.
Public Enum TimeComparison As Integer
   EarlierThan = -1
   TheSameAs = 0
   LaterThan = 1
End Enum

Module DateTimeOffsetManipulation
   Public Sub Main()
      Dim localTime As DateTimeOffset = DateTimeOffset.Now
      Dim utcTime As DateTimeOffset = DateTimeOffset.UtcNow
      
      Console.WriteLine("Difference between local time and UTC: {0}:{1:D2} hours.", _
                        (localTime - utcTime).Hours, _
                        (localTime - utcTime).Minutes)
      Console.WriteLine("The local time is {0} UTC.", _
                        [Enum].GetName(GetType(TimeComparison), localTime.CompareTo(utcTime)))  
   End Sub
End Module
' Regardless of the local time zone, the example displays 
' the following output to the console:
'    Difference between local time and UTC: 0:00 hours.
'    The local time is TheSameAs UTC.
'          Console.WriteLine(e.GetType().Name)

在此範例中, CompareTo方法會指出目前的當地時間和目前的 UTC 時間相等, 而CompareTo(DateTimeOffset)值的減法表示兩個時間之間的差異是TimeSpan.ZeroIn this example, the CompareTo method indicates that the current local time and the current UTC time are equal, and subtraction of CompareTo(DateTimeOffset) values indicates that the difference between the two times is TimeSpan.Zero.

在日期和時間運算DateTimeOffset中使用值的主要限制是, 雖然DateTimeOffset值有一些時區感知, 但它們並不是完整的時區感知。The chief limitation of using DateTimeOffset values in date and time arithmetic is that although DateTimeOffset values have some time zone awareness, they are not fully time zone aware. 雖然值的位移會DateTimeOffset在第一次為變數指派值時, 反映時區與 UTC 的位移, 但之後會變成與時區的解除關聯。 DateTimeOffsetAlthough the DateTimeOffset value's offset reflects a time zone's offset from UTC when a DateTimeOffset variable is first assigned a value, it becomes disassociated from the time zone thereafter. 因為它不再與可識別時間直接關聯,所以加上和減去日期和時間間隔不會視為時區的調整規則。Because it is no longer directly associated with an identifiable time, the addition and subtraction of date and time intervals does not consider a time zone's adjustment rules.

舉例而言,美國中央標準時間時區轉換成日光節約時間是在 2008 年 3 月 9 日的To illustrate, the transition to daylight saving time in the U.S. Central Standard Time zone occurs at 2:00 A.M. 凌晨 2:00 發生。on March 9, 2008. 這表示,中央標準時間 2008 年 3 月 9 日上午 1:30 加上兩個半小時的間隔,This means that adding a two and a half hour interval to a Central Standard time of 1:30 A.M. 就會產生 2008 年 3 月 9 日凌晨 5:00 的on March 9, 2008, should produce a date and time of 5:00 A.M. 日期和時間。on March 9, 2008. 不過,如下列範例所示,加上兩個半小時後為 2008 年 3 月 9 日However, as the following example shows, the result of the addition is 4:00 A.M. 凌晨 4:00。on March 9, 2008. 請注意,雖然這並非我們感興趣的時區時間 (亦即,它沒有預期的時區位移),但是這項作業的結果確實代表正確時間點。Note that this result of this operation does represent the correct point in time, although it is not the time in the time zone in which we are interested (that is, it does not have the expected time zone offset).

using System;

public class IntervalArithmetic
{
   public static void Main()
   {
      DateTime generalTime = new DateTime(2008, 3, 9, 1, 30, 0);
      const string tzName = "Central Standard Time";
      TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

      // Instantiate DateTimeOffset value to have correct CST offset
      try
      {
         DateTimeOffset centralTime1 = new DateTimeOffset(generalTime, 
                    TimeZoneInfo.FindSystemTimeZoneById(tzName).GetUtcOffset(generalTime));
      
         // Add two and a half hours      
         DateTimeOffset centralTime2 = centralTime1.Add(twoAndAHalfHours);
         // Display result
         Console.WriteLine("{0} + {1} hours = {2}", centralTime1, 
                                                    twoAndAHalfHours.ToString(), 
                                                    centralTime2);  
      }
      catch (TimeZoneNotFoundException)
      {
         Console.WriteLine("Unable to retrieve Central Standard Time zone information.");
      }
   }
}
// The example displays the following output to the console:
//    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 4:00:00 AM -06:00
Module IntervalArithmetic
   Public Sub Main()
      Dim generalTime As Date = #03/09/2008 1:30AM#
      Const tzName As String = "Central Standard Time"
      Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

      ' Instantiate DateTimeOffset value to have correct CST offset
      Try
         Dim centralTime1 As New DateTimeOffset(generalTime, _
                    TimeZoneInfo.FindSystemTimeZoneById(tzName).GetUtcOffset(generalTime))
      
         ' Add two and a half hours      
         Dim centralTime2 As DateTimeOffset = centralTime1.Add(twoAndAHalfHours)
         ' Display result
         Console.WriteLine("{0} + {1} hours = {2}", centralTime1, _
                                                    twoAndAHalfHours.ToString(), _
                                                    centralTime2)   
      Catch e As TimeZoneNotFoundException
         Console.WriteLine("Unable to retrieve Central Standard Time zone information.")
      End Try
   End Sub
End Module
' The example displays the following output to the console:
'    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 4:00:00 AM -06:00

使用時區時間的算數運算Arithmetic operations with times in time zones

TimeZoneInfo類別包含一些轉換方法, 會在將時間從某個時區轉換為另一個時區時, 自動套用調整。The TimeZoneInfo class includes a number of conversion methods that automatically apply adjustments when they convert times from one time zone to another. 這些需求包括下列各項:These include the following:

如需詳細資訊, 請參閱在各時區之間轉換時間For details, see Converting times between time zones.

當您執行日期和時間算術時,類別不會提供自動套用調整規則的任何方法。ConvertTimeToUtc(DateTime)The ConvertTimeToUtc(DateTime) class does not provide any methods that automatically apply adjustment rules when you perform date and time arithmetic. 不過,作法是將時區時間轉換為 UTC,並執行算術運算,然後從 UTC 轉換回時區時間。However, you can do this by converting the time in a time zone to UTC, performing the arithmetic operation, and then converting from UTC back to the time in the time zone. 如需詳細資訊,請參閱如何:使用日期和時間運算中的時區。For details, see How to: Use time zones in date and time arithmetic.

例如,下列程式碼與前面的程式碼類似,也是將 2008 年 3 月 9 日For example, the following code is similar to the previous code that added two-and-a-half hours to 2:00 A.M. 凌晨 2:00 加上兩個半小時。on March 9, 2008. 不過,因為它會先將美加中部標準時間轉換為 UTC,再執行日期和時間運算,然後將 UTC 的結果轉換回美加中部標準時間,所以產生的時間會反映美加中部標準時區到日光節約時間的轉換。However, because it converts a Central Standard time to UTC before it performs date and time arithmetic, and then converts the result from UTC back to Central Standard time, the resulting time reflects the Central Standard Time Zone's transition to daylight saving time.

using System;

public class TimeZoneAwareArithmetic
{
   public static void Main()
   {
      const string tzName = "Central Standard Time";
      
      DateTime generalTime = new DateTime(2008, 3, 9, 1, 30, 0);
      TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
      TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

      // Instantiate DateTimeOffset value to have correct CST offset
      try
      {
         DateTimeOffset centralTime1 = new DateTimeOffset(generalTime, 
                                       cst.GetUtcOffset(generalTime));
      
         // Add two and a half hours
         DateTimeOffset utcTime = centralTime1.ToUniversalTime();
         utcTime += twoAndAHalfHours;
               
         DateTimeOffset centralTime2 = TimeZoneInfo.ConvertTime(utcTime, cst);
         // Display result
         Console.WriteLine("{0} + {1} hours = {2}", centralTime1, 
                                                    twoAndAHalfHours.ToString(), 
                                                    centralTime2);  
      }
      catch (TimeZoneNotFoundException)
      {
         Console.WriteLine("Unable to retrieve Central Standard Time zone information.");
      }
   }
}
// The example displays the following output to the console:
//    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 5:00:00 AM -05:00
Module TimeZoneAwareArithmetic
   Public Sub Main()
      Const tzName As String = "Central Standard Time"
      
      Dim generalTime As Date = #03/09/2008 1:30AM#
      Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName) 
      Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

      ' Instantiate DateTimeOffset value to have correct CST offset
      Try
         Dim centralTime1 As New DateTimeOffset(generalTime, _
                    cst.GetUtcOffset(generalTime))
      
         ' Add two and a half hours 
         Dim utcTime As DateTimeOffset = centralTime1.ToUniversalTime()
         utcTime += twoAndAHalfHours
         
         Dim centralTime2 As DateTimeOffset = TimeZoneInfo.ConvertTime(utcTime, cst)
         ' Display result
         Console.WriteLine("{0} + {1} hours = {2}", centralTime1, _
                                                    twoAndAHalfHours.ToString(), _
                                                    centralTime2)   
      Catch e As TimeZoneNotFoundException
         Console.WriteLine("Unable to retrieve Central Standard Time zone information.")
      End Try
   End Sub
End Module
' The example displays the following output to the console:
'    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 5:00:00 AM -05:00

另請參閱See also