Преобразование времени из одного часового пояса в другойConverting times between time zones

Обработка различий между часовыми поясами становится все более важной для всех приложений, которые работают с датами и временем.It is becoming increasingly important for any application that works with dates and times to handle differences between time zones. Приложение больше не может считать, что все значения времени могут быть выражены в местном времени, которое является временем, доступным в DateTime структуре.An application can no longer assume that all times can be expressed in the local time, which is the time available from the DateTime structure. Например, веб-страница, которая отображает текущее время в восточной части США, будет содержать недостоверные сведения для пользователей в восточной Азии.For example, a Web page that displays the current time in the eastern part of the United States will lack credibility to a customer in eastern Asia. В этом разделе объясняется, как преобразовать время из одного часового пояса в другой, а также как преобразовать DateTimeOffset значения с ограниченной поддержкой часовых поясов.This topic explains how to convert times from one time zone to another, as well as how to convert DateTimeOffset values that have limited time zone awareness.

Преобразование во время в формате UTCConverting to Coordinated Universal Time

Время в формате UTC — это высокоточный, атомарный стандарт времени.Coordinated Universal Time (UTC) is a high-precision, atomic time standard. Часовые пояса мира выражаются как положительные или отрицательные смещения относительно времени в формате UTC.The world's time zones are expressed as positive or negative offsets from UTC. Таким образом, время в формате UTC предоставляет тип времени, свободного от часовых поясов, или нейтрального времени часового пояса.Thus, UTC provides a kind of time-zone free or time-zone neutral time. Использование времени в формате UTC рекомендовано, когда важна совместимость даты и времени между компьютерами.The use of UTC time is recommended when a date and time's portability across computers is important. (Дополнительные сведения и другие рекомендации по датам и времени см. в разделе Создание кода рекомендаций с использованием DateTime в .NET Framework.) Преобразование отдельных часовых поясов в формат UTC упрощает сравнение времени.(For details and other best practices using dates and times, see Coding best practices using DateTime in the .NET Framework.) Converting individual time zones to UTC makes time comparisons easy.

Примечание

Можно также сериализовать DateTimeOffset структуру для однозначного представления одного момента времени.You can also serialize a DateTimeOffset structure to unambiguously represent a single point in time. Поскольку DateTimeOffset объекты хранят значение даты и времени вместе со смещением от времени в формате UTC, они всегда представляют определенный момент времени в связи с временем в формате UTC.Because DateTimeOffset objects store a date and time value along with its offset from UTC, they always represent a particular point in time in relationship to UTC.

Самый простой способ преобразовать время в формат UTC — вызвать static Shared метод (в Visual Basic) TimeZoneInfo.ConvertTimeToUtc(DateTime) .The easiest way to convert a time to UTC is to call the static (Shared in Visual Basic) TimeZoneInfo.ConvertTimeToUtc(DateTime) method. Точное преобразование, выполняемое методом, зависит от значения dateTime Kind Свойства параметра, как показано в следующей таблице.The exact conversion performed by the method depends on the value of the dateTime parameter's Kind property, as the following table shows.

DateTime.Kind ПреобразованиеConversion
DateTimeKind.Local Преобразует местное время во время в формате UTC.Converts local time to UTC.
DateTimeKind.Unspecified Предполагает, что параметр dateTime является местным временем и преобразовывает местное время в UTC.Assumes the dateTime parameter is local time and converts local time to UTC.
DateTimeKind.Utc Возвращает неизмененный параметр dateTime.Returns the dateTime parameter unchanged.

Следующий код преобразовывает текущее местное время во время в формате UTC и выводит результат на консоль.The following code converts the current local time to UTC and displays the result to the console.

DateTime dateNow = DateTime.Now;
Console.WriteLine("The date and time are {0} UTC.",
                   TimeZoneInfo.ConvertTimeToUtc(dateNow));
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
                  TimeZoneInfo.ConvertTimeToUtc(dateNow))

Если значение даты и времени не представляет ни местное время, ни время в формате UTC, то, ToUniversalTime скорее всего, метод вернет ошибочный результат.If the date and time value does not represent either the local time or UTC, the ToUniversalTime method will likely return an erroneous result. Однако можно использовать TimeZoneInfo.ConvertTimeToUtc метод для преобразования даты и времени из указанного часового пояса.However, you can use the TimeZoneInfo.ConvertTimeToUtc method to convert the date and time from a specified time zone. (Дополнительные сведения о получении TimeZoneInfo объекта, представляющего часовой пояс назначения, см. в разделе Поиск часовых поясов, определенных в локальной системе.) В следующем коде используется TimeZoneInfo.ConvertTimeToUtc метод для преобразования восточного стандартного времени в формат UTC.(For details on retrieving a TimeZoneInfo object that represents the destination time zone, see Finding the time zones defined on a local system.) The following code uses the TimeZoneInfo.ConvertTimeToUtc method to convert Eastern Standard Time to UTC.

DateTime easternTime = new DateTime(2007, 01, 02, 12, 16, 00);
string easternZoneId = "Eastern Standard Time";
try
{
   TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
   Console.WriteLine("The date and time are {0} UTC.",
                     TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone));
}
catch (TimeZoneNotFoundException)
{
   Console.WriteLine("Unable to find the {0} zone in the registry.",
                     easternZoneId);
}
catch (InvalidTimeZoneException)
{
   Console.WriteLine("Registry data on the {0} zone has been corrupted.",
                     easternZoneId);
}
Dim easternTime As New Date(2007, 01, 02, 12, 16, 00)
Dim easternZoneId As String = "Eastern Standard Time"
Try
    Dim easternZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId)
    Console.WriteLine("The date and time are {0} UTC.", _
                      TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("Unable to find the {0} zone in the registry.", _
                      easternZoneId)
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the {0} zone has been corrupted.", _
                      easternZoneId)
End Try

Обратите внимание, что этот метод создает исключение, ArgumentException Если DateTime Kind свойство объекта и часовой пояс не совпадают.Note that this method throws an ArgumentException if the DateTime object's Kind property and the time zone are mismatched. Несоответствие возникает, если Kind свойство имеет значение DateTimeKind.Local TimeZoneInfo , но объект не представляет местный часовой пояс, или если свойство имеет значение, Kind DateTimeKind.Utc но объект не TimeZoneInfo равен TimeZoneInfo.Utc .A mismatch occurs if the Kind property is DateTimeKind.Local but the TimeZoneInfo object does not represent the local time zone, or if the Kind property is DateTimeKind.Utc but the TimeZoneInfo object does not equal TimeZoneInfo.Utc.

Все эти методы принимают DateTime значения в качестве параметров и возвращают DateTime значение.All of these methods take DateTime values as parameters and return a DateTime value. Для DateTimeOffset значений DateTimeOffset структура имеет ToUniversalTime метод экземпляра, который преобразует дату и время текущего экземпляра в формат UTC.For DateTimeOffset values, the DateTimeOffset structure has a ToUniversalTime instance method that converts the date and time of the current instance to UTC. В следующем примере вызывается ToUniversalTime метод для преобразования местного времени и нескольких других значений времени в формат UTC.The following example calls the ToUniversalTime method to convert a local time and several other times to Coordinated Universal Time (UTC).

DateTimeOffset localTime, otherTime, universalTime;

// Define local time in local time zone
localTime = new DateTimeOffset(new DateTime(2007, 6, 15, 12, 0, 0));
Console.WriteLine("Local time: {0}", localTime);
Console.WriteLine();

// Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero);
Console.WriteLine("Other time: {0}", otherTime);
Console.WriteLine("{0} = {1}: {2}",
                  localTime, otherTime,
                  localTime.Equals(otherTime));
Console.WriteLine("{0} exactly equals {1}: {2}",
                  localTime, otherTime,
                  localTime.EqualsExact(otherTime));
Console.WriteLine();

// Convert other time to UTC
universalTime = localTime.ToUniversalTime();
Console.WriteLine("Universal time: {0}", universalTime);
Console.WriteLine("{0} = {1}: {2}",
                  otherTime, universalTime,
                  universalTime.Equals(otherTime));
Console.WriteLine("{0} exactly equals {1}: {2}",
                  otherTime, universalTime,
                  universalTime.EqualsExact(otherTime));
Console.WriteLine();
// The example produces the following output to the console:
//    Local time: 6/15/2007 12:00:00 PM -07:00
//
//    Other time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
//
//    Universal time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True
Dim localTime, otherTime, universalTime As DateTimeOffset

' Define local time in local time zone
localTime = New DateTimeOffset(#6/15/2007 12:00:00PM#)
Console.WriteLine("Local time: {0}", localTime)
Console.WriteLine()

' Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero)
Console.WriteLine("Other time: {0}", otherTime)
Console.WriteLine("{0} = {1}: {2}", _
                  localTime, otherTime, _
                  localTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  localTime, otherTime, _
                  localTime.EqualsExact(otherTime))
Console.WriteLine()

' Convert other time to UTC
universalTime = localTime.ToUniversalTime()
Console.WriteLine("Universal time: {0}", universalTime)
Console.WriteLine("{0} = {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.EqualsExact(otherTime))
Console.WriteLine()
' The example produces the following output to the console:
'    Local time: 6/15/2007 12:00:00 PM -07:00
'    
'    Other time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
'    
'    Universal time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True   

Преобразование времени в формате UTC в заданный часовой поясConverting UTC to a designated time zone

Для преобразования времени в формате UTC в местное время см. следующий раздел "преобразование времени UTC в местное время".To convert UTC to local time, see the "Converting UTC to Local Time" section that follows. Для преобразования времени в формате UTC во время в любом назначенном часовом поясе вызовите ConvertTimeFromUtc метод.To convert UTC to the time in any time zone that you designate, call the ConvertTimeFromUtc method. Этот метод принимает два параметра:The method takes two parameters:

  • Время в формате UTC, которое требуется преобразовать.The UTC to convert. Это должно быть DateTime значение, свойство которого равно Kind Unspecified или Utc .This must be a DateTime value whose Kind property is set to Unspecified or Utc.

  • Часовой пояс, в который требуется преобразовать время в формате UTC.The time zone to convert the UTC to.

Следующий код преобразует время в формате UTC в центральное стандартное время.The following code converts UTC to Central Standard Time.

DateTime timeUtc = DateTime.UtcNow;
try
{
   TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
   DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
   Console.WriteLine("The date and time are {0} {1}.",
                     cstTime,
                     cstZone.IsDaylightSavingTime(cstTime) ?
                             cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
   Console.WriteLine("The registry does not define the Central Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
   Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.");
}
Dim timeUtc As Date = Date.UtcNow
Try
    Dim cstZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
    Dim cstTime As Date = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone)
    Console.WriteLine("The date and time are {0} {1}.", _
                      cstTime, _
                      IIf(cstZone.IsDaylightSavingTime(cstTime), _
                          cstZone.DaylightName, cstZone.StandardName))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Central Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.")
End Try

Преобразование времени в формате UTC в местное времяConverting UTC to local time

Для преобразования времени в формате UTC в местное время вызовите ToLocalTime метод DateTime объекта, время которого необходимо преобразовать.To convert UTC to local time, call the ToLocalTime method of the DateTime object whose time you want to convert. Точное поведение метода зависит от значения Kind свойства объекта, как показано в следующей таблице.The exact behavior of the method depends on the value of the object's Kind property, as the following table shows.

DateTime.Kind ПреобразованиеConversion
DateTimeKind.Local Возвращает DateTime значение без изменений.Returns the DateTime value unchanged.
DateTimeKind.Unspecified Предполагается, что DateTime значение равно UTC и ПРЕОБРАЗУЕТ UTC в местное время.Assumes that the DateTime value is UTC and converts the UTC to local time.
DateTimeKind.Utc Преобразует DateTime значение в местное время.Converts the DateTime value to local time.

Примечание

TimeZone.ToLocalTimeМетод ведет себя идентично DateTime.ToLocalTime методу.The TimeZone.ToLocalTime method behaves identically to the DateTime.ToLocalTime method. Он принимает один параметр, который представляет собой значение даты и времени для преобразования.It takes a single parameter, which is the date and time value to convert.

Можно также преобразовать время в любом заданном часовом поясе в местное время с помощью static Shared метода (в Visual Basic) TimeZoneInfo.ConvertTime .You can also convert the time in any designated time zone to local time by using the static (Shared in Visual Basic) TimeZoneInfo.ConvertTime method. Этот метод рассматривается в следующем разделе.This technique is discussed in the next section.

Преобразование между любыми двумя часовыми поясамиConverting between any two time zones

Преобразование между любыми двумя часовыми поясами можно выполнить с помощью любого из следующих двух static Shared методов (в Visual Basic) TimeZoneInfo класса:You can convert between any two time zones by using either of the following two static (Shared in Visual Basic) methods of the TimeZoneInfo class:

  • ConvertTime

    Параметры этого метода — это значение даты и времени для преобразования, TimeZoneInfo объект, представляющий часовой пояс значения даты и времени, и TimeZoneInfo объект, представляющий часовой пояс для преобразования значения даты и времени в.This method's parameters are the date and time value to convert, a TimeZoneInfo object that represents the time zone of the date and time value, and a TimeZoneInfo object that represents the time zone to convert the date and time value to.

  • ConvertTimeBySystemTimeZoneId

    Параметры этого метода — это значение даты и времени для преобразования, идентификатор часового пояса значения даты и времени и идентификатор часового пояса, в который необходимо преобразовать значение даты и времени.This method's parameters are the date and time value to convert, the identifier of the date and time value's time zone, and the identifier of the time zone to convert the date and time value to.

Для обоих методов требуется, Kind чтобы свойство значения даты и времени было преобразовано, а TimeZoneInfo объект или идентификатор часового пояса, представляющий его часовой пояс, соответствовал друг другу.Both methods require that the Kind property of the date and time value to convert and the TimeZoneInfo object or time zone identifier that represents its time zone correspond to one another. В противном случае возникает исключение ArgumentException.Otherwise, an ArgumentException is thrown. Например, если Kind свойство значения даты и времени равно DateTimeKind.Local , возникает исключение, если TimeZoneInfo объект, переданный в качестве параметра в метод, не равен TimeZoneInfo.Local .For example, if the Kind property of the date and time value is DateTimeKind.Local, an exception is thrown if the TimeZoneInfo object passed as a parameter to the method is not equal to TimeZoneInfo.Local. Исключение также создается, если идентификатор, переданный в качестве параметра в метод, не равен TimeZoneInfo.Local.Id .An exception is also thrown if the identifier passed as a parameter to the method is not equal to TimeZoneInfo.Local.Id.

В следующем примере используется ConvertTime метод для преобразования из Гавайского стандартного времени в местное время.The following example uses the ConvertTime method to convert from Hawaiian Standard Time to local time.

DateTime hwTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
   TimeZoneInfo hwZone = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time");
   Console.WriteLine("{0} {1} is {2} local time.",
           hwTime,
           hwZone.IsDaylightSavingTime(hwTime) ? hwZone.DaylightName : hwZone.StandardName,
           TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local));
}
catch (TimeZoneNotFoundException)
{
   Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
   Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.");
}
Dim hwTime As Date = #2/01/2007 8:00:00 AM#
Try
    Dim hwZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time")
    Console.WriteLine("{0} {1} is {2} local time.", _
                      hwTime, _
                      IIf(hwZone.IsDaylightSavingTime(hwTime), hwZone.DaylightName, hwZone.StandardName), _
                      TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.")
End Try

Преобразование значений DateTimeOffsetConverting DateTimeOffset values

Значения даты и времени, представленные DateTimeOffset объектами, не имеют полной осведомленности о часовых поясах, так как объект не связан с часовым поясом во время создания экземпляра.Date and time values represented by DateTimeOffset objects are not fully time-zone aware because the object is disassociated from its time zone at the time it is instantiated. Однако во многих случаях приложению достаточно преобразовать дату и время на основе двух различных значений смещения относительно времени в формате UTC, а не на основе времени конкретных часовых поясов.However, in many cases an application simply needs to convert a date and time based on two different offsets from UTC rather than on the time in particular time zones. Чтобы выполнить это преобразование, можно вызвать метод текущего экземпляра ToOffset .To perform this conversion, you can call the current instance's ToOffset method. Единственным параметром метода является смещение нового значения даты и времени, возвращаемого методом.The method's single parameter is the offset of the new date and time value that the method is to return.

Например, если дата и время запроса пользователя к веб-странице известны и сериализованы в виде строки в формате мм/дд/гггг чч:мм:сс zzzz, то следующий метод ReturnTimeOnServer преобразует это значение даты и времени в значение даты и времени на веб-сервере.For example, if the date and time of a user request for a Web page is known and is serialized as a string in the format MM/dd/yyyy hh:mm:ss zzzz, the following ReturnTimeOnServer method converts this date and time value to the date and time on the Web server.

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";
   TimeSpan serverOffset = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now);

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = clientTime.ToOffset(serverOffset);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"
    Dim serverOffset As TimeSpan = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now)

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = clientTime.ToOffset(serverOffset)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

Если методу передается строка "9/1/2007 5:32:07 -05:00", которая представляет дату и время в часовом поясе, который раньше пояса UTC на пять часов, он возвращает строку "9/1/2007 3:32:07 -07:00" для сервера, расположенного в тихоокеанском стандартном часовом поясе США.If the method is passed the string "9/1/2007 5:32:07 -05:00", which represents the date and time in a time zone five hours earlier than UTC, it returns 9/1/2007 3:32:07 AM -07:00 for a server located in the U.S. Pacific Standard Time zone.

TimeZoneInfoКласс также включает перегрузку TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) метода, который выполняет преобразование часовых поясов со ToOffset(TimeSpan) значениями.The TimeZoneInfo class also includes an overload of the TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) method that performs time zone conversions with ToOffset(TimeSpan) values. Параметры метода являются DateTimeOffset значением и ссылкой на часовой пояс, к которому необходимо преобразовать время.The method's parameters are a DateTimeOffset value and a reference to the time zone to which the time is to be converted. Вызов метода возвращает DateTimeOffset значение.The method call returns a DateTimeOffset value. Например, ReturnTimeOnServer метод в предыдущем примере можно переписывать следующим образом для вызова ConvertTime(DateTimeOffset, TimeZoneInfo) метода.For example, the ReturnTimeOnServer method in the previous example could be rewritten as follows to call the ConvertTime(DateTimeOffset, TimeZoneInfo) method.

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format,
                                  CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = TimeZoneInfo.ConvertTime(clientTime,
                                  TimeZoneInfo.Local);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = TimeZoneInfo.ConvertTime(clientTime, TimeZoneInfo.Local)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

См. также статьюSee also