Ответ 1
Вы не можете делать напрямую то, что вы просили, но я предложу несколько альтернатив. Как отметил Николас, в HTTP нет ничего, что дало бы вам часовой пояс напрямую.
Вариант 1
-
Сначала определите, с каким типом данных часового пояса вы хотите работать. Доступны два разных типа: временные зоны Microsoft, к которым вы можете получить доступ, с классом
TimeZoneInfo
или часовыми поясами IANA/Olson, которые используются остальным миром. Подробнее читайте здесь. Моя рекомендация будет последней, используя реализацию, предоставленную NodaTime. -
Затем определите, какой часовой пояс вы хотите преобразовать. Вы должны разрешить своему пользователю устанавливать где-нибудь место для своего часового пояса.
-
Вы можете отобразить раскрывающийся список, чтобы выбрать один из нескольких часовых поясов, или вы можете сделать что-то более полезное, например отобразить карту мира, которую они могут щелкнуть, чтобы выбрать свой часовой пояс. Есть несколько библиотек, которые могут сделать это в Javascript, но мой любимый этот.
-
Возможно, вам захочется угадать часовой пояс по умолчанию, чтобы вы могли быть как можно ближе к точности, прежде чем выбрать из списка (или карты). Существует большая библиотека для этого jsTimeZoneDetect. Он будет допрашивать часы браузера и делать наилучшее предположение о том, какой часовой пояс он может быть. Это довольно хорошо, но это все еще просто предположение. Не используйте его вслепую - но используйте его для определения начальной точки. Обновление. Теперь вы можете сделать это с помощью
moment.tz.guess()
, в момент-время компонент момента .js.
-
-
Теперь, когда вы знаете часовой пояс пользователя, вы можете использовать это значение для преобразования ваших значений UTC
DateTime
в этот локальный часовой пояс. К сожалению, вы ничего не можете установить в потоке, который это сделает. При изменении системного часового пояса он является глобальным для всех процессов и потоков. Таким образом, у вас нет выбора, кроме как передать часовой пояс для каждого места, куда вы его отправляете. (Я считаю, что это был ваш главный вопрос.) См. Здесь почти дубликат. -
Прежде чем преобразовать его в строку, вам также нужно знать локаль пользователя (которую вы можете получить из значения Request.UserLanguages ). Вы можете назначить его текущему потоку или передать его как параметр методу
DateTime.ToString()
. Это не делает никакого преобразования часового пояса - он просто гарантирует, что цифры находятся в правильном положении, используя правильные разделители и соответствующий язык для имен дней недели или месяцев.
Вариант 2
Не конвертируйте его в локальное время на сервере вообще.
-
Поскольку вы сказали, что работаете со значениями UTC, убедитесь, что их свойство
.Kind
Utc
. Вероятно, вы должны сделать это, когда загружаете из своей базы данных, но если вам нужно это сделать вручную:myDateTime = DateTime.SpecifyKind(myDateTime, DateTimeKind.Utc);
-
Отправьте его обратно в браузер как чистый UTC в инвариантном формате, таком как ISO8601. Другими словами:
myDateTime.ToString("o"); // example: "2013-05-02T21:01:26.0828604Z"
-
Используйте JavaScript в браузере, чтобы разобрать его как UTC. Он автоматически подберет локальные настройки времени в браузере. Один из способов - использовать встроенный объект
Date
в JavaScript, например:var dt = new Date('2013-05-02T21:01:26.0828604Z');
Однако это будет работать только в новых браузерах, поддерживающих формат ISO-8601. Вместо этого я рекомендую использовать библиотеку moment.js. Он совместим с браузерами, и он лучше поддерживает даты ISO и локализацию. Кроме того, вы получаете множество других полезных функций синтаксического анализа и форматирования.
// pass the value from your server var m = moment('2013-05-02T21:01:26.0828604Z'); // use one of the formats supported by moment.js // this is locale-specific "long date time" format. var s = m.format('LLLL');
Преимущество варианта 1 заключается в том, что вы можете работать со временем в любом часовом поясе. Если вы можете запросить у пользователя свой часовой пояс из выпадающего списка, вам не нужно использовать Javascript.
Преимущество Варианта 2 состоит в том, что вы получаете браузер для выполнения некоторых работ для вас. Это лучший способ пойти, если вы отправляете необработанные данные, такие как вызов AJAX в WebAPI. Однако JavaScript знает только о UTC и локальном часовом поясе браузера. Так что это не так хорошо, если вам нужно преобразовать в другие зоны.
Вы также должны знать, что если вы выберете вариант № 2, вы можете столкнуться с недостатком в дизайне ECMAScript 5.1. Это вступает в игру, если вы работаете с датами, которые покрываются другим набором правил летнего времени, чем в настоящее время. Вы можете прочитать в этом вопросе и в моем блоге.
Было бы намного проще, если бы у нас была некоторая информация о часовом поясе в заголовках HTTP, но, к сожалению, мы этого не делаем. Это много обручей, чтобы проскочить, но это лучший способ иметь как гибкость, так и точность.