У меня есть веб-приложение MVC. Я храню время UTC в базе данных. (Не datetime, а просто время). В C # Когда я извлекаю это время из базы данных, я возвращаю объект временного интервала. У меня также есть смещение в минутах. Например.
double offset = 600;
Как использовать это смещение для преобразования временного интервала в местное datetime.
Обратите внимание: я не хочу использовать метод DateTime.ToLocalTime (), потому что он будет использовать часовой пояс сервера.
UPDATE1
Я использую метод Javascript new Date().getTimezoneOffset()
для получения смещения клиента, и у меня есть значение смещения, хранящееся на сервере. Затем у меня также есть раскрывающийся список, который показывает время как 12:00, 12:30, 1:00 и т. Д. Выпадающий список привязан к свойству модели SelectedDateTime
типа DateTime
. Идея состоит в том, чтобы преобразовать время, выбранное пользователем, в UTC, а затем в UTC в местное время в зависимости от смещения. Допустим, у меня есть смещение 300 minitues
, которое будет 300/60 = 5 hours
double offset = 5.00; // this is available on the server
Когда пользователь выбирает время в раскрывающемся списке, я получаю объект datetime на сервере, игнорируя часть даты, которую я хочу сохранить в базе данных UTC. Вот как я конвертирую время в UTC.
TimeSpan utcTime = SelectedDateTime.AddHours(offset).TimeOfday;
Я сохраняю этот utcTime в базе данных. Теперь я хочу преобразовать временной интервал UTC в дату и время клиента. Я предполагаю, что сейчас у меня есть вычитание смещения
var newLocalTimeSpan = utcTime.Subtract(TimeSpan.FromHours(offset));
var newLocalDateTime = new DateTime(newLocalTimeSpan.Ticks, DateTimeKind.Local);
Однако это вызывает ошибку:
Тики должны быть между DateTime.MinValue.Ticks и DateTime.MaxValue.Ticks. \ R \ nИмя параметра: тики
Например, с дополнительными 5
часами. Если пользователь выберет 8:00 PM
, он будет преобразован в UTC и будет сохранен как 01:00:00.0000000
в базе данных. Когда я получаю значение UTC из базы данных, это «1:00:00 AM». Затем я вычитаю 5 часов из этого TimeSpan, который сейчас равен `-4 ', и если я передаю Ticks в DateTime..i получаю ошибку выше.
ПРИМЕЧАНИЯ. Если вам интересно, почему свойство модели - DateTime, а не TimeSpan, это потому, что я использую Kendo TimePicker, которому нужен тип DateTime.
ОБНОВЛЕНИЕ 2
Я очень благодарен всем за вашу помощь. Я просмотрел все статьи, опубликованные @Matt Johnson, и похоже, что мне не следует использовать смещение для расчета времени UTC. В основном из-за экономии дневного света. Но вместо этого я должен использовать часовой пояс. Итак, у меня есть 3 варианта определения часового пояса клиента:
1 ›Использование JavaScript для определения часового пояса
В JavaScript я могу сделать new Date().toString()
, который возвращает дату и время как Sun May 22 2016 02:12:36 GMT-0500 (Central Daylight Time)
. Затем я могу проанализировать строку, чтобы получить« Центральное летнее время »и отправить ее на сервер. . Однако на сервере для .net «Центральное летнее время» не является действительным идентификатором часового пояса Windows.
Вопрос
Это правильный подход? Возвращает ли JavaScript идентификатор зоны IANA? Всегда ли он будет возвращать идентификатор зоны IANA?
Если JavaScript возвращает IANA
Id, я могу использовать статью Мэтта здесь, чтобы получить идентификатор часового пояса Windows
2 ›Используйте http://momentjs.com/ для определения часового пояса клиента
Вопрос
Возвращает ли momentjs IANA
идентификатор зоны?
Если momentjs возвращает IANA
идентификатор зоны, я могу использовать статью Мэтта выше, чтобы получить идентификатор зоны Windows. Одна из причин, по которой мне не нравится этот подход, заключается в том, что мне приходится использовать две сторонние библиотеки momentjs
и Noda Time
.
3 ›Предоставьте пользователю раскрывающийся список с помощью TimeZoneInfo.GetSystemTimeZones () и позвольте пользователю выбрать часовой пояс.
Пользователь выберет время и часовой пояс, а затем на сервере я конвертирую его в UTC. используя выбранный часовой пояс и сохраните его в БД. Однако я должен показать это время на некоторых других страницах, поэтому мне снова нужен часовой пояс. Это означает, что я должен поместить раскрывающийся список в такое место в пользовательском интерфейсе, где он будет доступен все время. Нравится верхнее меню.
(Я, конечно, могу сохранить часовой пояс в БД вместе со временем, однако, если пользователь отправится в другое место, он все равно будет видеть время в первоначально выбранном часовом поясе. Что мне не нужно)
Это правильные подходы? Я что-то упускаю?
Вопрос
Предположим, что я реализую выбор часового пояса, используя один из описанных выше подходов, и у меня есть правильный часовой пояс клиента с идентификатором часового пояса Windows на сервере в некоторой переменной.
Теперь допустим, что пользователь выбирает 6:00 PM
(Центральное летнее время, UTC -5), который будет преобразован в UTC как 23:00:00. Пока мы находимся в центральном летнем времени, преобразование из UTC в местное будет отображаться в 18:00. Как только мы перейдем к Central Standard Time
, который является UTC -6, будет ли преобразование по-прежнему отображаться в 18:00 или 17:00?
Я планирую использовать метод TimeZoneInfo.ConvertFromUtc(datetimevalue, timezone)
для преобразования UTC в местное