Изменить свойство 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 непосредственно в вашей модели (без разбора).