Подтвердить что ты не робот

Как работать с часовыми поясами в ASP.NET?

Я работаю над проектом онлайн-напоминания (ASP.NET 2.0 (С#)/SQL Server 2005)

Поскольку это служба напоминания, которая будет отправлять почту пользователям в определенные даты. Но проблема в том, что пользователи не из определенных стран, они со всего мира и из разных часовых поясов. Теперь, когда я регистрируюсь, я запрашиваю часовой пояс пользователей так же, как окна запрашивают наш часовой пояс на момент установки.

Но я не получаю, если пользователь выбрал (+5.30) или что-то временное, тогда как обрабатывать этот часовой пояс в моем приложении asp.net. Как работать в соответствии с часовым поясом.

И, пожалуйста, подскажите, есть ли лучший способ обработки часовых поясов в этом приложении?

Спасибо

4b9b3361

Ответ 1

Прежде всего, убедитесь, что в часовом поясе находятся ваши данные. Я бы порекомендовал вам убедиться, что любое хранилище DateTime, которое вы храните, хранится в UTC (используйте DateTime.ToUniversalTime(), чтобы получить его).

Когда вы хотите сохранить напоминание для пользователя, вам понадобится текущее время UTC, добавьте или удалите разницу часовых поясов пользователя и преобразуйте это новое время обратно в UTC; это то, что вы хотите сохранить в БД.

Затем, когда вы хотите проверить отправку напоминаний, вам просто нужно посмотреть в базе данных, чтобы напоминания отправляли сейчас, в соответствии с временем UTC; по существу получить все напоминания, которые имеют отметку времени, которая до DateTime.Now.ToUniversalTime().

Обновить с некоторыми особенностями реализации: Вы можете получить список часовых поясов из метода TimeZoneInfo.GetSystemTimeZones(); вы можете использовать их для отображения списка часовых поясов для пользователя. Если вы сохранили свойство Id в выбранном часовом поясе, вы можете создать экземпляр класса TimeZoneInfo из него и вычислить время UTC для заданного локального значения даты/времени:

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("<the time zone id>");
// May 7, 08:04:00
DateTime userDateTime = new DateTime(2009, 5, 7, 8, 4, 0);
DateTime utcDateTime = userDateTime.Subtract(tzi.BaseUtcOffset);

Ответ 2

Я бы рекомендовал всегда использовать время UTC (GMT) на стороне сервера (в кодировке, базе данных и т.д.) и конвертировать время с UTC в локальное время для показа. Это означает, что все временные манипуляции, включая экономию времени в базе данных, выполнение вычислений и т.д., Должны выполняться с использованием UTC.

Проблема заключается в следующем: как ваш код-код знает, что такое часовой пояс клиентского браузера? Скажите, что пользователь вводит какое-либо значение даты/времени (например, 12/30/2009 14:30) в форме и отправляет его на сервер. Предполагая, что пользователь отправил местное время, как сервер знает, как преобразовать это значение в UTC?

Приложение может попросить пользователя указать часовой пояс (и сохранить его в постоянном файле cookie или базе данных), но для этого требуется и дополнительные усилия от пользователя, и вашему приложению потребуется реализовать для этого логику и экраны. Было бы лучше, если бы приложение автоматически определяло часовой пояс клиента.

Я рассмотрел этот вопрос с помощью JavaScript getTimezoneOffset функция, которая является единственным API, который может сообщить серверу о времени разница между местным временем на клиенте и GMT. Поскольку это API-интерфейс на стороне клиента, я сделал следующее: на стороне сервера проверьте, имеет ли пользовательский файл cookie сеанса значение смещения времени, а если он недоступен, перезагрузите страницу (только во время GET, а не POST, звонков) с добавлением некоторой логики JavaScript для создания смещения по времени и сохранения его в файле cookie. С клиентской стороны это почти прозрачно (один раз во время сеанса я перезагружаю страницу в GET). Как только у меня есть смещение в cookie, я применяю его к функциям управления временем в зависимости от направления преобразования времени (UTC в локальное время или по местному времени в UTC).

Это может показаться немного сложным, но это так, но после того, как я написал вспомогательные функции, интеграция этой функции на сайте заключалась в том, чтобы сделать одиночный вызов в Page_Load (страниц, требующих времени) преобразование) и использование процедур преобразования времени при отправке и извлечения значений времени в браузер и из него. Вот пример того, как его можно использовать:

using My.Utilities.Web;
...

// Derive the form class from BaseForm instead of Page.
public class WebForm1: BaseForm
{
...
private void Page_Load(object sender, System.EventArgs e)
{
  // If we only want to load the page to generate the time
  // zone offset cookie, we do not need to do anything else.
  if (InitializeLocalTime())
    return;

  // Assume that txtStartDate is a TextBox control.
  if (!IsPostback)
  {
     // To display a date-time value, convert it from GMT (UTC)
     // to local time.
     DateTime startDate = GetStartDateFromDB(...);
     txtStartDate.Text  = FormatLocalDate(startDate);
     ...
  }
  else
  {
     // To save a date-time value, convert it from local
     // time to GMT (UTC).
     DateTime tempDate  = DateTime.Parse(txtStartDate.Text);
     DateTime startDate = ConvertLocalTimeToUtc(tempDate);
     SaveStartDateInDB(startDate, ...);
     ...
  }
}
...
}

Если вам нужна дополнительная информация, ознакомьтесь с About About: время локализации в приложениях ASP.NET (извините, но я не имеют прямую ссылку на статью на сайте издателя, поскольку asp.netPRO ограничивает доступ только к платным подписчикам, однако есть ссылки на копии в формате PDF). Я хотел бы опубликовать образец из статьи, но я не хочу нарушать авторские права; однако здесь представлен проект для создания вспомогательной библиотеки, которая имеет всю необходимую функциональность и документацию (просто игнорируйте материал, который вы не нужно).

ОБНОВЛЕНИЕ: статья была опубликована онлайн с образцом проекта новым издателем здесь.

Ответ 3

Проблема со всеми ответами до сих пор заключается в том, что они не принимают во внимание то, что пытается достичь Прашант. Если пользователь своей системы за день до перехода на летнее время имеет смещение +12 и устанавливает напоминание на следующий день, его смещение, когда предполагается, что напоминание должно быть вызвано, будет вместо этого +13.

Вот почему вы можете использовать текущее смещение только для того, что происходит сейчас. Хотя я согласен со всеми, что все серверные серверы (за исключением, возможно, тех, которые используются только для отображения) должны храниться в UTC.

Ответ 4

Возможно, вы захотите рассмотреть структуру DateTimeOffset вместо DateTime, если вы находитесь в среде 2.0 или новее.

DateTimeOffset представляет собой момент времени относительно времени UTC, поэтому в этом случае должно быть проще работать.

Ответ 5

Есть два шага:

  • Обнаружение разного часового пояса на стороне клиента с помощью Javascript:

    var dt = new Date();
    var diffInMinutes = -dt.getTimezoneOffset();
    
  • Затем на стороне сервера код С# для преобразования времени сервера в клиентское время на основе обнаруженного смещения временной зоны выше:

------------------------;

string queryStr = Request.QueryString["diffInMinutes"];
int diffInMinutes = 0;
if (Int32.TryParse(queryStr, out diffInMinutes))
{
    clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes);
}

Ответ 6

В принципе, все, что вам нужно сделать, это добавить смещение (часы + минуты) в локальное время, которое пользователь ввел. Добавление в смещение в основном дает вам DateTime в часовой пояс UTC (в основном GMT).

Обычно проще всего стандартизировать все время до UTC, так что логика вашего приложения не должна иметь дело с смещениями.

На этой странице есть несколько хороших примеров: http://msdn.microsoft.com/en-us/library/bb546099.aspx

Ответ 7

Проблема в том, что смещение от UTC будет меняться в разное время года - каждый часовой пояс имеет свои собственные правила. (Я изучил этот трудный путь при разработке приложения для планирования конференц-зала.)

Похоже, есть встроенная поддержка здесь: http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx

Не пробовал сам, но, похоже, обещает правильное преобразование, учитывая переход на летнее время.

Если нет, здесь (дорогой) коммерческий инструмент, который я использовал: http://www.worldtimeserver.com/time_zone_guide/