はじめに
C# / .NET における日付・時刻の扱いは、いつもいつも悩ましいです。
これは DateTime 型を JSON シリアライズしたとき、どういう結果になるかのまとめです。
環境
- .NET 8.0.45
- Microsoft.AspNetCore.Mvc.NewtonsoftJson 8.0.12
Newtonsoft.Json の設定は、以下のようにしました。
- 書式: ISO-8601
- 付与するタイムゾーン: UTC
TL;DR;
2025年6月4日12時00分をJSONシリアライズした結果です。
シリアライズ時になんからの変換が入ることはなく、元のDateTimeインスタンスを値そのままになりました。
システムタイムゾーン | 指定したDateTimeKind | 結果 |
---|---|---|
UTC | Unspecified | "2025-06-04T12:00:00Z" |
UTC | UTC | "2025-06-04T12:00:00Z" |
UTC | Local | "2025-06-04T12:00:00Z" |
Asia/Kamchatka | Unspecifed | "2025-06-04T12:00:00Z" |
Asia/Kamchatka | UTC | "2025-06-04T12:00:00Z" |
Asia/Kamchatka | Local | "2025-06-04T00:00:00Z" |
Asia/Kamchatka(カムチャッカ)は、UTC+12:00 となるタイムゾーンです。
検証に使ったコード
Program.cs
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services
.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
});
var app = builder.Build();
app.MapControllers();
app.Run();
[ApiController]
[Route("/")]
public class HomeController : ControllerBase
{
[HttpGet]
public IActionResult Index() => Ok(new
{
TimeZone = TimeZoneInfo.Local.ToString(),
DateTime = new DateTime(2025, 6, 4, 12, 0, 0),
DateTimeInUtc = new DateTime(2025, 6, 4, 12, 0, 0, DateTimeKind.Utc),
DateTimeInLocal = new DateTime(2025, 6, 4, 12, 0, 0, DateTimeKind.Local),
});
}