Стратегия часового пояса - PullRequest
22 голосов
/ 10 января 2012

Я создаю приложение MVC 3, в котором пользователи могут не находиться в одном и том же часовом поясе, поэтому я намеревался хранить все в UTC и конвертировать из UTC в местное время в представлениях и локальное время в UTC при отправке.

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

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

Любые предложения о том, как справиться с этим в целомстратегия?

РЕДАКТИРОВАТЬ Кажется, что все очень застряли на части "Как я могу получить часовой пояс клиента", которая, как я упоминаю в одном из комментариев, не моябеспокойство.Я в порядке с настройками пользователя, которые определяют их часовой пояс, поэтому предположим, что я уже знаю, что такое часовой пояс клиента ... это не решает мою проблему.

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

Я надеялся, что существовал более автоматизированный метод, тем более чтомодель представления строго типизирована в MVC 3. Я надеялся, что сумма магии сможет хотя бы автоматически отображаться в часовом поясе, если не обрабатывать отправку, точно так же, как формат даты или диапазон могут контролироваться атрибутом.

Так, например,

[DateRange]
Public DateTime MyDate

У меня может быть что-то вроде

[ConvertToUTC(offset)]
Public DateTime MyDate

В любом случае, я думаю, что мой единственный подход - написать пользовательскую аннотацию данных для ее отображения вчасовой пояс и переопределение для подшивки модели MVC 3, поэтому входящие даты преобразуются, если только я не хочу переносить дату в вызове метода.Поэтому, если у кого-то нет дальнейших комментариев или предложений, это будет один из этих двух вариантов, я просто удивлен, что что-то еще не существует для этого.

Если я реализую решение, я обязательно опубликуюit.

Edit 2 Как-то так http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx для MVC 3 представления и модели просмотра - это то, что я ищу.

Окончательное редактирование Я пометил ответ эпигнозиса как правильный, но у меня также есть несколько комментариев для добавления.Я нашел нечто похожее здесь: http://dalldorf.com/blog/2011/06/mvc3-timezones-1/ С реализацией получения часового пояса от клиента, поместив его в cookie для людей, которые хотят этого во второй части (ссылка ниже, так как ссылка в первой части статьи начасть 2 не работает) http://dalldorf.com/blog/2011/09/mvc3-timezones-2/

При этих подходах важно отметить, что вы ДОЛЖНЫ использовать Editfor и Displayfor, а не такие вещи, как TextForFor, поскольку только EditFor и DisplayFor используют поставщиков метаданных, используемых для передачи MVCкак отобразить свойство этого типа на модели.Если вы обращаетесь к значениям модели непосредственно в представлении (@ Model.MyDate), преобразование не будет выполняться.

Ответы [ 4 ]

4 голосов
/ 14 января 2012

Вы можете справиться с проблемой преобразования UTC в местное время пользователя, используя DisplayTemplate для всего сайта для DateTime.

Из ваших просмотров вы должны использовать @ Html.DisplayFor (n => n.MyDateTimeProperty)

Вторая проблема сложнее решить. Чтобы преобразовать локальное время пользователя в UTC, вы можете переопределить DefaultModelBinder . В частности, метод SetProperty . Вот наивная реализация, демонстрирующая суть. Он применяется только для DateTime , но может быть легко расширен до DateTime? . Затем установите его в качестве связующего по умолчанию в Global.asax

public class MyDefaultModelBinder : DefaultModelBinder
{
    protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
    {
        //special case for DateTime
        if(propertyDescriptor.PropertyType == typeof(DateTime))
        {
            if (propertyDescriptor.IsReadOnly)
            {
                return;
            }

            try
            {
                if(value != null)
                {
                    DateTime dt = (DateTime)value;
                    propertyDescriptor.SetValue(bindingContext.Model, dt.ToUniversalTime());
                }
            }
            catch (Exception ex)
            {
                string modelStateKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
                bindingContext.ModelState.AddModelError(modelStateKey, ex);
            }
        }
        else
        {
            //handles all other types
            base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
        }
    }
}
2 голосов
/ 12 января 2012

Во-первых, это в основном дубликат Как я могу определить часовой пояс веб-пользователя? , я согласен с мнением большинства там за этот ответ:

Самый популярный (== стандартный?) Способ определения часового пояса, который у меня есть увиденное вокруг просто спрашивает самого пользователя. Если ваш сайт требуется подписка, это может быть сохранено в данных профиля пользователя. Для пользователей, не являющихся пользователями, даты могут отображаться в формате UTC или GMT или некоторых других. например.

При этом наиболее распространенным подходом к автоматической установке этого значения является использование javascript's Date getTimezoneOffset (). Затем его можно отправить обратно на сервер с помощью запроса cookie или ajax и сохранить вместе с профилем пользователя, сеансом или файлом cookie.

В конечном счете, я по-прежнему считаю, что вы должны разрешить пользователям изменять этот параметр, чтобы вы могли определять не только смещение UTC, но и фактическую информацию о часовом поясе и летнем времени.

При сборе данных от пользователей должно быть достаточно преобразования в и из UTC через DateTime. DateTimeOffset отлично подходит, когда клиент управляет кодом; тем не менее, с чистым html / javascript это действительно не будет вам выгодно покупать. Более того, дополнительная информация DateTimeOffset не обязательно нужна большинству приложений, если только вы не намереваетесь отображать другим пользователям исходную информацию о часовом поясе.

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

Вы не должны зависеть от усердия в правильном форматировании даты и времени и разборе. Платформа .NET должна справиться с этим за вас, для начала посмотрите " Как: установить культуру и культуру пользовательского интерфейса для глобализации веб-страниц ASP.NET ".

Заключительное замечание

Честно говоря, это боль в шее. Мы отказались от реализации несколько лет назад и начали передавать всю информацию о дате и времени в UTC, затем мы используем Javascript для преобразования в местное время и формат отображения. Это действительно единственная рабочая модель ИМХО.

1 голос
/ 10 января 2012

Вы можете использовать что-то вроде MomentJS для отображения даты / времени.Помогает с форматированием и местным временем.

0 голосов
/ 13 января 2012

Это невозможно автоматически, вам придется выполнить некоторую ручную работу.

1 Если вы не хотите хранить часовой пояс пользователя в db

1.1 Без главной страницы: поскольку csharptest.net предложил использовать getDateTimeOffset () сценария java для получения смещения часового пояса, установить значение в cookie, написать модуль для проверки наличия cookie, если cookie отсутствует, вставить код сценария java и cookie, используя модуль.

1.2 Использование главной страницы: то же самое, но не нужно писать модуль для проверки.

2 Хранить часовой пояс пользователя в дБ (лучший и самый простой) Нет необходимости использовать JavaScript для получения часового пояса, просто конвертируйте дату и время в соответствии с часовым поясом пользователя.

...