C#
定石5: SQL Server datetime vs datetime2 —業務系JOIN事故の温床
出典: C# DateTime と DateTimeOffset の違い・タイムゾーン処理の正解(業務SE本番事故編) — 定石5: SQL Server datetime vs datetime2 —業務系JOIN事故の温床
// ✅定石5-b: SQL Serverから読み出したDateTimeのKindはUnspecified
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand("SELECT created_at FROM order_log WHERE id = @id", conn))
{
conn.Open();
cmd.Parameters.AddWithValue("@id", orderId);
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
DateTime dt = reader.GetDateTime(0);
Console.WriteLine($"Kind: {dt.Kind}"); // Unspecified
// ❌ NG:そのままToUniversalTime()するとLocalとみなされる
// ✅ OK: KindをUtcに固定してから扱う(DB側をUTCで保存している前提)
DateTime utcDt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
DateTime jstDt = utcDt.ToLocalTime();
}
}
}
▸ 実行ボタンで結果を表示
Source収録記事
この snippet は記事の「定石5: SQL Server datetime vs datetime2 —業務系JOIN事故の温床」セクションに登場する。コードの前後の文脈・ハマりどころの解説は記事本文で。
同じ記事から
6 件// ✅定石1: DateTime.Kindの3パターン var local = DateTime.Now; // Kind=Local var utc = DateTime.UtcNow; // Kind=Utc var unsp = new DateTime(2026, 5, 8, 14, 30, 0); // Kind=Unspecified
▶ 実行可
定石1: DateTime.Kindの3つの罠(Local / Utc / Unspecified)
#05c39f91324d
// ✅定石2:サーバー処理はUtcNow、UI表示だけNow public class OrderLog { public Guid OrderId { get; set; }未収録
定石2: DateTime.NowとDateTime.UtcNowの使い分け
#23a7f94f1fd9
// ✅定石3: DateTimeOffsetでタイムゾーン情報を持ち回る DateTimeOffset jstNow = DateTimeOffset.Now; // JST環境なら+09:00 DateTimeOffset utcNow = DateTimeOffset.UtcNow; // +00:00
▶ 実行可
定石3: DateTimeOffsetを使うべき場面
#ec04c241b5a6
// ✅定石4: TimeZoneInfoで明示的タイムゾーン変換 var utcNow = DateTime.UtcNow; // JSTに変換(.NET Framework / Windows: "Tokyo Standard Time")
▶ 実行可
定石4: TimeZoneInfo.ConvertTimeで明示的タイムゾーン変換
#0a3109479ee8
-- ✅定石5-a: datetimeとdatetime2の精度差 DECLARE @dt1 datetime = '2026-05-08 14:30:00.123'; DECLARE @dt2 datetime2 = '2026-05-08 14:30:00.123';
▶ 実行可
定石5: SQL Server datetime vs datetime2 —業務系JOIN事故の温床
#b343acd30a08
// ✅定石6: JSONシリアライズでKindを死守する using Newtonsoft.Json; using Newtonsoft.Json.Converters;未収録
定石6: JSONシリアライズでISO 8601統一
#bd2c0847de10
