Проблема с часовым поясом веб-приложения
Вопрос
У нас есть веб-приложение ASP.Net 2.0, работающее с сервером на Среднем Западе (восточное стандартное время). На данный момент все наши клиенты находятся в одном часовом поясе с сервером. Мы подключаем другой сервер к сети в Аризоне (стандартное горное время).
Мы все время храним в базе данных SQL 2005 с помощью C # codebehind DateTime.UtcNow.
Во время тестирования мы столкнулись с некоторыми проблемами при преобразовании часовых поясов. Наша проблема заключается в том, что в веб-браузере наше время отображает стандартное горное время вместо часового пояса, который мы тестируем, по восточному стандартному времени. Р>
Когда мы вводим новую информацию, она сохраняется в базе данных как UTC, но когда мы просматриваем эту информацию в браузере, она отображает стандартное время в горах. Ниже приведен код, который берет значение UTC из базы данных и отображает его в браузере.
lblUpdatedDate.Text = Convert.ToDateTime(dr["UpdatedDate"]).ToLocalTime().ToString();
Приведенный выше код возвращает стандартное время в горах, где находится сервер, а не восточное стандартное время, в котором запущен браузер. Как мы получаем время, чтобы показать, где находится пользователь?
Решение
У меня была такая же проблема. Мы продали наше приложение пользователю, который находился в другом часовом поясе, чем веб-сервер. Мы не хранили никакой информации о времени в UTC, но на самом деле она работала правильно. Время, отображаемое в часовом поясе сервера, показывало ровно 3 часа. Все, что нам нужно было сделать, это добавить раскрывающийся список часовых поясов, чтобы они могли выбирать свой часовой пояс для всего сайта (поскольку единственные пользователи приложения были бы в их часовом поясе). Мы сохранили эту настройку, а затем вставили функцию для получения всех отображений даты и времени и преобразования из одного часового пояса в другой, используя пространство имен TimeZoneInfo. Работает отлично.
Другие советы
Местное время всегда будет на стороне сервера преобразовывать в физическое местоположение. У вас есть несколько вариантов.
<Ол>Если вы используете .NET 3.5 и , вы знаете часовой пояс, в котором находится пользователь, TimeZoneInfo - ваш друг. Если вы не используете .NET 3.5, есть несколько примеров P / Invoke, чтобы получить экземпляры TimeZone , но этого стоит избегать, если у вас есть доступ к 3.5. (TimeZoneInfo содержит исторические данные и т. Д., И, как правило, это предпочтительный способ.)
Теперь выяснить, в каком часовом поясе находятся ваши пользователи, это другая проблема - самый простой способ избежать путаницы - это дать им варианты. (Получение смещения "сейчас" дает вам только ограниченную информацию.)
Я столкнулся с чем-то подобным до использования ASP.NET. Вот моя общая методология.
Я отправил JavaScript, чтобы сделать document.write. JavaScript определяет смещение клиента от GMT. Таким образом, вы можете отправить определенное время, а затем позволить JavaScript сделать плюс / минус.
Просто всегда храните дату и время в формате GMT.
Есть 2 шага:
Определите другой часовой пояс на стороне клиента с помощью Javascript:
var dt = new Date();
var diffInMinutes = -dt.getTimezoneOffset();
Затем на стороне сервера код C # для преобразования времени сервера в время клиента на основе обнаруженного смещения часового пояса, приведенного выше:
string queryStr = Request.QueryString["diffInMinutes"];
int diffInMinutes = 0;
if (Int32.TryParse(queryStr, out diffInMinutes))
{
clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes);
}
Мы столкнулись с той же или схожей проблемой с удаленными клиентами, обращающимися к нашей базе данных через веб-сервисы, где база данных и клиенты находятся в разных часовых поясах.
Нам было проще всего указать, чтобы набор данных не заботился о часовых поясах, чтобы время не менялось за пределами часового пояса ...
Мы создали служебный метод (SetAllDateModes), который преобразует все поля даты и времени в наборе данных по таблице - вот конец бизнеса (Foreach) и вызов, который устанавливает dateMode:
foreach (DataColumn dc in dt.Columns)
{
if (dc.DataType == typeof(DateTime))
{
dc.DateTimeMode = dateMode;
}
}
SetAllDateModes(dt, DataSetDateTime.Unspecified);
DateSetDateTime.Unspecified не включает смещение, поэтому нет преобразования.
Я думал, что общая идея заключается в том, чтобы не локализовать дату & amp; время, пока вы не представите это пользователю. Так что, если человек не собирается читать его, он остается в UTC, GMT, CUT. В одной дополнительной заметке используется библиотека даты / времени, поэтому вам не нужно сильно беспокоиться о проблемах изменения летнего времени.