Obsługa elementów DateTime i DateTimeOffset w pliku System.Text.JsonDateTime and DateTimeOffset support in System.Text.Json

Biblioteka system. Text. JSON analizuje i zapisuje DateTime i DateTimeOffset wartości zgodnie z rozszerzonym profilem ISO 8601:-2019.The System.Text.Json library parses and writes DateTime and DateTimeOffset values according to the ISO 8601:-2019 extended profile. Konwertery zapewniają obsługę niestandardową do serializacji i deserializacji za pomocą JsonSerializer.Converters provide custom support for serializing and deserializing with JsonSerializer. Obsługę niestandardową można również zaimplementować przy użyciu Utf8JsonReader i Utf8JsonWriter.Custom support can also be implemented when using Utf8JsonReader and Utf8JsonWriter.

Obsługa formatu ISO 8601-1:2019Support for the ISO 8601-1:2019 format

Typy JsonSerializer, Utf8JsonReader, Utf8JsonWriteri JsonElement analizują i zapisują DateTime i DateTimeOffset reprezentacje tekstowe zgodnie z rozszerzonym profilem formatu ISO 8601-1:2019; na przykład 2019-07-26T16:59:57-05:00.The JsonSerializer, Utf8JsonReader, Utf8JsonWriter, and JsonElement types parse and write DateTime and DateTimeOffset text representations according to the extended profile of the ISO 8601-1:2019 format; for example, 2019-07-26T16:59:57-05:00.

DateTime i DateTimeOffset dane można serializować przy użyciu JsonSerializer:DateTime and DateTimeOffset data can be serialized with JsonSerializer:

using System;
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);
    }
}

// The example displays the following output:
// {"Name":"Banana","ExpiryDate":"2019-07-26T00:00:00"}

Można je również zdeserializować przy użyciu JsonSerializer:They can also be deserialized with JsonSerializer:

using System;
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 the following output:
// Banana
// 7/26/2019 12:00:00 AM

Z opcjami domyślnymi dane wejściowe DateTime i DateTimeOffset reprezentacje tekstowe muszą być zgodne z profilem rozszerzonego ISO 8601-1:2019.With default options, input DateTime and DateTimeOffset text representations must conform to the extended ISO 8601-1:2019 profile. Próba deserializacji reprezentacji, które nie są zgodne z profilem, spowoduje, że JsonSerializer zgłosić JsonException:Attempting to deserialize representations that don't conform to the profile will cause JsonSerializer to throw a JsonException:

using System;
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.

JsonDocument zapewnia strukturalny dostęp do zawartości ładunku JSON, w tym DateTime i DateTimeOffset reprezentacje.The JsonDocument provides structured access to the contents of a JSON payload, including DateTime and DateTimeOffset representations. W poniższym przykładzie pokazano, jak w przypadku zbierania temperatury można obliczyć średnią temperaturę w poniedziałek:The example below shows how, when given a collection of temperatures, the average temperature on Mondays can be calculated:

using System;
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

Próba obliczenia średniej temperatury danego ładunku z niezgodnymi reprezentacjami DateTime spowoduje, że JsonDocument zgłosić FormatException:Attempting to compute the average temperature given a payload with non-compliant DateTime representations will cause JsonDocument to throw a FormatException:

using System;
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 niższego poziomu zapisuje DateTime i DateTimeOffset dane:The lower level Utf8JsonWriter writes DateTime and DateTimeOffset data:

using System;
using System.IO;
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 displays the following output:
// {
//     "date": "2019-07-26T00:00:00-05:00",
//     "temp": 42
// }

Utf8JsonReader analizuje DateTime i DateTimeOffset dane:Utf8JsonReader parses DateTime and DateTimeOffset data:

using System;
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 the following output:
// True
// 7/26/2019 12:00:00 AM
// 7/26/2019 12:00:00 AM

Próba odczytania niezgodnych formatów z Utf8JsonReader spowoduje zgłoszenie FormatException:Attempting to read non-compliant formats with Utf8JsonReader will cause it to throw a FormatException:

using System;
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()

Obsługa niestandardowych DateTime i DateTimeOffsetCustom support for DateTime and DateTimeOffset

Przy użyciu JsonSerializerWhen using JsonSerializer

Jeśli chcesz, aby serializator wykonywał niestandardowe analizy lub formatowanie, możesz zaimplementować niestandardowe konwertery.If you want the serializer to perform custom parsing or formatting, you can implement custom converters. Oto kilka przykładów:Here are a few examples:

Używanie DateTime(Offset).Parse i DateTime(Offset).ToStringUsing DateTime(Offset).Parse and DateTime(Offset).ToString

Jeśli nie możesz określić formatów danych wejściowych DateTime lub DateTimeOffset reprezentacje tekstu, możesz użyć metody DateTime(Offset).Parse w logice odczytu konwertera.If you can't determine the formats of your input DateTime or DateTimeOffset text representations, you can use the DateTime(Offset).Parse method in your converter read logic. Umożliwia to korzystanie z programu. Rozległa pomoc techniczna w sieci na potrzeby analizowania różnych DateTime i DateTimeOffset formatów tekstu, w tym ciągów z niestandardem ISO 8601 i formatów ISO 8601, które nie są zgodne z rozszerzonym profilem ISO 8601-1:2019.This allows you to use .NET's extensive support for parsing various DateTime and DateTimeOffset text formats, including non-ISO 8601 strings and ISO 8601 formats that don't conform to the extended ISO 8601-1:2019 profile. Ta metoda jest znacznie mniej wydajna niż użycie natywnej implementacji serializatora.This approach is significantly less performant than using the serializer's native implementation.

Do serializacji można użyć metody DateTime(Offset).ToString w logice zapisu konwertera.For serializing, you can use the DateTime(Offset).ToString method in your converter write logic. Dzięki temu można pisać DateTime i DateTimeOffset wartości przy użyciu dowolnych standardowych formatów daty i godzinyoraz niestandardowych formatów daty i godziny.This allows you to write DateTime and DateTimeOffset values using any of the standard date and time formats, and the custom date and time formats. Jest to również znacznie mniej wydajne niż użycie natywnej implementacji serializatora.This is also significantly less performant than using the serializer's native implementation.

using System;
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());
        }

        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 the following output:
// 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"

Uwaga

Podczas implementowania JsonConverter<T>, a T jest DateTime, parametr typeToConvert będzie zawsze typeof(DateTime).When implementing JsonConverter<T>, and T is DateTime, the typeToConvert parameter will always be typeof(DateTime). Parametr jest przydatny do obsługi przypadków polimorficznych i używania typów ogólnych do uzyskiwania typeof(T) w sposób efektywny.The parameter is useful for handling polymorphic cases and when using generics to get typeof(T) in a performant way.

Używanie Utf8Parser i Utf8FormatterUsing Utf8Parser and Utf8Formatter

W logice konwertera można używać szybkich metod analizy i formatowania opartych na kodowaniu UTF-8, jeśli dane wejściowe DateTime lub DateTimeOffset są zgodne z jednym z ciągów "R", "l", "O" lub "G" standardowego formatu daty i godziny, lub chcesz pisać według jednego z tych formatów.You can use fast UTF-8-based parsing and formatting methods in your converter logic if your input DateTime or DateTimeOffset text representations are compliant with one of the "R", "l", "O", or "G" standard date and time format strings, or you want to write according to one of these formats. Jest to znacznie szybsze niż używanie DateTime(Offset).Parse i DateTime(Offset).ToString.This is much faster than using DateTime(Offset).Parse and DateTime(Offset).ToString.

W tym przykładzie przedstawiono niestandardowy konwerter, który serializować i deserializacji wartości DateTime zgodnie z formatem standardowym "R":This example shows a custom converter that serializes and deserializes DateTime values according to the "R" standard format:

using System;
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://docs.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.
            try
            {
                ParseDateTimeWithDefaultOptions();
            }
            catch (JsonException e)
            {
                Console.WriteLine(e.Message);
            }

            // Using converters gives you control over the serializers parsing and formatting.
            ProcessDateTimeWithCustomConverter();
        }
    }
}

// The example displays the following output:
// 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"

Uwaga

Standardowy format "R" będzie zawsze zawierać 29 znaków.The "R" standard format will always be 29 characters long.

Używanie DateTime(Offset).Parse jako powrotu do analizy natywnej serializatoraUsing DateTime(Offset).Parse as a fallback to the serializer's native parsing

Jeśli zwykle oczekujesz, że dane wejściowe DateTime lub DateTimeOffset są zgodne z rozszerzonym profilem ISO 8601-1:2019, możesz użyć natywnej logiki analizy serializatora.If you generally expect your input DateTime or DateTimeOffset data to conform to the extended ISO 8601-1:2019 profile, you can use the serializer's native parsing logic. Można również zaimplementować mechanizm rezerwowy tylko w przypadku.You can also implement a fallback mechanism just in case. Ten przykład pokazuje, że po niepowodzeniu analizy DateTime reprezentacji tekstowej przy użyciu TryGetDateTime(DateTime), konwerter pomyślnie przeanalizuje dane przy użyciu Parse(String).This example shows that, after failing to parse a DateTime text representation using TryGetDateTime(DateTime), the converter successfully parses the data using Parse(String).

using System;
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 the following output:
// 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"

Podczas pisania przy użyciu Utf8JsonWriterWhen writing with Utf8JsonWriter

Jeśli chcesz napisać niestandardowy DateTime lub DateTimeOffset reprezentację tekstową za pomocą Utf8JsonWriter, możesz sformatować swoją niestandardową reprezentację do String, ReadOnlySpan<Byte>, ReadOnlySpan<Char>lub JsonEncodedText, a następnie przekazać ją do odpowiedniej metody Utf8JsonWriter.WriteStringValue lub Utf8JsonWriter.WriteString.If you want to write a custom DateTime or DateTimeOffset text representation with Utf8JsonWriter, you can format your custom representation to a String, ReadOnlySpan<Byte>, ReadOnlySpan<Char>, or JsonEncodedText, then pass it to the corresponding Utf8JsonWriter.WriteStringValue or Utf8JsonWriter.WriteString method.

Poniższy przykład pokazuje, jak DateTime format niestandardowy można utworzyć za pomocą ToString(String, IFormatProvider), a następnie napisać przy użyciu metody WriteStringValue(String):The following example shows how a custom DateTime format can be created with ToString(String, IFormatProvider), then written with the WriteStringValue(String) method:

using System;
using System.Globalization;
using System.IO;
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
// }

Podczas czytania przy użyciu Utf8JsonReaderWhen reading with Utf8JsonReader

Jeśli chcesz odczytać niestandardowy DateTime lub DateTimeOffset reprezentację tekstową za pomocą Utf8JsonReader, możesz pobrać wartość bieżącego tokenu JSON jako String przy użyciu GetString(), a następnie przeanalizować wartość przy użyciu logiki niestandardowej.If you want to read a custom DateTime or DateTimeOffset text representation with Utf8JsonReader, you can get the value of the current JSON token as a String using GetString(), then parse the value using custom logic.

Poniższy przykład pokazuje, jak można pobrać niestandardową reprezentację tekstu DateTimeOffset przy użyciu GetString(), a następnie przeanalizować ją przy użyciu ParseExact(String, String, IFormatProvider):The following example shows how a custom DateTimeOffset text representation can be retrieved using GetString(), then parsed using ParseExact(String, String, IFormatProvider):

using System;
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 the following output:
// 7/26/2019 12:00:00 AM -04:00

Profil rozszerzonego ISO 8601-1:2019 w pliku System. Text. JSONThe extended ISO 8601-1:2019 profile in System.Text.Json

Składniki daty i godzinyDate and time components

Profil rozszerzonego ISO 8601-1:2019 zaimplementowany w System.Text.Json definiuje następujące składniki dla reprezentacji daty i godziny.The extended ISO 8601-1:2019 profile implemented in System.Text.Json defines the following components for date and time representations. Te składniki są używane do definiowania różnych poziomów szczegółowości, które są obsługiwane podczas analizowania i formatowania DateTime i DateTimeOffset reprezentacji.These components are used to define various levels of granularity supported when parsing and formatting DateTime and DateTimeOffset representations.

SkładnikComponent FormatFormat OpisDescription
RokYear „yyyy”"yyyy" 0001-99990001-9999
BieżącymMonth „MM”"MM" 01-1201-12
DzieńDay „dd”"dd" 01-28, 01-29, 01-30, 01-31 w oparciu o miesiąc/rok01-28, 01-29, 01-30, 01-31 based on month/year
GodzinaHour „HH”"HH" 00-2300-23
MinutaMinute „mm”"mm" 00-5900-59
SekundaSecond „ss”"ss" 00-5900-59
Druga częśćSecond fraction „FFFFFFF”"FFFFFFF" Co najmniej jedna cyfra, maksymalnie 16 cyfrMinimum of one digit, maximum of 16 digits
Przesunięcie czasuTime offset „K”"K" "Z" lub "(" + "/"-") gg": "mm"Either "Z" or "('+'/'-')HH':'mm"
Czas częściowyPartial time "Gg": "mm": "SS [FFFFFFF]""HH':'mm':'ss[FFFFFFF]" Czas bez informacji o przesunięciu czasu UTCTime without UTC offset information
Pełna DataFull date "yyyy'-'MM'-'dd""yyyy'-'MM'-'dd" Data kalendarzaCalendar date
Pełny czasFull time "Częściowe time'K""'Partial time'K" Czas UTC dnia lub lokalny dzień z przesunięciem czasu między czasem lokalnym i czasem UTCUTC of day or Local time of day with the time offset between local time and UTC
Data i godzinaDate time "" Pełna Data "t" "Pełny czas" ""'Full date''T''Full time'" Data i godzina kalendarzowa, np. 2019-07-26T16:59:57-05:00Calendar date and time of day, e.g. 2019-07-26T16:59:57-05:00

Obsługa analizySupport for parsing

Następujące poziomy szczegółowości są zdefiniowane do analizy:The following levels of granularity are defined for parsing:

  1. "Pełna Data"'Full date'

    1. "yyyy'-'MM'-'dd""yyyy'-'MM'-'dd"
  2. "" Pełna Data "t" godzina "": "minuta" ""'Full date''T''Hour'':''Minute'"

    1. "yyyy'-'MM'-'dd'T'HH": "mm""yyyy'-'MM'-'dd'T'HH':'mm"
  3. "" Pełna Data "" t "" częściowe czas """'Full date''T''Partial time'"

    1. "yyyy'-'MM'-'dd'T'HH": "mm": "SS" (specyfikator formatu sortowania ("s")"yyyy'-'MM'-'dd'T'HH':'mm':'ss" (The Sortable ("s") Format Specifier)
    2. "yyyy'-'MM'-'dd'T'HH": "mm": "SS". " FFFFFFF"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF"
  4. "" Pełna Data "" t "godzina" ":" minuta "przesunięcie czasu" ""'Full date''T''Time hour'':''Minute''Time offset'"

    1. "yyyy'-'MM'-'dd'T'HH": "mmZ""yyyy'-'MM'-'dd'T'HH':'mmZ"
    2. "yyyy'-'MM'-'dd'T'HH": "mm (" + "/"-") gg": "mm""yyyy'-'MM'-'dd'T'HH':'mm('+'/'-')HH':'mm"
  5. "Data i godzina"'Date time'

    1. "yyyy'-'MM'-'dd'T'HH": "mm": "SSS""yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
    2. "yyyy'-'MM'-'dd'T'HH": "mm": "SS". " FFFFFFFZ""yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ"
    3. "yyyy'-'MM'-'dd'T'HH": "mm": "SS" + "/"-") gg": "mm""yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"
    4. "yyyy'-'MM'-'dd'T'HH": "mm": "SS". " FFFFFFF (' + '/'-') gg ': ' mm '"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm"

Jeśli istnieją ułamki dziesiętne dla sekund, musi zawierać co najmniej jedną cyfrę; 2019-07-26T00:00:00. jest niedozwolony.If there are decimal fractions for seconds, there must be at least one digit; 2019-07-26T00:00:00. is not allowed. Gdy dozwolone są maksymalnie 16 cyfr ułamkowych, analizowane są tylko pierwsze siedem.While up to 16 fractional digits are allowed, only the first seven are parsed. Wszystko, co jest traktowane jako zero.Anything beyond that is considered a zero. Na przykład 2019-07-26T00:00:00.1234567890 zostanie przeanalizowany, jeśli jest 2019-07-26T00:00:00.1234567.For example, 2019-07-26T00:00:00.1234567890 will be parsed as if it is 2019-07-26T00:00:00.1234567. Jest to zgodne z implementacją DateTime, która jest ograniczona do tego rozwiązania.This is to stay compatible with the DateTime implementation, which is limited to this resolution.

Sekundy przestępne nie są obsługiwane.Leap seconds are not supported.

Obsługa formatowaniaSupport for formatting

Następujące poziomy szczegółowości są zdefiniowane na potrzeby formatowania:The following levels of granularity are defined for formatting:

  1. "" Pełna Data "" t "" częściowe czas """'Full date''T''Partial time'"

    1. "yyyy'-'MM'-'dd'T'HH": "mm": "SS" (specyfikator formatu sortowania ("s")"yyyy'-'MM'-'dd'T'HH':'mm':'ss" (The Sortable ("s") Format Specifier)

      Służy do formatowania DateTime bez ułamków sekund i bez informacji o przesunięciu.Used to format a DateTime without fractional seconds and without offset information.

    2. "yyyy'-'MM'-'dd'T'HH": "mm": "SS". " FFFFFFF"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF"

      Służy do formatowania DateTime za pomocą ułamków sekund, ale bez informacji o przesunięciu.Used to format a DateTime with fractional seconds but without offset information.

  2. "Data i godzina"'Date time'

    1. "yyyy'-'MM'-'dd'T'HH": "mm": "SSS""yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"

      Służy do formatowania DateTime bez ułamków sekund, ale z przesunięciem czasu UTC.Used to format a DateTime without fractional seconds but with a UTC offset.

    2. "yyyy'-'MM'-'dd'T'HH": "mm": "SS". " FFFFFFFZ""yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ"

      Służy do formatowania DateTime za pomocą ułamków sekund i przesunięcia czasu UTC.Used to format a DateTime with fractional seconds and with a UTC offset.

    3. "yyyy'-'MM'-'dd'T'HH": "mm": "SS" + "/"-") gg": "mm""yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"

      Służy do formatowania DateTime lub DateTimeOffset bez ułamków sekund, ale z przesunięciem lokalnym.Used to format a DateTime or DateTimeOffset without fractional seconds but with a local offset.

    4. "yyyy'-'MM'-'dd'T'HH": "mm": "SS". " FFFFFFF (' + '/'-') gg ': ' mm '"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm"

      Służy do formatowania DateTime lub DateTimeOffset za pomocą ułamków sekund i przesunięcia lokalnego.Used to format a DateTime or DateTimeOffset with fractional seconds and with a local offset.

Jeśli reprezentacja w formacie rundy dla DateTime lub DateTimeOffset ma końcowe zera w ułamkach sekund, wówczas JsonSerializer i Utf8JsonWriter będą formatować reprezentację wystąpienia bez końcowych zer.If the round-trip format representation of a DateTime or DateTimeOffset instance has trailing zeros in its fractional seconds, then JsonSerializer and Utf8JsonWriter will format a representation of the instance without trailing zeros. Na przykład wystąpienie DateTime, którego reprezentacja formatu rundy jest 2019-04-24T14:50:17.1010000Z, zostanie sformatowane jako 2019-04-24T14:50:17.101Z przez JsonSerializer i Utf8JsonWriter.For example, a DateTime instance whose round-trip format representation is 2019-04-24T14:50:17.1010000Z, will be formatted as 2019-04-24T14:50:17.101Z by JsonSerializer and Utf8JsonWriter.

Jeśli reprezentacja w formacie rundy DateTime lub DateTimeOffset ma wszystkie zera w ułamkach sekund, wówczas JsonSerializer i Utf8JsonWriter będą sformatować reprezentację wystąpienia bez ułamków sekund.If the round-trip format representation of a DateTime or DateTimeOffset instance has all zeros in its fractional seconds, then JsonSerializer and Utf8JsonWriter will format a representation of the instance without fractional seconds. Na przykład wystąpienie DateTime, którego reprezentacja formatu rundy jest 2019-04-24T14:50:17.0000000+02:00, zostanie sformatowane jako 2019-04-24T14:50:17+02:00 przez JsonSerializer i Utf8JsonWriter.For example, a DateTime instance whose round-trip format representation is 2019-04-24T14:50:17.0000000+02:00, will be formatted as 2019-04-24T14:50:17+02:00 by JsonSerializer and Utf8JsonWriter.

Obcinanie zer w cyfrach dziesiętnych umożliwia najmniejsze dane wyjściowe, które są konieczne, aby zachować informacje o liczbie, która ma być zapisywana.Truncating zeros in fractional-second digits allows the smallest output needed to preserve information on a round trip to be written.

Zapisywane są maksymalnie 7 cyfr dziesiętnych.A maximum of 7 fractional-second digits are written. Jest to zgodne z implementacją DateTime, która jest ograniczona do tego rozwiązania.This aligns with the DateTime implementation, which is limited to this resolution.