# 使用日期和时间执行算术运算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.

## 日期时间值的比较和算术运算Comparisons and arithmetic operations with DateTime values

DateTime.Kind属性允许将值分配给日期和时间,以指示它是表示本地时间、协调世界时(UTC)还是未指定的时区DateTimeKind中的时间。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 时间和本地时间之间的时差其 UTC 时间与本地时间之间的时差是 7 小时。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执行的任何算术运算的结果都相等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.

## 具有 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. 当值相同时, 如果它们具有相同的日期和时间值DateTimeOffset , 则值相等; 如果两个值都引用同一时间点, 则值相等。 DateTimeWhereas 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)


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

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