Podpora DateTime a DateTimeOffset v System.Text.Json
Knihovna System.Text.Json
analyzuje a zapisuje DateTime a DateTimeOffset hodnoty podle rozšířeného profilu ISO 8601-1:2019.
Převaděče poskytují vlastní podporu pro serializaci a deserializaci pomocí JsonSerializer. Můžete také použít Utf8JsonReader a Utf8JsonWriter implementovat vlastní podporu.
Podpora formátu ISO 8601-1:2019
JsonSerializer, Utf8JsonReader, Utf8JsonWritera JsonElement typy parsovat a zapisovat DateTime a DateTimeOffset text reprezentace podle rozšířeného profilu formátu ISO 8601-1:2019. Například 2019-07-26T16:59:57-05:00
.
DateTime a DateTimeOffset data lze serializovat pomocí 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 a DateTimeOffset lze také deserializovat pomocí 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
U výchozích možností musí vstupní DateTime a DateTimeOffset textové reprezentace odpovídat rozšířenému profilu ISO 8601-1:2019. Pokus o deserializaci reprezentací, které neodpovídají profilu, způsobí JsonSerializer vyvolání 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""}";
try
{
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.
Poskytuje JsonDocument strukturovaný přístup k obsahu datové části JSON včetně DateTime a DateTimeOffset reprezentací. Následující příklad ukazuje, jak vypočítat průměrnou teplotu v pondělí z kolekce teplot:
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
Pokus o výpočet průměrné teploty zadanou datovou částí s nekompatibilními DateTime reprezentacemi způsobí JsonDocument vyvolání 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()
Nižší úroveň Utf8JsonWriter zapisuje DateTime a DateTimeOffset data:
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 parsuje DateTime a DateTimeOffset data:
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
Pokus o čtení nekompatibilníchformátůch 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()
Serializace vlastností DateOnly a TimeOnly
S .NET 7+ System.Text.Json
podporuje serializaci a deserializaci DateOnly a TimeOnly typy. Představte si následující objekt:
sealed file record Appointment(
Guid Id,
string Description,
DateOnly Date,
TimeOnly StartTime,
TimeOnly EndTime);
Následující příklad serializuje Appointment
objekt, zobrazí výsledný JSON a pak deserializuje zpět do nové instance Appointment
typu. Nakonec se původní a nově deserializované instance porovnávají s rovností a výsledky se zapisují do konzoly:
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}
""");
V předchozím kódu:
- Vytvoří
Appointment
instanci objektuappointment
a přiřadí se k proměnné. - Instance je serializována
appointment
do FORMÁTU JSON pomocí JsonSerializer.Serialize. - Výsledný json se zapíše do konzoly.
- JSON se deserializuje zpět do nové instance
Appointment
typu pomocí JsonSerializer.Deserialize. - Původní a nově deserializované instance se porovnávají s rovností.
- Výsledek porovnání se zapíše do konzoly.
Vlastní podpora pro DateTime a DateTimeOffset
Při použití JsonSerializer
Pokud chcete, aby serializátor prováděl vlastní analýzu nebo formátování, můžete implementovat vlastní převaděče. Tady je pár příkladů:
DateTime(Offset). Parsování a DateTime(Posun) ToString
Pokud nemůžete určit formáty vstupních DateTime nebo DateTimeOffset textových reprezentací, můžete použít metodu DateTime(Offset).Parse
v logice čtení převaděče.
Tato metoda umožňuje použít . Rozsáhlá podpora analýzy různých DateTime a DateTimeOffset textových formátů, včetně řetězců jiných než ISO 8601 a formátů ISO 8601, které nevyhovují rozšířenému profilu ISO 8601-1:2019.
Tento přístup je méně výkonný než použití nativní implementace serializátoru.
Pro serializaci můžete použít metodu v logice zápisu DateTime(Offset).ToString
převaděče.
Tato metoda umožňuje psát DateTime a hodnoty pomocí libovolného standardního formátu data a DateTimeOffset času a vlastních formátů data a času.
Tento přístup je také méně výkonný než použití nativní implementace serializátoru.
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.
try
{
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"
Poznámka:
Při implementaci JsonConverter<T>a T
je DateTime, typeToConvert
parametr bude vždy typeof(DateTime)
.
Tento parametr je užitečný pro zpracování polymorfních případů a při použití obecných typů k typeof(T)
získání výkonnějšího způsobu.
Utf8Parser a Utf8Formatter
V logice převaděče můžete použít rychlé metody analýzy a formátování založené na kódování UTF-8, pokud jsou vstupní DateTime nebo DateTimeOffset textové reprezentace kompatibilní s jedním z řetězců standardního formátu data a času založených na kódování R, L nebo G nebo podle jednoho z těchto formátů. Tento přístup je mnohem rychlejší než použití DateTime(Offset).Parse
a DateTime(Offset).ToString
.
Následující příklad ukazuje vlastní převaděč, který serializuje a deserializuje DateTime hodnoty podle standardního formátu "R":
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://video2.skills-academy.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.
try
{
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"
Poznámka:
Standardní formát "R" bude vždy dlouhý 29 znaků.
Formát "l" (malými písmeny "L") není zdokumentovaný s jinými standardními řetězci formátu data a času, protože je podporovaný pouze typy Utf8Parser
a Utf8Formatter
typy. Formát je malými písmeny RFC 1123 (malá písmena ve formátu R). Například "thu, 25 jul 2019 06:36:07 gmt".
Použijte dateTime(posun). Parsovat jako záložní
Pokud obecně očekáváte, že vaše vstupy DateTime nebo DateTimeOffset data odpovídají rozšířenému profilu ISO 8601-1:2019, můžete použít nativní logiku analýzy serializátoru. Můžete také implementovat záložní mechanismus. Následující příklad ukazuje, že po selhání parsování textové reprezentace DateTime pomocí TryGetDateTime(DateTime)převaděč úspěšně parsuje data pomocí 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.
try
{
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"
Použití formátu kalendářního data unixové epochy
Následující převaděče zpracovávají formát unixové epochy s posunem časového pásma (hodnoty jako /Date(1590863400000-0700)/
/Date(1590863400000)/
nebo):
sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset s_epoch = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
static readonly Regex s_regex = new("^/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);
if (
!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(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 = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
writer.WriteStringValue(formatted);
}
}
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
static readonly DateTime s_epoch = new(1970, 1, 1, 0, 0, 0);
static readonly Regex s_regex = new("^/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);
if (
!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 = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime})/");
writer.WriteStringValue(formatted);
}
}
Při použití Utf8JsonWriter
Pokud chcete napsat vlastní DateTime nebo DateTimeOffset textovou reprezentaci pomocí Utf8JsonWriter, můžete vlastní reprezentaci naformátovat na String, ReadOnlySpan<Byte>
ReadOnlySpan<Char>
nebo JsonEncodedText, a pak ji předat odpovídající Utf8JsonWriter.WriteStringValue nebo Utf8JsonWriter.WriteString metodě.
Následující příklad ukazuje, jak lze vytvořit vlastní DateTime formát s ToString(String, IFormatProvider) metodou a pak ji WriteStringValue(String) zapsat:
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
// }
Při použití Utf8JsonReader
Pokud chcete přečíst vlastní DateTime nebo DateTimeOffset textovou reprezentaci pomocí Utf8JsonReader, můžete získat hodnotu aktuálního tokenu JSON jako metodu String pomocí GetString() metody a pak parsovat hodnotu pomocí vlastní logiky.
Následující příklad ukazuje, jak lze pomocí metody načíst GetString() vlastní DateTimeOffset textovou reprezentaci a pak analyzovat pomocí 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
Rozšířený profil ISO 8601-1:2019 v system.Text.Json
Komponenty data a času
Rozšířený profil ISO 8601-1:2019 implementovaný v System.Text.Json definici následujících součástí pro vyjádření data a času. Tyto komponenty se používají k definování různých podporovaných úrovní členitosti při analýze a formátování DateTime a DateTimeOffset reprezentaci.
Komponenta | Formát | Popis |
---|---|---|
Year | "yyyy" | 0001-9999 |
Month | "MM" | 01-12 |
Den | "dd" | 01-28, 01-29, 01-30, 01-31 na základě měsíce/roku. |
Hodina | "HH" | 00-23 |
Minuta | "mm" | 00-59 |
Second | "ss" | 00-59 |
Druhý zlomek | "FFFFFFF" | Minimálně jedna číslice, maximálně 16 číslic. |
Časový posun | "K" | Buď "Z" nebo "('+'/'-')HH':'mm". |
Částečný čas | "HH':'mm':'ss[FFFFFFF]" | Čas bez informací o posunu UTC |
Úplné datum | "yyyy'-'MM'-'dd" | Datum kalendáře. |
Plný úvazek | "'Částečný čas'K" | UTC dne nebo místního dne s časovým posunem mezi místním časem a UTC. |
Datum a čas | "Úplné datum''T'Full time'' | Datum a čas kalendáře, například 2019-07-26T16:59:57-05:00. |
Podpora analýzy
Pro parsování jsou definovány následující úrovně členitosti:
Úplné datum
- "yyyy'-'MM'-'dd"
"'Celé datum''T'Hour'':'Minute'"
- "yyyy'-'MM'-'dd'T'HH':'mm"
"Úplné datum''T'Částečný čas'"
- "yyyy'-'MM'-'dd'T'HH':'mm':'ss" (Specifikátor formátu sortable ("s")
- "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.' FFFFFFF"
"'Celé datum''T'Time hour'':'Minute'''Time offset''
- "yyyy'-'MM'-'dd'T'HH':'mmZ"
- "yyyy'-'MM'-'dd'T'HH':'mm('+'/'-')HH':'mm"
Datum a čas
- "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"
Tato úroveň členitosti je kompatibilní s DOKUMENTEM RFC 3339, široce používaným profilem ISO 8601 pro prokládání informací o datu a čase. Implementace však má několik omezení
System.Text.Json
.- RFC 3339 nezadá maximální počet desetinných číslic za sekundu, ale určuje, že alespoň jedna číslice musí následovat za tečkou, pokud je přítomen zlomek-druhý oddíl. Implementace umožňuje
System.Text.Json
až 16 číslic (pro podporu spolupráce s jinými programovacími jazyky a architekturami), ale parsuje pouze prvních sedm. Pokud při čteníDateTime
aDateTimeOffset
instancích existuje více než 16 desetinných sekund, bude vyvolán znak AJsonException. - RFC 3339 umožňuje znaky "T" a "Z" být "t" nebo "z", ale umožňuje aplikacím omezit podporu pouze na varianty velkého písmena. Implementace v
System.Text.Json
nich vyžaduje, aby byly "T" a "Z". A JsonException bude vyvolána, pokud vstupní datové části při čteníDateTime
aDateTimeOffset
instancích obsahují "t" nebo "z". - RFC 3339 určuje, že oddíly data a času jsou oddělené "T", ale umožňují aplikacím je oddělit mezerou (" ").
System.Text.Json
vyžaduje, aby oddíly data a času byly odděleny pomocí "T". Při čteníDateTime
aDateTimeOffset
instancích bude vyvolána funkce AJsonException, pokud vstupní datové části obsahují mezeru ("").
Pokud jsou desetinné zlomky pro sekundy, musí existovat alespoň jedna číslice. 2019-07-26T00:00:00.
není povolená.
I když je povoleno až 16 desetinných míst, parsuje se pouze prvních sedm. Cokoli, co je nad rámec toho, co je považováno za nulu.
Například bude analyzováno, 2019-07-26T00:00:00.1234567890
jako by to bylo 2019-07-26T00:00:00.1234567
.
Tento přístup zachovává kompatibilitu DateTime s implementací, která je omezená na toto řešení.
Přestupné sekundy nejsou podporovány.
Podpora formátování
Pro formátování jsou definovány následující úrovně podrobností:
"Úplné datum''T'Částečný čas'"
"yyyy'-'MM'-'dd'T'HH':'mm':'ss" (Specifikátor formátu sortable ("s")
Slouží k formátování DateTime bez desetinných sekund a bez informací o posunu.
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.' FFFFFFF"
Slouží k formátování DateTime s desetinnými sekundami, ale bez informací o posunu.
Datum a čas
"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
Používá se k formátování DateTime bez desetinných sekund, ale s posunem UTC.
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.' FFFFFFFZ"
Slouží k formátování DateTime s desetinnými sekundami a posunem UTC.
"yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"
Slouží k formátování DateTime desetinných sekund nebo DateTimeOffset bez, ale s místním posunem.
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.' FFFFFFF('+'/'-')HH':'mm"
Slouží k formátování DateTime desetinných DateTimeOffset sekund a místního posunu.
Tato úroveň členitosti odpovídá dokumentu RFC 3339.
Pokud reprezentace DateTime formátu odezvy nebo DateTimeOffset instance obsahuje koncové nuly v desetinných sekundách, pak JsonSerializer a Utf8JsonWriter naformátuje reprezentaci instance bez koncových nul.
Například instance, DateTime jejíž reprezentace formátu odezvy je 2019-04-24T14:50:17.1010000Z
, bude formátována jako 2019-04-24T14:50:17.101Z
a JsonSerializer Utf8JsonWriter.
Pokud reprezentace DateTime formátu odezvy nebo DateTimeOffset instance obsahuje všechny nuly v desetinných sekundách, pak JsonSerializer Utf8JsonWriter naformátuje reprezentaci instance bez desetinných sekund.
Například instance, DateTime jejíž reprezentace formátu odezvy je 2019-04-24T14:50:17.0000000+02:00
, bude formátována jako 2019-04-24T14:50:17+02:00
a JsonSerializer Utf8JsonWriter.
Zkrácení nul v desetinných číslicích a sekundách umožňuje nejmenší výstup potřebný k zachování informací o zaokrouhlené cestě.
Zapisují se maximálně sedm desetinných a druhých číslic. Toto maximum odpovídá implementaci DateTime , která je omezená na toto řešení.