ValueProviderResult.ConvertTo возвращает разные даты локально и в облаке - PullRequest
0 голосов
/ 03 июня 2019

У меня есть следующая пользовательская привязка модели:

public class WebApiModelBinderDateTime : IModelBinder
{
    public bool BindModel(HttpActionContext executionContext, ModelBindingContext bindingContext)
    {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (value == null)
        {
            return false;
        }

        DateTime date = (DateTime)value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture);
        date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
        bindingContext.Model = date;

        return true;
    }
}

Культура настраивается в web.config следующим образом:

<globalization culture="en-GB" enableClientBasedCulture="false" uiCulture="en-GB" />

и в global.asax так:

CultureInfo culture = CultureInfo.CreateSpecificCulture("en-GB");
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;

Проблема в том, что этот механизм связывания возвращает разные даты локально и удаленно.

Например, 2019-06-03T09:53:26.651Z будет преобразован в 2019-06-03 10:53:26 локально, но в 2019-06-03 09:53:26 в облаке (это старая система, развернутая в облачных службах Azure).

Я попытался отладитькак локально, так и удаленно, но не обнаружил различий между CultureInfo.CurrentCulture, ModelBindingContext, ValueProvider или ValueProviderResult.

Что еще может вызывать разные часовые пояса?

1 Ответ

1 голос
/ 03 июня 2019

Несколько вещей:

  • Настройки культуры и часовые пояса являются абсолютно ортогональными понятиями.Культура может повлиять на форматирование строки или применяемую календарную систему, но не влияет на часовые пояса.Они не имеют ничего общего друг с другом.

  • Вы указываете DateTimeKind.Utc, поэтому везде, где вы используете это, результирующее значение будет сериализовано с конечным Z, указывающим UTC.Если значения действительно основаны на UTC, то все в порядке и больше ничего не остается.Однако, если вы применяете их к произвольным значениям, которые могут представлять время в другом часовом поясе, установка типа UTC не поможет.Вместо этого вы можете рассмотреть возможность использования типа DateTimeOffset вместо DateTime.

  • . Вы не показали нам, как применять это связующее для модели или как вы используете API.Если предположить, что ваш API правильно доставляет результат на основе UTC (с Z), то ваша забота о часовых поясах полностью основана на интерпретации клиентским кодом.

  • Чтобы ответить прямо «Что еще может вызвать различные часовые пояса?»

    • Если вы позвоните DateTime.Now или DateTimeOffset.Now или TimeZoneInfo.Local или будете использовать DateTimeKind.Local, .ToLocalTime() и т. Д.,а также несколько API-интерфейсов, которые конвертируют из местного времени, например .ToUniversalTime(), тогда настройка часового пояса сервера (из панели управления датой и временем или на странице настроек) - это то, что контролирует этот часовой пояс.Это настройка для всего сервера для всех приложений на сервере.Вы также можете просмотреть или контролировать его с помощью tzutil.exe в командной строке.
    • Если вы следуете рекомендациям , а не , полагаясь на настройку часового пояса сервера (используя только API на основе UTC)или API, которые используют определенный часовой пояс), тогда у вас нет этой проблемы.
    • Не забывайте, что мир не все в одном часовом поясе.Таким образом, если ваш сервер выдает время в одном часовом поясе (например, в формате UTC), а ваш клиентский код либо явно, либо неявно преобразует его в другой часовой пояс (например, в местное время), то значения совершенно различны.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...