Изменить свойство DateTimeOffset.Offset?

Моя конечная цель - получить универсальное время от клиента без смещения - только время UTC. Я пытаюсь сделать это так:

Javascript: (new Date()).toUTCString(), на выходе которого записывается: Thu, 17 Mar 2016 15:13:23 GMT, что именно то, что мне нужно.

Затем я беру его на сервер и пытаюсь преобразовать в DateTimeOffset:

string dateTimeOffsetPattern = "ddd, dd MMM yyyy HH:mm:ss 'GMT'"; 

DateTimeOffset clientLoginTime = DateTimeOffset.ParseExact
    (timeStringFromClient, dateTimeOffsetPattern, CultureInfo.InvariantCulture);

Что приводит к:

3/17/2016 3:13:23 PM -04:00 

Каким-то образом он корректирует время для моего локального (восточного) смещения. Я не хочу, чтобы это произошло, я хочу, чтобы он просто возвращал время UTC, вот так:

3/17/2016 3:13:23 PM +00:00

PS Я только что задал еще один вопрос по этому поводу, и я прошу прощения, так как я чувствую, что это должно быть достаточно легко, но я не понимаю. Это должно быть действительно просто, но похоже, что у offset нет сеттера (если я не пропускаю некоторые основы C# как обычно):

public TimeSpan Offset { get; }

3 ответа

Решение

Там перегрузка ParseExact где вы можете указать DateTimeStyles , Одно из значений DateTimeValues является AssumeUniversal, который говорит:

Если формат не требует, чтобы входные данные содержали значение смещения, возвращаемому объекту DateTimeOffset присваивается смещение UTC (+00:00).

что в основном означает "не предполагайте, что это локально, предположите, что это универсально". Предполагается, что по умолчанию используется local, поэтому вы видите результат, который вы используете, и он адаптируется к local. Определение AssumeUniversal надо разобрать как хочешь.

DateTimeOffset clientLoginTime = DateTimeOffset.ParseExact
(timeStringFromClient, dateTimeOffsetPattern, CultureInfo.InvariantCulture, 
    DateTimeStyles.AssumeUniversal);

Я бы нормально проанализировал JS, а затем сделал бы следующее:

  • полоса OffSet от DateTimeOffset вернувшись DateTime
  • Задавать OffSetпутем создания другого экземпляра DateTimeOffset имеющий TimeSpan установлен в ZERO,

В твоем случае:

var clientLoginTime = new DateTimeOffset(clientLoginTime.DateTime, TimeSpan.FromHours(0));

Это может быть легко преобразовано в метод расширения

public static DateTimeOffset SetOffset(this DateTimeOffset dto, int timeZoneDiff)
{
    return new DateTimeOffset(dto.DateTime, TimeSpan.FromHours(timeZoneDiff));
}

Из JavaScript (или любого другого клиента) вы должны отправить DateTimes в формате ISO8601, который будет yyyy-MM-ddTHH-mm-ss.sssz, Z указывает, что экземпляром даты и времени является время по Гринвичу (UTC). Вы также можете изменить это, чтобы добавить + или - от GMT. Вы можете сделать это с помощью объекта JavaScript Date, используя myDate.toISOString()

При создании модели (моделей) WebAPI вы можете использовать DateTime или же DateTimeOffset вводит напрямую. Сериализатор JSON.NET для Web API автоматически десериализует отправленную строку даты-времени ISO8601 в правильный тип DateTime или DateTimeOffset (в зависимости от того, какой из них вы используете). Это означает, что вам не нужно выполнять какой-либо ручной анализ в вашем коде, что хорошо. (Представьте, если вам нужно было отправить все как строку и проанализировать все вручную во всех ваших методах?).

Так что теперь вы можете иметь метод

public async Task<IHttpActionResult> GetRecords(DateTimeOffset? startFrom)

И startFrom будет автоматически заполняться на основе отправленной строки DateTime в формате ISO8601.

Наконец, последняя и самая важная причина для этого заключается в том, что ваши клиенты, вероятно, не все будут использовать одну и ту же локаль. У вас может быть пользователь, у которого в браузере настроен испанский язык, поэтому .toUTCString() не выдаст английскую строку или, возможно, даже строку с mm/dd, но наоборот (как в большинстве стран, кроме США).

Короче говоря, для WebAPI

  • Используйте ISO8601 от / к клиенту.
  • Используйте экземпляры DateTimeOffset или DateTime непосредственно в вашей модели (без разбора).
Другие вопросы по тегам