Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Это становится все более важным для любого приложения, которое работает с датами и временем для обработки различий между часовыми поясами. Приложение больше не может предположить, что все время может быть выражено в локальном времени, что является временем, доступным из 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, если свойство DateTime объекта Kind и часовой пояс не совпадают. Несоответствие возникает, если свойство 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