我们正在将 JSON 发送到由 swagger 定义的 API,该 API 某些属性是格式为 yyyy-MM-ddThh:mm:ss.000Z 的 DateTime(毫秒数必须为 3 位数字,否则在端点验证失败),有些属性是日期(无时间)属性。
我看到很多消息说使用这样的格式化程序:
var jsonSettings = new JsonSerializerSettings();
jsonSettings.DateFormatString = "yyyy-MM-ddThh:mm:ss.000Z"; //try .fffZ too
var jsonObject= Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json , setting);
但这不会将 DateTimes 转换为正确的格式,C# 如何处理仅日期类型?它似乎总是序列化为DateTime.MinValue()
下面是一个示例:
有人将 json 作为字符串发送给我,但日期和时间格式不正确,要发送到端点。我希望 swagger 类和 json 反序列化能够格式化它们,但事实并非如此。
这是招摇生成的类
public class OurSwaggerObject
{
[Newtonsoft.Json.JsonProperty("dateTimeField", Required = Newtonsoft.Json.Required.Always)]
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.RegularExpression(@"^d{4}-dd-ddTdd:dd:dd.d{3}Z$")]
public DateTime dateTimeField { get; set; }
[Newtonsoft.Json.JsonProperty("dateField", Required = Newtonsoft.Json.Required.Always)]
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.RegularExpression(@"^d{4}-dd-dd$")]
public DateTime dateField { get; set; }
}
所以我试图强迫 json 正确,但我做错了或缺少某些东西
string json = @"{ 'dateTimeField': '1995-04-07T00:00:00',
'dateField': '1995-04-07T00:00:00'
}";
/* The json we need to satisfy the swagger endpoint is:
{ 'dateTimeField': '1995-04-07T00:00:00.000Z',
'dateField': '1995-04-07'
}
*/
OurSwaggerObject deserialisedIntoObject = Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json);
string serialisedToString = Newtonsoft.Json.JsonConvert.SerializeObject(deserialisedIntoObject);
//serialisedToString= "{"dateTimeField":"1995-04-07T00:00:00","dateField":"1995-04-07T00:00:00"}"
var jsonSettings = new JsonSerializerSettings();
jsonSettings.DateFormatString = "yyyy-MM-ddThh:mm:ss.fffZ"; //this won't help much for the 'date' only field!
deserialisedIntoObject = Newtonsoft.Json.JsonConvert.DeserializeObject<OurSwaggerObject>(json,jsonSettings);
serialisedToString = Newtonsoft.Json.JsonConvert.SerializeObject(deserialisedIntoObject, jsonSettings);
//serialisedToString="{"dateTimeField":"1995-04-07T00:00:00","dateField":"1995-04-07T00:00:00"}"
正如我在评论中提到的,JSON 中没有标准的日期表示形式。ISO8601是事实上的标准,即大多数人几年前开始使用它。ISO8601不需要毫秒。如果其他端点需要它们,则违反了事实上的标准。
Json.NET 自 4.5 版以来一直在使用 IOS8601。当前的是 10.0.3。以下代码:
JsonConvert.SerializeObject(DateTime.Now)
返回
"2017-09-08T19:01:55.714942+03:00"
在我的机器上。请注意时区偏移量。这也是标准的一部分。Z
表示 UTC。
您可以指定自己的时间格式,前提是它是正确的。在这种情况下,它应该是yyyy-MM-ddTHH:mm:ss.fffZ
.请注意fff
毫秒,HH
24 小时。
以下代码
var settings=new JsonSerializerSettings{DateFormatString ="yyyy-MM-ddTHH:mm:ss.fffZ"};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);
返回
"2017-09-08T19:04:14.480Z"
格式字符串不会强制进行时区转换。您可以通过 DateTimeZoneHandling 设置告诉 Json.NET 将时间视为本地或 UTC:
var settings=new JsonSerializerSettings{
DateFormatString ="yyyy-MM-ddTH:mm:ss.fffZ",
DateTimeZoneHandling=DateTimeZoneHandling.Utc};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);
返回:
"2017-09-08T16:08:19.290Z"
更新
正如 Matt Johnson 所解释的那样,Z
只是一个文字,而K
根据DateTimeZoneHandling
设置生成Z
或偏移量。
格式字符串与 DateTimeZoneHandling.Utcyyyy-MM-ddTH:mm:ss.fffK
var settings=new JsonSerializerSettings{
DateFormatString ="yyyy-MM-ddTH:mm:ss.fffK",
DateTimeZoneHandling=DateTimeZoneHandling.Utc};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);
将返回 :
2017-09-11T9:10:08.293Z
更改为DateTimeZoneHandling.Utc
将返回
2017-09-11T12:15:12.862+03:00
顺便说一下,这是 Json.NET 的默认行为,除了强制毫秒精度。
最后,.NET还没有仅Date
类型。日期时间用于日期和日期+时间值。可以使用 DateTime.Date 属性获取 DateTime 的日期部分。您可以使用 DateTime.Today 检索当前日期。
一天中的时间由时间跨度类型表示。您可以使用 DateTime.TimeOfDay 从 DateTime 值中提取一天中的时间。 严格来说,Timespan
不是时间类型,因为它可以表示超过 24 小时。
那还是什么?
对显式日期、时间的支持正在通过 CoreFX Lab 项目提供。这包含极有可能出现在 .NET 运行时中的"实验性"功能,如 UTF8 支持、日期、字符串、Channles。其中一些已显示为单独的 NuGet 包。
可以通过复制代码或通过实验性NuGet源添加它们来使用System.Time类。
获取当前通用时间到 json 日期时间格式,反之亦然:
DateTime currentDateTime = DateTime.Now.ToUniversalTime();
var jsonDateTime = GetJSONFromUserDateTime(currentDateTime);
DateTime getDateTime = GetUserDateTimeFromJSON(jsonDateTime);
以下是两种方法:
/// <summary>
/// Convert UserDateTime({9/7/2018 8:37:20 AM}) to JSON datetime(1536309440373) format
/// </summary>
/// <param name="givenDateTime"></param>
/// <returns></returns>
public static string GetJSONFromUserDateTime(DateTime givenDateTime)
{
string jsonDateTime = string.Empty;
if (givenDateTime != null)
{
JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
jsonDateTime = JsonConvert.SerializeObject(givenDateTime, microsoftDateFormatSettings);
jsonDateTime = jsonDateTime.Replace(""\/Date(", "").Replace(")\/"", "");
}
return jsonDateTime;
}
/// <summary>
/// Convert JSON datetime(1536309440373) to user datetime({9/7/2018 8:37:20 AM})
/// </summary>
/// <param name="jsonDateTime"></param>
/// <returns></returns>
public static dynamic GetUserDateTimeFromJSON(string jsonDateTime)
{
dynamic userDateTime = null;
if (!string.IsNullOrEmpty(jsonDateTime))
{
JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
userDateTime = JsonConvert.DeserializeObject(""\/Date(" + jsonDateTime + ")\/"", microsoftDateFormatSettings);
}
return userDateTime;
}
如果像Willie Esteche一样,您希望转换一个太低的数字,那么您可能已经得到了一个Unix日期时间值。 他的解决方案确实有效,但是从.Net Framework 4.6开始,有一种更简单的方法来做事。
给定值 1500013000,首先使用 FromUnixTimeSeconds() 方法将其转换为 DateTimeOffset ,然后只需获取 DateTime 组件即可。
DateTime dt = DateTimeOffset.FromUnixTimeSeconds(1500013000).UtcDateTime;
转换回来(假设UTC)是这样执行的:
long Udt = new DateTimeOffset(dt,TimeSpan.Zero).ToUnixTimeSeconds();
就我而言,我在 vb.net 中使用此配置,它很容易转换为 c #
settings.NullValueHandling = NullValueHandling.Ignore
settings.DateTimeZoneHandling = DateTimeZoneHandling.Local
BE = JsonConvert.DeserializeObject(Of EN_BE)(str, settings)
我从 laravel API 获得此格式日期
2020-08-02T01:41:05.000000Z
我转换为与数据库相同的正确值
2020-08-01 20:41:05
你可以试试这个:
DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");