System.Text.Json
库根据 ISO 8601-1:2019 扩展配置文件分析和写入
DateTime
和
DateTimeOffset
值。
对于使用
JsonSerializer
进行序列化和反序列化,
转换器
提供自定义支持。 还可以使用
Utf8JsonReader
和
Utf8JsonWriter
实现自定义支持。
JsonSerializer
、
Utf8JsonReader
、
Utf8JsonWriter
和
JsonElement
类型根据 ISO 8601-1:2019 格式的扩展配置文件分析和写入
DateTime
和
DateTimeOffset
文本表示形式。 例如,
2019-07-26T16:59:57-05:00
。
DateTime
和
DateTimeOffset
数据可使用
JsonSerializer
进行序列化:
using System.Text.Json;
public class Example
private class Product
public string? Name { get; set; }
public DateTime ExpiryDate { get; set; }
public static void Main(string[] args)
Product p = new Product();
p.Name = "Banana";
p.ExpiryDate = new DateTime(2019, 7, 26);
string json = JsonSerializer.Serialize(p);
Console.WriteLine(json);
// The example displays the following output:
// {"Name":"Banana","ExpiryDate":"2019-07-26T00:00:00"}
DateTime
和
DateTimeOffset
还可以使用
JsonSerializer
进行反序列化:
using System.Text.Json;
public class Example
private class Product
public string? Name { get; set; }
public DateTime ExpiryDate { get; set; }
public static void Main(string[] args)
string json = @"{""Name"":""Banana"",""ExpiryDate"":""2019-07-26T00:00:00""}";
Product p = JsonSerializer.Deserialize<Product>(json)!;
Console.WriteLine(p.Name);
Console.WriteLine(p.ExpiryDate);
// The example displays output similar to the following:
// Banana
// 7/26/2019 12:00:00 AM
使用默认选项时,输入
DateTime
和
DateTimeOffset
文本表示形式必须符合 ISO 8601-1:2019 扩展配置文件。
尝试反序列化不符合配置文件的表示形式将导致
JsonSerializer
引发
JsonException
:
using System.Text.Json;
public class Example
private class Product
public string? Name { get; set; }
public DateTime ExpiryDate { get; set; }
public static void Main(string[] args)
string json = @"{""Name"":""Banana"",""ExpiryDate"":""26/07/2019""}";
Product _ = JsonSerializer.Deserialize<Product>(json)!;
catch (JsonException e)
Console.WriteLine(e.Message);
// The example displays the following output:
// The JSON value could not be converted to System.DateTime. Path: $.ExpiryDate | LineNumber: 0 | BytePositionInLine: 42.
JsonDocument
提供对 JSON 有效负载内容的结构化访问,包括
DateTime
和
DateTimeOffset
表示形式。 以下示例演示如何通过一组温度计算周一的平均温度:
using System.Text.Json;
public class Example
private static double ComputeAverageTemperatures(string json)
JsonDocumentOptions options = new JsonDocumentOptions
AllowTrailingCommas = true
using (JsonDocument document = JsonDocument.Parse(json, options))
int sumOfAllTemperatures = 0;
int count = 0;
foreach (JsonElement element in document.RootElement.EnumerateArray())
DateTimeOffset date = element.GetProperty("date").GetDateTimeOffset();
if (date.DayOfWeek == DayOfWeek.Monday)
int temp = element.GetProperty("temp").GetInt32();
sumOfAllTemperatures += temp;
count++;
double averageTemp = (double)sumOfAllTemperatures / count;
return averageTemp;
public static void Main(string[] args)
string json =
@"[" +
@"{" +
@"""date"": ""2013-01-07T00:00:00Z""," +
@"""temp"": 23," +
@"}," +
@"{" +
@"""date"": ""2013-01-08T00:00:00Z""," +
@"""temp"": 28," +
@"}," +
@"{" +
@"""date"": ""2013-01-14T00:00:00Z""," +
@"""temp"": 8," +
@"}," +
@"]";
Console.WriteLine(ComputeAverageTemperatures(json));
// The example displays the following output:
// 15.5
假定有效负载的
DateTime
表示形式不合规,尝试计算平均温度将导致
JsonDocument
引发
FormatException
:
using System.Text.Json;
public class Example
private static double ComputeAverageTemperatures(string json)
JsonDocumentOptions options = new JsonDocumentOptions
AllowTrailingCommas = true
using (JsonDocument document = JsonDocument.Parse(json, options))
int sumOfAllTemperatures = 0;
int count = 0;
foreach (JsonElement element in document.RootElement.EnumerateArray())
DateTimeOffset date = element.GetProperty("date").GetDateTimeOffset();
if (date.DayOfWeek == DayOfWeek.Monday)
int temp = element.GetProperty("temp").GetInt32();
sumOfAllTemperatures += temp;
count++;
double averageTemp = (double)sumOfAllTemperatures / count;
return averageTemp;
public static void Main(string[] args)
// Computing the average temperatures will fail because the DateTimeOffset
// values in the payload do not conform to the extended ISO 8601-1:2019 profile.
string json =
@"[" +
@"{" +
@"""date"": ""2013/01/07 00:00:00Z""," +
@"""temp"": 23," +
@"}," +
@"{" +
@"""date"": ""2013/01/08 00:00:00Z""," +
@"""temp"": 28," +
@"}," +
@"{" +
@"""date"": ""2013/01/14 00:00:00Z""," +
@"""temp"": 8," +
@"}," +
@"]";
Console.WriteLine(ComputeAverageTemperatures(json));
// The example displays the following output:
// Unhandled exception.System.FormatException: One of the identified items was in an invalid format.
// at System.Text.Json.JsonElement.GetDateTimeOffset()
较低级别的
Utf8JsonWriter
写入
DateTime
和
DateTimeOffset
数据:
using System.Text;
using System.Text.Json;
public class Example
public static void Main(string[] args)
JsonWriterOptions options = new JsonWriterOptions
Indented = true
using (MemoryStream stream = new MemoryStream())
using (Utf8JsonWriter writer = new Utf8JsonWriter(stream, options))
writer.WriteStartObject();
writer.WriteString("date", DateTimeOffset.UtcNow);
writer.WriteNumber("temp", 42);
writer.WriteEndObject();
string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
// The example output similar to the following:
// "date": "2019-07-26T00:00:00+00:00",
// "temp": 42
Utf8JsonReader
分析
DateTime
和
DateTimeOffset
数据:
using System.Text;
using System.Text.Json;
public class Example
public static void Main(string[] args)
byte[] utf8Data = Encoding.UTF8.GetBytes(@"""2019-07-26T00:00:00""");
Utf8JsonReader json = new Utf8JsonReader(utf8Data);
while (json.Read())
if (json.TokenType == JsonTokenType.String)
Console.WriteLine(json.TryGetDateTime(out DateTime datetime));
Console.WriteLine(datetime);
Console.WriteLine(json.GetDateTime());
// The example displays output similar to the following:
// True
// 7/26/2019 12:00:00 AM
// 7/26/2019 12:00:00 AM
尝试使用
Utf8JsonReader
读取不合规的格式将导致引发
FormatException
:
using System.Text;
using System.Text.Json;
public class Example
public static void Main(string[] args)
byte[] utf8Data = Encoding.UTF8.GetBytes(@"""2019/07/26 00:00:00""");
Utf8JsonReader json = new Utf8JsonReader(utf8Data);
while (json.Read())
if (json.TokenType == JsonTokenType.String)
Console.WriteLine(json.TryGetDateTime(out DateTime datetime));
Console.WriteLine(datetime);
DateTime _ = json.GetDateTime();
// The example displays the following output:
// False
// 1/1/0001 12:00:00 AM
// Unhandled exception. System.FormatException: The JSON value is not in a supported DateTime format.
// at System.Text.Json.Utf8JsonReader.GetDateTime()
将 DateOnly 和 TimeOnly 属性序列化
在 .NET 7+ 中,
System.Text.Json
支持将
DateOnly
和
TimeOnly
类型序列化和反序列化。 请考虑以下对象:
sealed file record Appointment(
Guid Id,
string Description,
DateOnly Date,
TimeOnly StartTime,
TimeOnly EndTime);
以下示例序列化
Appointment
对象,显示生成的 JSON,然后将其反序列化为
Appointment
类型的新实例。 最后,对比原始实例与反序列化后的新实例是否相同,并将结果写入控制台:
Appointment originalAppointment = new(
Id: Guid.NewGuid(),
Description: "Take dog to veterinarian.",
Date: new DateOnly(2002, 1, 13),
StartTime: new TimeOnly(5,15),
EndTime: new TimeOnly(5, 45));
string serialized = JsonSerializer.Serialize(originalAppointment);
Console.WriteLine($"Resulting JSON: {serialized}");
Appointment deserializedAppointment =
JsonSerializer.Deserialize<Appointment>(serialized)!;
bool valuesAreTheSame = originalAppointment == deserializedAppointment;
Console.WriteLine($"""
Original record has the same values as the deserialized record: {valuesAreTheSame}
""");
在上述代码中:
将
Appointment
对象实例化并分配给
appointment
变量。
使用
JsonSerializer.Serialize
将
appointment
实例序列化为 JSON。
将生成的 JSON 写入控制台。
使用
JsonSerializer.Deserialize
将 JSON 反序列化为
Appointment
类型的新实例。
对比原始实例与反序列化后的新实例是否相同。
将对比结果写入控制台。
如果希望序列化程序执行自定义分析或格式设置,可以实现
自定义转换器
。
以下是一些示例:
使用 DateTime(Offset).Parse 和 DateTime(Offset).ToString
如果无法确定输入
DateTime
或
DateTimeOffset
文本表示形式的格式,可在转换器读取逻辑中使用
DateTime(Offset).Parse
方法。
此方法使你能够使用 .NET 的广泛支持来分析各种
DateTime
和
DateTimeOffset
文本格式,包括不符合 ISO 8601-1:2019 扩展配置文件的非 ISO 8601 字符串和 ISO 8601 格式。
与使用序列化程序的本机实现相比,此方法的性能较低。
若要序列化,可在转换器写入逻辑中使用
DateTime(Offset).ToString
方法。
此方法使你能够使用任何
标准日期和时间格式
以及
自定义日期和时间格式
来写入
DateTime
和
DateTimeOffset
值。
与使用序列化程序的本机实现相比,此方法的性能也较低。
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
namespace DateTimeConverterExamples;
public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
Debug.Assert(typeToConvert == typeof(DateTime));
return DateTime.Parse(reader.GetString() ?? string.Empty);
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
writer.WriteStringValue(value.ToString());
class Program
private static void ParseDateTimeWithDefaultOptions()
DateTime _ = JsonSerializer.Deserialize<DateTime>(@"""04-10-2008 6:30 AM""");
private static void FormatDateTimeWithDefaultOptions()
Console.WriteLine(JsonSerializer.Serialize(DateTime.Parse("04-10-2008 6:30 AM -4")));
private static void ProcessDateTimeWithCustomConverter()
JsonSerializerOptions options = new JsonSerializerOptions();
options.Converters.Add(new DateTimeConverterUsingDateTimeParse());
string testDateTimeStr = "04-10-2008 6:30 AM";
string testDateTimeJson = @"""" + testDateTimeStr + @"""";
DateTime resultDateTime = JsonSerializer.Deserialize<DateTime>(testDateTimeJson, options);
Console.WriteLine(resultDateTime);
string resultDateTimeJson = JsonSerializer.Serialize(DateTime.Parse(testDateTimeStr), options);
Console.WriteLine(Regex.Unescape(resultDateTimeJson));
static void Main(string[] args)
// Parsing non-compliant format as DateTime fails by default.
ParseDateTimeWithDefaultOptions();
catch (JsonException e)
Console.WriteLine(e.Message);
// Formatting with default options prints according to extended ISO 8601 profile.
FormatDateTimeWithDefaultOptions();
// Using converters gives you control over the serializers parsing and formatting.
ProcessDateTimeWithCustomConverter();
// The example displays output similar to the following:
// The JSON value could not be converted to System.DateTime. Path: $ | LineNumber: 0 | BytePositionInLine: 20.
// "2008-04-10T06:30:00-04:00"
// 4/10/2008 6:30:00 AM
// "4/10/2008 6:30:00 AM"
实现
JsonConverter<T>
且
T
为
DateTime
时,
typeToConvert
参数将始终为
typeof(DateTime)
。
在处理多态情况以及使用泛型以高效方式获取
typeof(T)
时,该参数非常有用。
如果输入
DateTime
或
DateTimeOffset
文本表示形式符合“R”、“l”、“O”或“G”
标准日期和时间格式字符串
之一,或者希望根据其中一种格式进行编写,可以在转换器逻辑中使用基于 UTF-8 的分析和格式设置方法。 此方法比使用
DateTime(Offset).Parse
和
DateTime(Offset).ToString
快得多。
以下示例演示自定义转换器根据
“R”标准格式
序列化和反序列化
DateTime
值:
using System.Buffers;
using System.Buffers.Text;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace DateTimeConverterExamples;
// This converter reads and writes DateTime values according to the "R" standard format specifier:
// https://learn.microsoft.com/dotnet/standard/base-types/standard-date-and-time-format-strings#the-rfc1123-r-r-format-specifier.
public class DateTimeConverterForCustomStandardFormatR : JsonConverter<DateTime>
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
Debug.Assert(typeToConvert == typeof(DateTime));
if (Utf8Parser.TryParse(reader.ValueSpan, out DateTime value, out _, 'R'))
return value;
throw new FormatException();
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
// The "R" standard format will always be 29 bytes.
Span<byte> utf8Date = new byte[29];
bool result = Utf8Formatter.TryFormat(value, utf8Date, out _, new StandardFormat('R'));
Debug.Assert(result);
writer.WriteStringValue(utf8Date);
class Program
private static void ParseDateTimeWithDefaultOptions()
DateTime _ = JsonSerializer.Deserialize<DateTime>(@"""Thu, 25 Jul 2019 13:36:07 GMT""");
private static void ProcessDateTimeWithCustomConverter()
JsonSerializerOptions options = new JsonSerializerOptions();
options.Converters.Add(new DateTimeConverterForCustomStandardFormatR());
string testDateTimeStr = "Thu, 25 Jul 2019 13:36:07 GMT";
string testDateTimeJson = @"""" + testDateTimeStr + @"""";
DateTime resultDateTime = JsonSerializer.Deserialize<DateTime>(testDateTimeJson, options);
Console.WriteLine(resultDateTime);
Console.WriteLine(JsonSerializer.Serialize(DateTime.Parse(testDateTimeStr), options));
static void Main(string[] args)
// Parsing non-compliant format as DateTime fails by default.
ParseDateTimeWithDefaultOptions();
catch (JsonException e)
Console.WriteLine(e.Message);
// Using converters gives you control over the serializers parsing and formatting.
ProcessDateTimeWithCustomConverter();
// The example displays output similar to the following:
// The JSON value could not be converted to System.DateTime.Path: $ | LineNumber: 0 | BytePositionInLine: 31.
// 7/25/2019 1:36:07 PM
// "Thu, 25 Jul 2019 09:36:07 GMT"
“R”标准格式的长度始终为 29 个字符。
“l”(“L”的小写形式)格式未记录为其他
标准日期和时间格式字符串
,因为只有
Utf8Parser
和
Utf8Formatter
类型支持该格式。 该格式为小写的 RFC 1123(“R”格式的小写版本)。 例如“thu, 25 jul 2019 06:36:07 gmt”。
使用 DateTime(Offset).Parse 作为序列化程序的本机分析的回退
如果通常希望输入
DateTime
或
DateTimeOffset
数据以符合 ISO 8601-1:2019 扩展配置文件,可以使用序列化程序的本机分析逻辑。 还可以实现回退机制。
以下示例显示在未能使用
TryGetDateTime(DateTime)
分析
DateTime
文本表示形式后,转换器使用
Parse(String)
成功分析该数据:
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
namespace DateTimeConverterExamples;
public class DateTimeConverterUsingDateTimeParseAsFallback : JsonConverter<DateTime>
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
Debug.Assert(typeToConvert == typeof(DateTime));
if (!reader.TryGetDateTime(out DateTime value))
value = DateTime.Parse(reader.GetString()!);
return value;
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
writer.WriteStringValue(value.ToString("dd/MM/yyyy"));
class Program
private static void ParseDateTimeWithDefaultOptions()
DateTime _ = JsonSerializer.Deserialize<DateTime>(@"""2019-07-16 16:45:27.4937872+00:00""");
private static void ProcessDateTimeWithCustomConverter()
JsonSerializerOptions options = new JsonSerializerOptions();
options.Converters.Add(new DateTimeConverterUsingDateTimeParseAsFallback());
string testDateTimeStr = "2019-07-16 16:45:27.4937872+00:00";
string testDateTimeJson = @"""" + testDateTimeStr + @"""";
DateTime resultDateTime = JsonSerializer.Deserialize<DateTime>(testDateTimeJson, options);
Console.WriteLine(resultDateTime);
string resultDateTimeJson = JsonSerializer.Serialize(DateTime.Parse(testDateTimeStr), options);
Console.WriteLine(Regex.Unescape(resultDateTimeJson));
static void Main(string[] args)
// Parsing non-compliant format as DateTime fails by default.
ParseDateTimeWithDefaultOptions();
catch (JsonException e)
Console.WriteLine(e.Message);
// Using converters gives you control over the serializers parsing and formatting.
ProcessDateTimeWithCustomConverter();
// The example displays output similar to the following:
// The JSON value could not be converted to System.DateTime.Path: $ | LineNumber: 0 | BytePositionInLine: 35.
// 7/16/2019 4:45:27 PM
// "16/07/2019"
以下转换器将处理 Unix epoch 格式,而无论是否带有时区偏移(
/Date(1590863400000-0700)/
或
/Date(1590863400000)/
之类的值):
sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
static readonly DateTimeOffset s_epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
static readonly Regex s_regex = new Regex("^/Date\\(([+-]*\\d+)([+-])(\\d{2})(\\d{2})\\)/$", RegexOptions.CultureInvariant);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
|| !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
|| !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
throw new JsonException();
int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
TimeSpan utcOffset = new TimeSpan(hours * sign, minutes * sign, 0);
return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
TimeSpan utcOffset = value.Offset;
string formatted = FormattableString.Invariant($"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
writer.WriteStringValue(formatted);
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
static readonly DateTime s_epoch = new DateTime(1970, 1, 1, 0, 0, 0);
static readonly Regex s_regex = new Regex("^/Date\\(([+-]*\\d+)\\)/$", RegexOptions.CultureInvariant);
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
throw new JsonException();
return s_epoch.AddMilliseconds(unixTime);
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
string formatted = FormattableString.Invariant($"/Date({unixTime})/");
writer.WriteStringValue(formatted);
如果要使用
Utf8JsonWriter
编写自定义
DateTime
或
DateTimeOffset
文本表示形式,可以将自定义表示形式的格式设置为
String
、
ReadOnlySpan<Byte>
、
ReadOnlySpan<Char>
或
JsonEncodedText
,然后将它传递给相应的
Utf8JsonWriter.WriteStringValue
或
Utf8JsonWriter.WriteString
方法。
以下示例演示如何使用
ToString(String, IFormatProvider)
创建自定义
DateTime
格式,然后如何使用
WriteStringValue(String)
方法编写该格式:
using System.Globalization;
using System.Text;
using System.Text.Json;
public class Example
public static void Main(string[] args)
var options = new JsonWriterOptions
Indented = true
using (var stream = new MemoryStream())
using (var writer = new Utf8JsonWriter(stream, options))
string dateStr = DateTime.UtcNow.ToString("F", CultureInfo.InvariantCulture);
writer.WriteStartObject();
writer.WriteString("date", dateStr);
writer.WriteNumber("temp", 42);
writer.WriteEndObject();
string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
// The example displays output similar to the following:
// "date": "Tuesday, 27 August 2019 19:21:44",
// "temp": 42
如果要使用
Utf8JsonReader
读取自定义
DateTime
或
DateTimeOffset
文本表示形式,可使用
GetString()
方法将当前 JSON 令牌的值获取为
String
,然后使用自定义逻辑分析该值。
以下示例演示如何使用
GetString()
方法检索自定义
DateTimeOffset
文本表示形式,然后使用
ParseExact(String, String, IFormatProvider)
进行分析:
using System.Globalization;
using System.Text;
using System.Text.Json;
public class Example
public static void Main(string[] args)
byte[] utf8Data = Encoding.UTF8.GetBytes(@"""Friday, 26 July 2019 00:00:00""");
var json = new Utf8JsonReader(utf8Data);
while (json.Read())
if (json.TokenType == JsonTokenType.String)
string value = json.GetString();
DateTimeOffset dto = DateTimeOffset.ParseExact(value, "F", CultureInfo.InvariantCulture);
Console.WriteLine(dto);
// The example displays output similar to the following:
// 7/26/2019 12:00:00 AM -04:00
System.Text.Json 中的 ISO 8601-1:2019 扩展配置文件
日期和时间组件
System.Text.Json
中实现的 ISO 8601-1:2019 扩展配置文件定义了日期和时间表示形式的以下组件。 这些组件用于定义在分析和格式化
DateTime
和
DateTimeOffset
表示形式时支持的各种粒度级别。
"yyyy'-'MM'-'dd'T'HH':'mm':'ss"(
可排序(“s”)格式说明符
)
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF"
“‘完整日期’‘T’‘小时’‘:’‘分钟’‘时间偏移’”
"yyyy'-'MM'-'dd'T'HH':'mmZ"
"yyyy'-'MM'-'dd'T'HH':'mm('+'/'-')HH':'mm"
‘日期时间’
"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ"
"yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm"
此粒度级别符合
RFC 3339
,这是一种广泛使用的 ISO 8601 配置文件,用于交换日期和时间信息。 但是,
System.Text.Json
实现存在一些限制。
RFC 3339 未指定秒的小数部分的最大位数,但指定如果存在秒的小数部分,则句点后面必须至少有一位数字。
System.Text.Json
中的实现允许最多 16 位数(以支持与其他编程语言和框架的互操作),但仅分析前 7 位数。 如果读取
DateTime
和
DateTimeOffset
实例时秒的小数位数超过 16 位,则会引发
JsonException
。
RFC 3339 允许“T”和“Z”字符分别为“t”或“z”,但允许应用程序仅支持大写变体。
System.Text.Json
中的实现要求它们为“T”和“Z”。 如果读取
DateTime
和
DateTimeOffset
实例时输入有效负载包含“t”或“z”,则会引发
JsonException
。
RFC 3339 指定日期和时间部分用“T”分隔,但允许应用程序用空格(“ ”)分隔它们。
System.Text.Json
要求日期和时间部分用“T”分隔。 如果读取
DateTime
和
DateTimeOffset
实例时输入有效负载包含空格(“ ”),则会引发
JsonException
。
如果秒有小数部分,则必须至少有一位数字。 不允许使用
2019-07-26T00:00:00.
。
尽管最多允许 16 个小数位数,但仅分析前 7 位数。 超出该范围的任何内容都将被视为零。
例如,
2019-07-26T00:00:00.1234567890
将按
2019-07-26T00:00:00.1234567
分析。
此方法是为了与
DateTime
实现保持兼容,该实现仅限于此解决方法。
不支持跳跃秒。
为格式设置定义了以下粒度级别:
“‘完整日期’‘T’‘部分时间’”
"yyyy'-'MM'-'dd'T'HH':'mm':'ss"(
可排序(“s”)格式说明符
)
用于格式化不含秒小数部分且不含偏移信息的
DateTime
。
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF"
用于格式化含秒小数部分但不含偏移信息的
DateTime
。
‘日期时间’
"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
用于格式化不含秒小数部分但含 UTC 偏移的
DateTime
。
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ"
用于格式化含秒小数部分且含 UTC 偏移的
DateTime
。
"yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"
用于格式化不含秒小数部分但含本地偏移的
DateTime
或
DateTimeOffset
。
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm"
用于格式化含秒小数部分且含本地偏移的
DateTime
或
DateTimeOffset
。
此粒度级别符合
RFC 3339
。
如果
DateTime
或
DateTimeOffset
实例的
往返格式
表示形式的秒小数部分的末尾有零,则
JsonSerializer
和
Utf8JsonWriter
将格式化该实例表示形式,而不在末尾使用零。
例如,其
往返格式
表示形式为
2019-04-24T14:50:17.1010000Z
的
DateTime
实例将被
JsonSerializer
和
Utf8JsonWriter
格式化为
2019-04-24T14:50:17.101Z
。
如果
DateTime
或
DateTimeOffset
实例的
往返格式
表示形式的秒小数部分全都为零,则
JsonSerializer
和
Utf8JsonWriter
将格式化该实例表示形式,而不采用秒的小数部分。
例如,其
往返格式
表示形式为
2019-04-24T14:50:17.0000000+02:00
的
DateTime
实例将被
JsonSerializer
和
Utf8JsonWriter
格式化为
2019-04-24T14:50:17+02:00
。
截断秒小数位数中的零允许写入保留往返信息所需的最小输出。
秒的小数部分最多写入七位数。 最大位数与
DateTime
实现一致,该实现仅限于此解决方法。