TimeOffset support in での DateTime と DateTimeOffset のサポートDateTime and DateTimeOffset support in System.Text.Json

ライブラリの System.Text.Jsは、 DateTime DateTimeOffset ISO 8601:-2019 拡張プロファイルに従って、との値を解析して書き込みます。The System.Text.Json library parses and writes DateTime and DateTimeOffset values according to the ISO 8601:-2019 extended profile. コンバーターは、を使用したシリアル化と逆シリアル化のためのカスタムサポートを提供 JsonSerializer します。Converters provide custom support for serializing and deserializing with JsonSerializer. およびを使用する場合は、カスタムサポートを実装することもでき Utf8JsonReader Utf8JsonWriter ます。Custom support can also be implemented when using Utf8JsonReader and Utf8JsonWriter.

ISO 8601-1:2019 形式のサポートSupport for the ISO 8601-1:2019 format

、、、およびの各型は、 JsonSerializer Utf8JsonReader Utf8JsonWriter JsonElement DateTime DateTimeOffset ISO 8601-1:2019 形式の拡張プロファイルに従って、解析および書き込みとテキスト表現を行います。たとえば、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および DateTimeOffset データは、次の方法でシリアル化でき 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);
        Console.WriteLine(json);
    }
}

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

また、次のようにして逆シリアル化することもでき 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 output similar to the following:
// Banana
// 7/26/2019 12:00:00 AM

既定のオプションでは、入力 DateTime および DateTimeOffset テキスト表現は拡張 ISO 8601-1:2019 プロファイルに準拠している必要があります。With default options, input DateTime and DateTimeOffset text representations must conform to the extended ISO 8601-1:2019 profile. プロファイルに準拠していない表現を逆シリアル化しようとすると、がスローされ JsonSerializer 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 JSON ペイロードの内容 (や表現を含む) への構造化されたアクセスを提供し DateTime DateTimeOffset ます。The JsonDocument provides structured access to the contents of a JSON payload, including DateTime and DateTimeOffset representations. 次の例では、温度のコレクションを指定した場合に、月曜日の平均温度を計算できる方法を示しています。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

準拠していない形式のペイロードで平均温度を計算しようとすると、がを DateTime JsonDocument スローし 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 書き込み DateTimeDateTimeOffset データ: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 output similar to the following:
// {
//     "date": "2019-07-26T00:00:00+00:00",
//     "temp": 42
// }

Utf8JsonReaderDateTimeとデータを解析し DateTimeOffset ます。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 output similar to the following:
// True
// 7/26/2019 12:00:00 AM
// 7/26/2019 12:00:00 AM

に準拠していない形式を読み取ろうとすると Utf8JsonReader 、がスローされ 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()

およびのカスタムサポート DateTimeDateTimeOffsetCustom support for DateTime and DateTimeOffset

使用する場合JsonSerializerWhen using JsonSerializer

シリアライザーでカスタムの解析または書式設定を実行する場合は、カスタムコンバーターを実装できます。If you want the serializer to perform custom parsing or formatting, you can implement custom converters. 次に例をいくつか示します。Here are a few examples:

およびを使用する DateTime(Offset).Parse``DateTime(Offset).ToStringUsing DateTime(Offset).Parse and DateTime(Offset).ToString

入力またはテキスト表現の形式を特定できない場合は DateTime DateTimeOffsetDateTime(Offset).Parse コンバーターの読み取りロジックでメソッドを使用できます。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. これにより、を使用できるようになります。さまざまな DateTime 形式とテキスト形式のサポート DateTimeOffset (iso 8601 以外の文字列や iso 8601 形式の拡張 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. この方法では、シリアライザーのネイティブ実装よりもパフォーマンスが大幅に低下します。This approach is significantly less performant than using the serializer's native implementation.

シリアル化の場合は、 DateTime(Offset).ToString コンバーターの書き込みロジックでメソッドを使用できます。For serializing, you can use the DateTime(Offset).ToString method in your converter write logic. これにより、 DateTime 標準の DateTimeOffset 日付と時刻の形式、およびカスタムの日付と時刻の書式を使用して、との値を書き込むことができます。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. これは、シリアライザーのネイティブ実装を使用する場合よりも、パフォーマンスが大幅に低下します。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 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) ます。When implementing JsonConverter<T>, and T is DateTime, the typeToConvert parameter will always be typeof(DateTime). パラメーターは、ポリモーフィックなケースを処理する場合や、ジェネリックを使用してパフォーマンスの高い方法を実現する場合に便利です typeof(T)The parameter is useful for handling polymorphic cases and when using generics to get typeof(T) in a performant way.

およびを使用する Utf8ParserUtf8FormatterUsing Utf8Parser and Utf8Formatter

入力 DateTime または DateTimeOffset テキスト表現が "R"、"l"、"O"、"G" のいずれかの日付/時刻書式指定文字列に準拠している場合、またはこれらの形式のいずれかに従って記述する場合は、コンバーターロジックで utf-8 ベースの高速な解析および書式指定メソッドを使用できます。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. これは、およびを使用するよりもはるかに高速です DateTime(Offset).Parse DateTime(Offset).ToStringThis is much faster than using DateTime(Offset).Parse and DateTime(Offset).ToString.

次の例は、 DateTime "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 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文字です。The "R" standard format will always be 29 characters long.

"L" (小文字の "L") 形式は、および型でのみサポートされているため、他の標準の日時書式指定文字列には記載されていません Utf8Parser Utf8FormatterThe "l" (lowercase "L") format is not documented with the other standard date and time format strings because it is supported only by the Utf8Parser and Utf8Formatter types. 形式は、小文字の RFC 1123 ("R" 形式の小文字バージョン) です。たとえば、"thu, 25 月 2019 06:36:07 gmt" のようになります。The format is lowercase RFC 1123 (a lowercase version of the "R" format), for example: "thu, 25 jul 2019 06:36:07 gmt".

DateTime(Offset).Parseシリアライザーのネイティブ解析へのフォールバックとしての使用Using DateTime(Offset).Parse as a fallback to the serializer's native parsing

通常、入力 DateTime またはデータが DateTimeOffset 拡張 ISO 8601-1:2019 プロファイルに準拠していることが予想される場合は、シリアライザーのネイティブ解析ロジックを使用できます。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. また、場合によっては、フォールバックメカニズムを実装することもできます。You can also implement a fallback mechanism just in case. この例では、を使用してテキスト表現の解析に失敗した後に、 DateTime TryGetDateTime(DateTime) コンバーターがを使用してデータを正常に解析することを示して 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 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"

書き込み時にUtf8JsonWriterWhen writing with Utf8JsonWriter

でカスタムまたはテキスト表現を記述する場合は、 DateTime DateTimeOffset Utf8JsonWriter カスタム表現を String 、、 ReadOnlySpan<Byte> 、またはに書式設定 ReadOnlySpan<Char> JsonEncodedText し、それを対応するメソッドまたはメソッドに渡すことができ Utf8JsonWriter.WriteStringValue 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.

次の例では、を使用してカスタム DateTime 書式を作成 ToString(String, IFormatProvider) し、メソッドを使用して記述する方法を示し 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
// }

読み取り時のUtf8JsonReaderWhen reading with Utf8JsonReader

を使用してカスタムまたはテキスト表現を読み取る場合は、 DateTime DateTimeOffset 現在の Utf8JsonReader JSON トークンの値をを使用して取得し String 、その値を GetString() カスタムロジックを使用して解析することができます。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.

次の例は、を使用してカスタム DateTimeOffset テキスト表現を取得し GetString() 、を使用して解析する方法を示してい 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 output similar to the following:
// 7/26/2019 12:00:00 AM -04:00

System.Text.Jsの拡張 ISO 8601-1:2019 プロファイルThe extended ISO 8601-1:2019 profile in System.Text.Json

日付と時刻のコンポーネントDate and time components

で実装されている拡張 ISO 8601-1:2019 プロファイルは、 System.Text.Json 日付と時刻の表現に関して次のコンポーネントを定義します。The extended ISO 8601-1:2019 profile implemented in System.Text.Json defines the following components for date and time representations. これらのコンポーネントは、解析と書式設定および表現の際にサポートされるさまざまな粒度レベルを定義するために使用され DateTime DateTimeOffset ます。These components are used to define various levels of granularity supported when parsing and formatting DateTime and DateTimeOffset representations.

コンポーネントComponent FormatFormat 説明Description
Year "yyyy""yyyy" 0001-99990001-9999
MonthMonth "MM""MM" 01-1201-12
日間Day "dd""dd" 01-28、01-29、01-30、01-31 (月/年)01-28, 01-29, 01-30, 01-31 based on month/year
時間Hour "HH""HH" 00-2300-23
Minute "mm""mm" 00-5900-59
Second "ss""ss" 00-5900-59
2番目の分数Second fraction "FFFFFFF""FFFFFFF" 最低1桁、最大16桁Minimum of one digit, maximum of 16 digits
時間のオフセットTime offset "K""K" "Z" または "(' + '/'-') HH ': ' mm 'Either "Z" or "('+'/'-')HH':'mm"
部分的な時間Partial time "HH ': ' mm ': ' ss [FFFFFFF]""HH':'mm':'ss[FFFFFFF]" UTC オフセット情報なしの時間Time without UTC offset information
完全な日付Full date "yyyy'-'mm'-'dd't'hh-' MM'-' dd""yyyy'-'MM'-'dd" カレンダーの日付Calendar date
フルタイムFull time "Partial time'K""'Partial time'K" 現地時刻と UTC の時差を使用した日の UTC または現地時刻UTC of day or Local time of day with the time offset between local time and UTC
日時Date time "' 完全な日付 ' ' ' ' ' ' ' は完全な時刻 '" になります。"'Full date''T''Full time'" カレンダーの日付と時刻。例: 2019-07-26T16:59:57-05:00Calendar date and time of day, e.g. 2019-07-26T16:59:57-05:00

解析のサポートSupport for parsing

解析のために次の粒度のレベルが定義されています。The following levels of granularity are defined for parsing:

  1. ' 完全な日付 ''Full date'

    1. "yyyy'-'mm'-'dd't'hh-' MM'-' dd""yyyy'-'MM'-'dd"
  2. "' Full date ' ' ' Hour ' ': ' ' Minute '""'Full date''T''Hour'':''Minute'"

    1. "yyyy'-'mm'-'dd't'hh-' MM'-' + ': ' MM '"yyyy'-'MM'-'dd'T'HH':'mm"
  3. "' 完全な日付 ' t ' ' Partial time '""'Full date''T''Partial time'"

    1. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ss ' (並べ替え可能な (" s ") 書式指定子)"yyyy'-'MM'-'dd'T'HH':'mm':'ss" (The Sortable ("s") Format Specifier)
    2. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ss '. 'FFFFFFF"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF"
  4. "' Full date ' ' ' Time Time ' ': ' ' Minute ' ' Time offset '""'Full date''T''Time hour'':''Minute''Time offset'"

    1. "yyyy'-'mm'-'dd't'hh-" MM'-' Dd' T' HH ': ' mmZ ""yyyy'-'MM'-'dd'T'HH':'mmZ"
    2. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' Hh ': ' mm (' + '/'-') HH ': ' mm '"yyyy'-'MM'-'dd'T'HH':'mm('+'/'-')HH':'mm"
  5. ' 日時 ''Date time'

    1. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ssZ '"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
    2. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ss '. 'FFFFFFFZ ""yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ"
    3. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' mm ': ' ss (' + '/'-') HH ': ' mm '"yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"
    4. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ss '. 'FFFFFFF (' + '/'-') HH ': ' mm ""yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm"

秒の小数部がある場合は、少なくとも1つの数字が必要です。2019-07-26T00:00:00.は使用できません。If there are decimal fractions for seconds, there must be at least one digit; 2019-07-26T00:00:00. is not allowed. 最大16桁の小数部を使用できますが、最初の7だけが解析されます。While up to 16 fractional digits are allowed, only the first seven are parsed. それを超えるものはゼロと見なされます。Anything beyond that is considered a zero. たとえば、はの 2019-07-26T00:00:00.1234567890 ように解析され 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. これは、 DateTime この解決に限定された実装との互換性を維持するためのものです。This is to stay compatible with the DateTime implementation, which is limited to this resolution.

うるう秒はサポートされていません。Leap seconds are not supported.

書式設定のサポートSupport for formatting

次の粒度レベルは、書式設定のために定義されています。The following levels of granularity are defined for formatting:

  1. "' 完全な日付 ' t ' ' Partial time '""'Full date''T''Partial time'"

    1. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ss ' (並べ替え可能な (" s ") 書式指定子)"yyyy'-'MM'-'dd'T'HH':'mm':'ss" (The Sortable ("s") Format Specifier)

      DateTime秒の小数部を含まない、オフセット情報を使用せずに、を書式設定するために使用します。Used to format a DateTime without fractional seconds and without offset information.

    2. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ss '. 'FFFFFFF"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF"

      DateTime秒の小数部のオフセット情報を使用せずに、を書式設定するために使用します。Used to format a DateTime with fractional seconds but without offset information.

  2. ' 日時 ''Date time'

    1. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ssZ '"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"

      秒単位ではなく、UTC オフセットを使用して、を書式設定するために使用 DateTime します。Used to format a DateTime without fractional seconds but with a UTC offset.

    2. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ss '. 'FFFFFFFZ ""yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ"

      秒の小数部を UTC オフセットで書式設定するために使用し DateTime ます。Used to format a DateTime with fractional seconds and with a UTC offset.

    3. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' mm ': ' ss (' + '/'-') HH ': ' mm '"yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"

      DateTime秒の小数部を含まない、またはローカルオフセットを使用して、またはの書式を設定するために使用 DateTimeOffset します。Used to format a DateTime or DateTimeOffset without fractional seconds but with a local offset.

    4. "yyyy'-'mm'-'dd't'hh-' MM'-' Dd' T' HH ': ' MM ': ' ss '. 'FFFFFFF (' + '/'-') HH ': ' mm ""yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm"

      DateTime秒の小数部とローカルオフセットを使用して、またはの書式を設定するために使用し DateTimeOffset ます。Used to format a DateTime or DateTimeOffset with fractional seconds and with a local offset.

またはインスタンスのラウンドトリップ形式表現の DateTime DateTimeOffset 秒の小数部に後続のゼロがある場合、 JsonSerializer とは、末尾に0を Utf8JsonWriter 付けずにインスタンスの表現を書式設定します。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. たとえば、 DateTime ラウンドトリップ形式表現がであるインスタンスは、 2019-04-24T14:50:17.1010000Z とによって書式設定され 2019-04-24T14:50:17.101Z JsonSerializer 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.

またはインスタンスのラウンドトリップ形式表現で DateTimeDateTimeOffset 秒の小数部にゼロがすべて含まれている場合、 JsonSerializerUtf8JsonWriter は秒の小数部なしでインスタンスの表現を書式設定します。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. たとえば、 DateTime ラウンドトリップ形式表現がであるインスタンスは、 2019-04-24T14:50:17.0000000+02:00 とによって書式設定され 2019-04-24T14:50:17+02:00 JsonSerializer 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.

秒の小数点以下桁数で0を切り捨てた場合、書き込まれるラウンドトリップに関する情報を保持するために必要な最小の出力が可能になります。Truncating zeros in fractional-second digits allows the smallest output needed to preserve information on a round trip to be written.

最大7桁の小数点以下桁数が書き込まれます。A maximum of 7 fractional-second digits are written. これ DateTime は、この解決に限定される実装に合わせて配置されます。This aligns with the DateTime implementation, which is limited to this resolution.