Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это становится все более важным для любого приложения, которое работает с датами и временем для обработки различий между часовыми поясами. Приложение больше не может предположить, что все время может быть выражено в локальном времени, что является временем, доступным из DateTime структуры. Например, веб-страница, отображающая текущее время в восточной части США, не вызовет доверия у клиента в Восточной Азии. В этой статье объясняется, как преобразовать время из одного часового пояса в другой и преобразовать DateTimeOffset значения с ограниченным учетом часовых поясов.
Преобразование в координированное универсальное время
Координированное универсальное время (UTC) — это высокоточный, атомарный стандарт времени. Часовые пояса мира выражаются как положительные или отрицательные смещения из UTC. Таким образом, UTC предоставляет время, не зависящее от часовых поясов или нейтральное по отношению к ним. Использование UTC рекомендуется, когда важно переносимость даты и времени на компьютерах. Дополнительные сведения и другие рекомендации по использованию дат и времени см. в рекомендациях по написанию кода с помощью DateTime в .NET Framework. Преобразование отдельных часовых поясов в UTC упрощает сравнение времени.
Примечание.
Можно также сериализовать структуру DateTimeOffset для представления единой точки во времени однозначно. Поскольку DateTimeOffset объекты хранят значение даты и времени вместе со смещением из UTC, они всегда представляют определенную точку времени в отношении UTC.
Самый простой способ преобразовать время в UTC — это вызвать метод static
(Shared
в Visual Basic) TimeZoneInfo.ConvertTimeToUtc(DateTime). Точное преобразование, выполняемое методом, зависит от значения dateTime
свойства параметра Kind , как показано в следующей таблице:
DateTime.Kind |
Превращение |
---|---|
DateTimeKind.Local |
Преобразует локальное время в формате UTC. |
DateTimeKind.Unspecified |
Предполагает, dateTime что параметр является локальным временем и преобразует локальное время в utc. |
DateTimeKind.Utc |
dateTime Возвращает параметр без изменений. |
Следующий код преобразует текущее локальное время в формате UTC и отображает результат в консоль:
DateTime dateNow = DateTime.Now;
Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(dateNow)} UTC.");
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
TimeZoneInfo.ConvertTimeToUtc(dateNow))
Если значение даты и времени не представляет локальное время или utc, метод, скорее всего, ToUniversalTime вернет ошибочный результат. Однако метод можно использовать TimeZoneInfo.ConvertTimeToUtc для преобразования даты и времени из указанного часового пояса. Дополнительные сведения о получении объекта, представляющего часовой TimeZoneInfo пояс назначения, см. в статье Поиск часовых поясов, определенных в локальной системе. Следующий код использует метод TimeZoneInfo.ConvertTimeToUtc для преобразования Восточного стандартного времени в 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 {TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)} UTC.");
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine($"Unable to find the {easternZoneId} zone in the registry.");
}
catch (InvalidTimeZoneException)
{
Console.WriteLine($"Registry data on the {easternZoneId} zone has been corrupted.");
}
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
Метод TimeZoneInfo.ConvertTimeToUtc вызывает ArgumentException, если свойство Kind объекта DateTime и часовой пояс не совпадают. Несоответствие возникает, если свойство Kind — это DateTimeKind.Local, но объект TimeZoneInfo не представляет локальный часовой пояс, или если свойство Kind — это DateTimeKind.Utc, но объект TimeZoneInfo не равен TimeZoneInfo.Utc.
Все эти методы принимают DateTime значения в качестве параметров и возвращают DateTime значение. Для значений DateTimeOffset структура DateTimeOffset имеет метод экземпляра ToUniversalTime, который преобразует дату и время текущего экземпляра в формат UTC. В следующем примере вызывается метод ToUniversalTime, чтобы преобразовать локальное время и несколько других моментов во время 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: {localTime}");
Console.WriteLine();
// Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero);
Console.WriteLine($"Other time: {otherTime}");
Console.WriteLine($"{localTime} = {otherTime}: {localTime.Equals(otherTime)}");
Console.WriteLine($"{localTime} exactly equals {otherTime}: {localTime.EqualsExact(otherTime)}");
Console.WriteLine();
// Convert other time to UTC
universalTime = localTime.ToUniversalTime();
Console.WriteLine($"Universal time: {universalTime}");
Console.WriteLine($"{otherTime} = {universalTime}: {universalTime.Equals(otherTime)}");
Console.WriteLine($"{otherTime} exactly equals {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 в указанный часовой пояс
Чтобы преобразовать UTC в локальное время, см. раздел преобразование UTC в локальное время, приведенный ниже. Чтобы преобразовать UTC в время в любом заданном часовом поясе, вызовите ConvertTimeFromUtc метод. Метод принимает два параметра:
UTC, который нужно преобразовать. Это должно быть DateTime значение, для свойства которого Kind задано значение
Unspecified
илиUtc
.Часовой пояс, в который нужно преобразовать время из UTC.
Следующий код преобразует UTC в центральное стандартное время:
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 в локальное время
Чтобы преобразовать UTC в локальное время, вызовите ToLocalTime метод DateTime объекта, время которого требуется преобразовать. Точное поведение метода зависит от значения свойства объекта Kind , как показано в следующей таблице:
DateTime.Kind |
Превращение |
---|---|
DateTimeKind.Local |
DateTime Возвращает значение без изменений. |
DateTimeKind.Unspecified |
Предполагается, что значение DateTime является UTC и преобразует UTC в местное время. |
DateTimeKind.Utc |
Преобразует DateTime значение в локальное время. |
Примечание.
Метод TimeZone.ToLocalTime работает идентично методу DateTime.ToLocalTime
. Для преобразования требуется один параметр, являющийся значением даты и времени.
Вы также можете преобразовать время в любой указанный часовой пояс в местное время, используя метод static
(Shared
в Visual Basic). TimeZoneInfo.ConvertTime Этот метод рассматривается в следующем разделе.
Преобразование между двумя часовых поясами
Можно преобразовать между любыми двумя часовыми поясами с помощью одного из следующих двух методов класса static
(Shared
в Visual Basic):
-
Параметры этого метода — это значение даты и времени, которое нужно преобразовать, объект
TimeZoneInfo
, который представляет часовой пояс значения даты и времени, а также объектTimeZoneInfo
, представляющий часовой пояс, в который нужно преобразовать значение даты и времени. -
Параметры этого метода — это значение даты и времени для преобразования, идентификатор часового пояса даты и времени, а также идентификатор часового пояса для преобразования значения даты и времени в.
Оба метода требуют, чтобы Kind свойство значения даты и времени, которое необходимо преобразовать, и TimeZoneInfo объект или идентификатор часового пояса, представляющий его часовой пояс, соответствовали друг другу. В противном случае выбрасывается ArgumentException. Например, если свойство значения даты и времени Kind
имеет значение DateTimeKind.Local
, возникает исключение, если объект TimeZoneInfo
, переданный в метод в качестве параметра, не равен TimeZoneInfo.Local
. Исключение также возникает, если идентификатор, переданный в качестве параметра методу, не равен TimeZoneInfo.Local.Id
.
В следующем примере метод используется ConvertTime для преобразования из Гавайского стандартного времени в местное время:
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
Преобразование значений DateTimeOffset
Значения даты и времени, представленные объектами DateTimeOffset не полностью осведомлены о часовом поясе, так как объект отсоединяется от часового пояса во время создания экземпляра. Однако во многих случаях приложению просто необходимо преобразовать дату и время на основе двух разных смещения из UTC, а не по времени в определенных часовых поясах. Для выполнения этого преобразования можно вызвать метод текущего экземпляра ToOffset . Один параметр метода — это смещение нового значения даты и времени, возвращаемое методом.
Например, если дата и время запроса пользователя на веб-страницу известна и сериализуется как строка в формате MM/dd/гггг чч:мм:ss zzzz, следующий ReturnTimeOnServer
метод преобразует это значение даты и времени в дату и время на веб-сервере:
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 AM -07:00" для сервера, расположенного в Тихоокеанском стандартном времени (PST).
Класс TimeZoneInfo также включает перегрузку метода TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo), которая выполняет преобразование часовых поясов при помощи значений ToOffset(TimeSpan). Параметры метода — это DateTimeOffset значение и ссылка на часовой пояс для преобразования времени. Вызов метода возвращает DateTimeOffset значение. Например, ReturnTimeOnServer
метод в предыдущем примере может быть перезаписан следующим образом, чтобы вызвать ConvertTime(DateTimeOffset, TimeZoneInfo) метод.
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