C# 日期(服务器)=> JSON 日期/时间(浏览器)=> C# 日期/时间与时间部分(服务器)问题



上下文信息:PST 时区,Asp.net 带有 WebApi 2.x 的 Mvc 旧版应用程序,该应用使用 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"。
  • 浏览器(在 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# 领域:

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# 是错误的。我已经在装有.Net Framework 4.8(528049(的Windows 7 VM上进行了测试。

更新 2:

这越来越有趣了。我在MacOS上使用.net core sdk 2.1测试了F#。

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 偏移量更改。

<rant>

我发现使用DateTime日期令人沮丧</rant>

处理问题的一种方法是在某个时候提取.Date(编辑:或new Date(orig.Year, orig.Month, orig.Day)(部分以丢失时间部分。


编辑: 回复: 评论: 这是一个可以提供帮助的黑客。最终,管道的每个元素都需要正常工作。

我发现最好的方法是使用字符串("yyyy-MM-dd"(或ints 作为 3 个部分。

最新更新