C # Дата (сервер) => Json дата / время (браузер) => C # дата / время с временной частью (сервер) проблема - PullRequest
0 голосов
/ 12 октября 2019

Контекстная информация: часовой пояс PST, устаревшее приложение Asp.net Mvc с WebApi 2.x, которое использует json.net для сериализации / десериализации в браузеры json, Chrome / FF. Приложение настроено с:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Unspecified;

Тестер сообщил о проблеме, связанной с этой датой: 1977-04-15. Вот поток:

  • C # 1977-04-15 => Сериализуется в json как "1977-04-15T00: 00: 00" из-за использования Unspecified.
  • В браузере (в часовом поясе PST) это анализируется как:
var dt = new Date("1977-04-15T00:00:00")
dt
Output: Date Fri Apr 15 1977 00:00:00 GMT-0800 (Pacific Standard Time)
  • Сериализация обратно в службу C # WebApi:
JSON.stringify(dt);
Output: "\"1977-04-15T08:00:00.000Z\""
  • В мире C # это становится (я использовал linqpad):
Console.WriteLine(DateTime.Parse("1977-04-15T08:00:00.000Z"));
Output: 1977-04-15 01:00:00

Похоже, что C # использовал другое смещение, чем браузер для часового пояса PST в тот момент. свидание. Я проверил это в FF & Chrome. Это нормально?

Как лучше всего это исправить?

Один из способов настроить DateTimeZoneHandling на Newtonsoft.Json.DateTimeZoneHandling.Local, но я не хочу делать это насуществующее приложение.

Если я использую локальное, у меня есть:

c #:

var date = new DateTime(1977, 04, 15); //, 0, 0, 0, DateTimeKind.Local);

JsonSerializerSettings settings = new JsonSerializerSettings
{
  DateTimeZoneHandling = DateTimeZoneHandling.Local
};
Console.WriteLine(JsonConvert.SerializeObject(date, settings));
Ouput: "1977-04-15T00:00:00-07:00"

В земле Javascript:

"1977-04-15T00:00:00-07:00"
dt
Output: Date Thu Apr 14 1977 23:00:00 GMT-0800 (Pacific Standard Time)
JSON.stringify(dt)
Output: "\"1977-04-15T07:00:00.000Z\""

Назад вC # land:

Console.WriteLine(DateTime.Parse("1977-04-15T07:00:00.000Z"));
Output:1977-04-15 00:00:00

Это похоже на работу, даты совпадают.

Обновление:

После дополнительного тестирования мы имеем в C # (linqpad):


var date = new DateTime(1977, 04, 03, 0, 0, 0, DateTimeKind.Local);
date.ToLongDateString().Dump();
date.ToUniversalTime().Dump();
date = new DateTime(1977, 04, 04, 0, 0, 0, DateTimeKind.Local);
date.ToLongDateString().Dump();
date.ToUniversalTime().Dump();
Output:
Sunday, April 03, 1977
1977-04-03 08:00:00
Monday, April 04, 1977
1977-04-04 07:00:00

В то время как в JavaScript (FF) мы имеем:

var dt = new Date(1977, 3, 24); 
dt.toGMTString()
var dt = new Date(1977, 3, 25); 
dt.toGMTString()
Output:
"Sun, 24 Apr 1977 08:00:00 GMT"
"Mon, 25 Apr 1977 07:00:00 GMT"

Кажется, есть несоответствие во временных таблицах DST.

Меня интересовало мир Java, поэтому я запустил это в scala:

scala> ZonedDateTime.of(1977, 4, 24, 0, 0, 0, 0, ZoneId.of(ZoneId.SHORT_IDS.get("PST")))
res8: java.time.ZonedDateTime = 1977-04-24T00:00-08:00[America/Los_Angeles]

scala> ZonedDateTime.of(1977, 4, 25, 0, 0, 0, 0, ZoneId.of(ZoneId.SHORT_IDS.get("PST")))
res9: java.time.ZonedDateTime = 1977-04-25T00:00-07:00[America/Los_Angeles]

Похоже, C # не так,Я проверил на виртуальной машине Windows 7 с .Net Framework 4.8 (528049).

Обновление 2:

Это становится интересным. Я тестировал F # на MacO с .net core sdk 2.1.

    let mutable dt = System.DateTime(1977, 04, 24, 0, 0, 0, System.DateTimeKind.Local)
    printfn "%s" (dt.ToLongDateString())
    printfn "%A" (dt.ToUniversalTime())
    let dt = System.DateTime(1977, 04, 25, 0, 0, 0, System.DateTimeKind.Local)
    printfn "%s" (dt.ToLongDateString())
    printfn "%A" (dt.ToUniversalTime())
Output:
Sunday, April 24, 1977
4/24/77 8:00:00 AM
Monday, April 25, 1977
4/25/77 7:00:00 AM

Обратите внимание на изменение смещения DST.

1 Ответ

0 голосов
/ 12 октября 2019

<rant> Я обнаружил, что использование DateTime для дат расстраивает </rant>

Один из способов справиться с вашей проблемой - извлечь часть .Date (EDIT: или new Date(orig.Year, orig.Month, orig.Day)) в некоторых случаях. указать потерять часть времени.


Редактировать: re: comments: Это хак, который может помочь. В конечном итоге каждый элемент конвейера должен работать правильно.

Я считаю, что лучший способ - использовать либо строку ("гггг-ММ-дд"), либо int s для трех частей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...