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

Стратегия часовых поясов

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

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

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

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

ИЗМЕНИТЬ Все кажутся очень зацикленными на "как мне получить клиентский часовой пояс", что, как я упоминаю в одном из комментариев, не вызывает беспокойства. Я в порядке с настройкой пользователя, которая определяет их часовой пояс, поэтому предположим, что я уже знаю, что такое часовой пояс клиента..., который не затрагивает мою проблему.

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

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

Так нравится

[DateRange]
Public DateTime MyDate

Я мог бы что-то вроде

[ConvertToUTC(offset)]
Public DateTime MyDate

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

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

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

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

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

4b9b3361

Ответ 1

Вы можете справиться с проблемой преобразования 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

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

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

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

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

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

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

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

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

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

Ответ 3

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

Ответ 4

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

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

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

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

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