web-dev-qa-db-ja.com

JSON.NETで日付/時刻をISO 8601にシリアル化する方法

Microsoftテクノロジーを使用していない可能性のある消費者にJSONを返すWeb APIアプリケーションがあります。私のコントローラーがDateTimeプロパティを持つオブジェクトをJSONとして返すと、次の形式で日付がシリアル化されます。

2017-03-15T00:00:00-04:00

これは、消費者がISO 8601形式であると期待しているため、消費者に少し頭痛の種を与えています。一部の調査によると、JSON.NETはデフォルトでISO 8601を使用するようになっています(私は9.0.1を使用しています)。このコードを実行すると...

Clipboard.Copy(JsonConvert.SerializeObject(DateTime.Now));

...私はこれを得ます:

2017-03-15T09:10:13.8105498-04:00

ウィキペディアは、完全な日付と時刻を表すときに、これらを有効なISO 8601形式として表示します。

2017-03-15T11:45:42+00:00
2017-03-15T11:45:42Z
20170315T114542Z

ただし、上記で取得した出力は、これらのいずれにも完全には一致しません。フォーマッタで2017-03-15T11:45:42Zを使用してください。

そして、おそらく別の質問に完全に値するでしょうが、私のWeb API構成に以下の行を追加すると、最初に上に表示された日付でJSONを返し続けるため、無視されるようです:

config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter());

中心的な問題を見つけたら、Web APIの問題も解決されると思います。

18

取得している形式is ISO 8601形式(Wikipediaの「Times and Time Zone Designators」のセクションを参照)、日付がUTC時間に調整されていないように見えるため、タイムゾーンオフセットが取得されますZ Zuluタイムゾーンインジケーターではなく、日付に追加されます。

IsoDateTimeConverterには、その出力をカスタマイズするために使用できる設定があります。 DateTimeStylesAdjustToUniversalに設定すると、日付を自動的にUTCに調整できます。また、出力形式をカスタマイズして、必要に応じて小数秒を省略することもできます。デフォルトでは、コンバーターはUTC時間に調整されず、秒に使用できるのと同じ数の小数点以下の精度が含まれます。

これを試して:

IsoDateTimeConverter converter = new IsoDateTimeConverter
{
    DateTimeStyles = DateTimeStyles.AdjustToUniversal,
    DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssK"
};

config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(converter);

日付がすでにUTCであるが、それらのDateTimeKindが本来のようにUtcに設定されていない場合(たとえば、Unspecifiedである場合)、理想的には、シリアル化する前にこのインジケーターが正しく設定されるようにコードを修正する必要があります。ただし、それができない(またはしたくない)場合は、コンバーターの設定を変更して、Zインジケーターを日付形式に常に含めるように(K指定子を使用する代わりに、DateTimeKindを調べる)ことができます。日付)およびAdjustToUniversalディレクティブを削除します。

IsoDateTimeConverter converter = new IsoDateTimeConverter
{
    DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
};
27
Brian Rogers

@Brian Rogersの回答に追加して、ASP Coreの場合、Startup.cs

services.AddMvc()
  .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
  .AddJsonOptions(options =>
    options.SerializerSettings.Converters.Add(new IsoDateTimeConverter
    {
      DateTimeStyles = DateTimeStyles.AdjustToUniversal
    }));
2
Assaf S.