C#のDateTime.Nowは、日本時間とは限らない
ログの時刻や申請日時を記録するとき、C#では DateTime.Now を使うのがいちばん手軽です。ただ、DateTime.Now が返すのは「そのPCのタイムゾーンでの今」です。
社内のPCでは正しかった時刻が、クラウドのサーバに載せたら9時間ずれた
クラウドのサーバ(Azure・AWS・Linuxのコンテナなど)は、タイムゾーンがUTC(協定世界時)になっていることが多く、そのままでは日本時間より9時間前の時刻が記録されます。
本記事では、C#でPCの設定に左右されずに日本標準時(JST)を取得する方法を紹介します。自作の立替精算システムで、申請・承認の日時、通知、操作ログの時刻に使っている部品です。
立替精算システムで使ったところ

通知の画面です。「承認されました」「経理確認が完了しました」などの日時を、日本時間で表示しています。
私が自作した立替精算システムは、社内のWindows PC 1台で動かす作りですが、導入先によってはサーバのタイムゾーンが日本になっていないこともあります。また、データベースをSQLite・PostgreSQL・SQL Serverから選べるため、どこで動かしても日本時間になるようにしています。
日本時間を取る方法の比較
| 書き方 | 得られるもの | 注意 |
|---|---|---|
| DateTime.Now | PCのタイムゾーンでの今 | サーバの設定で変わる |
| DateTime.UtcNow.AddHours(9) | 日本時間の今 | 日本にはサマータイムが無いので常に正しい |
| DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(9)) | +09:00 付きの今 | 時差の情報も一緒に持てる |
| TimeZoneInfo.FindSystemTimeZoneById(…) | 指定したタイムゾーンの今 | IDがWindows(Tokyo Standard Time)とLinux(Asia/Tokyo)で違う |
TimeZoneInfo は、サマータイムのある国の時刻を扱うときには欠かせません。ただ、日本時間だけでよいなら、日本にはサマータイムが無いので「UTCに9時間を足す」だけで常に正しい時刻になります。OSのタイムゾーンの情報(LinuxではICUというライブラリ)にも頼らずに済むため、立替精算システムではこの方法にしています。
C#で日本時間(JST)を取得するサンプルコード
動作確認は Windows 11・.NET 10 です(.NET 8 以降で動きます)。Visual Studio でコンソールアプリを作り、Program.cs に貼り付けて実行してください。.NET 10 なら、ファイルに保存して dotnet run ファイル名.cs でも実行できます。
// 日本時間(JST)を取得する
Console.WriteLine($"DateTime.Now :{DateTime.Now:yyyy/MM/dd HH:mm:ss}(PC のタイムゾーンしだい)");
Console.WriteLine($"DateTime.UtcNow :{DateTime.UtcNow:yyyy/MM/dd HH:mm:ss}(世界標準時)");
Console.WriteLine($"JST(UTC+9) :{JstNow():yyyy/MM/dd HH:mm:ss}");
Console.WriteLine($"今日(JST) :{JstToday():yyyy/MM/dd}");
Console.WriteLine($"Kind :{JstNow().Kind}");
// 比較:DateTimeOffset で +09:00 付きの時刻にする
var offset = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(9));
Console.WriteLine($"DateTimeOffset :{offset:yyyy/MM/dd HH:mm:ss zzz}");
// 比較:TimeZoneInfo でタイムゾーンを探す(ID が OS によって違う)
foreach (var id in new[] { "Tokyo Standard Time", "Asia/Tokyo" })
{
try
{
var tz = TimeZoneInfo.FindSystemTimeZoneById(id);
var t = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz);
Console.WriteLine($"TimeZoneInfo({id}):{t:yyyy/MM/dd HH:mm:ss}");
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine($"TimeZoneInfo({id}):見つかりません");
}
}
/// <summary>
/// 日本時間(UTC+9)の今。日本にはサマータイムが無いので、+9 時間で常に正しい。
/// Kind は Unspecified にしておく(データベースの「タイムゾーンなし」の列にそのまま入れられる)。
/// </summary>
static DateTime JstNow() =>
DateTime.SpecifyKind(DateTime.UtcNow.AddHours(9), DateTimeKind.Unspecified);
/// <summary>日本時間の今日。</summary>
static DateOnly JstToday() => DateOnly.FromDateTime(JstNow());実行結果
DateTime.Now :2026/10/25 10:27:10(PC のタイムゾーンしだい)
DateTime.UtcNow :2026/10/25 01:27:10(世界標準時)
JST(UTC+9) :2026/10/25 10:27:10
今日(JST) :2026/10/25
Kind :Unspecified
DateTimeOffset :2026/10/25 10:27:10 +09:00
TimeZoneInfo(Tokyo Standard Time):2026/10/25 10:27:10
TimeZoneInfo(Asia/Tokyo):2026/10/25 10:27:10このPCはタイムゾーンが日本なので、DateTime.Now とJSTが同じ時刻になっています。タイムゾーンがUTCのサーバで動かすと、DateTime.Now の行だけが9時間前の時刻になり、JSTの行は変わりません。
最近の.NET(.NET 6以降)は、WindowsでもLinuxのID(Asia/Tokyo)でタイムゾーンを探せるため、この実行結果では両方とも見つかっています。ただ、動かす環境しだいで結果が変わる書き方は、できるだけ避けています。
コードの説明
DateTime.UtcNow.AddHours(9)で、世界標準時に9時間を足して日本時間にしています。DateTimeには、その時刻がUTCなのか、PCのローカル時刻なのか、どちらでもないのかを表すKindがあります。UtcNowから作るとKindはUtcのままなので、DateTime.SpecifyKind(..., DateTimeKind.Unspecified)で「タイムゾーンを持たない日本時間」にしています。- PostgreSQLの
timestamp without time zoneの列にKindがUtcの値を入れようとすると、エラーになります(Npgsql 6以降)。Unspecifiedにしておけば、そのまま保存できます。 DateOnly.FromDateTimeは、日付だけが欲しいとき(今日が何日か)に使います。
「今」を差し替えられるようにしておく
立替精算システムでは、時刻の取得をインターフェースにしています。
public interface IClock
{
/// <summary>現在日時(JST)。</summary>
DateTime Now { get; }
/// <summary>今日の日付(JST)。</summary>
DateOnly Today { get; }
}
public sealed class JstClock : IClock
{
private const int JstOffsetHours = 9;
public DateTime Now =>
DateTime.SpecifyKind(DateTime.UtcNow.AddHours(JstOffsetHours), DateTimeKind.Unspecified);
public DateOnly Today => DateOnly.FromDateTime(Now);
}ASP.NET Coreでは、Program.cs で builder.Services.AddSingleton<IClock, JstClock>(); と登録し、画面や処理は DateTime.Now を直接使わずに IClock を受け取って時刻を取ります。
こうしておくと、試験のときに「今日は2026年9月30日」のように日付を固定した時計に差し替えられます。月末・月初の締め処理や、「今月は何月か」で動きが変わる処理を確かめるときに便利です。
注意点
- PCの時計そのものがずれていると、正しい日本時間にはなりません。Windowsの「設定」→「時刻と言語」で、時刻の同期が有効になっているか確認してください。
- 海外の拠点など、日本以外の時刻も扱うシステムでは、
DateTimeOffsetやTimeZoneInfoを使ってください。 - 1つのシステムの中で
DateTime.NowとJSTが混ざると、比べたときに9時間ずれます。時刻を取る場所を1か所(IClock)にまとめておくのが安全です。
最後に
以上が、C#で日本時間(JST)を取得する方法です。
DateTime.UtcNow.AddHours(9) の1行で済みますが、時刻を取る場所を1か所にまとめておくと、サーバの設定で時刻がずれる心配がなくなり、試験もしやすくなります。
この部品を使っている立替精算システムは、こちらで紹介しています。
Pythonでインターネットの時刻サーバ(NTP)から日本時間を取得する方法は、こちらで紹介しています。




コメント