.NET FrameworkでUNIX時間を扱う方法、またUNIX時間とDateTime型DateTimeOffset型を相互に変換する方法について。

§1 .NET Framework 4.6以降

DateTimeOffset構造体のメソッドToUnixTimeSecondsおよびFromUnixTimeSecondsを使うことにより、DateTimeOffsetで表される時間とUNIX時間を相互に変換することができる。

using System;

class Sample {
  static void Main()
  {
    // DateTimeOffsetからUNIX時間への変換
    var dto = new DateTimeOffset(2009, 02, 13, 23, 31, 30, new TimeSpan(+00, 00, 00));

    Console.WriteLine(dto.ToUnixTimeSeconds());

    // 2038-01-19T03:14:07+00:00をUNIX時間に変換
    Console.WriteLine((new DateTimeOffset(2038, 01, 19, 03, 14, 07, new TimeSpan(+00, 00, 00))).ToUnixTimeSeconds());

    // 2038-01-19T12:14:07+09:00をUNIX時間に変換
    Console.WriteLine((new DateTimeOffset(2038, 01, 19, 12, 14, 07, new TimeSpan(+09, 00, 00))).ToUnixTimeSeconds());

    Console.WriteLine();



    // UNIX時間からDateTimeOffsetへの変換
    Console.WriteLine(DateTimeOffset.FromUnixTimeSeconds(1000000000L));

    // UNIX時間からローカル時間に変換
    Console.WriteLine(DateTimeOffset.FromUnixTimeSeconds(1000000000L).ToLocalTime());

    // 64ビット符号付き整数の最大値を変換
    Console.WriteLine(DateTimeOffset.FromUnixTimeSeconds((long)int.MaxValue));
    Console.WriteLine(DateTimeOffset.FromUnixTimeSeconds((long)int.MaxValue).ToLocalTime());
  }
}
出力例
1234567890
2147483647
2147483647

2001/09/09 1:46:40 +00:00
2001/09/09 10:46:40 +09:00
2038/01/19 3:14:07 +00:00
2038/01/19 12:14:07 +09:00

FromUnixTimeSecondsメソッドは指定されたUNIX時間をUTC(世界協定時)と解釈する。 戻り値として返されるDateTimeOffsetのOffsetプロパティも+00:00となる。 このため、UNIX時間をローカル時間に変換したい場合は、FromUnixTimeSecondsメソッドで得られたDateTimeOffsetに対してToLocalTimeメソッドを呼び出すことによってローカル時間に変換する必要がある。

FromUnixTimeSecondsメソッドでは、64ビット整数で表されるUNIX時間を扱うことができる。 そのため2038年以降の日時を表すUNIX時間を扱うこともできるが、一方DateTimeOffsetで扱える範囲外の日時へ変換しようとした場合は例外ArgumentOutOfRangeExceptionがスローされる。 (DateTimeOffsetで扱える日時の最大値・最小値: 型の種類・サイズ・精度・値域 §.型のサイズ・精度と値域)

ミリ秒単位のUNIX時間を扱いたい場合は、ToUnixTimeMillisecondsおよびFromUnixTimeMillisecondsを使うことができる。

なおDateTime構造体にはこのようなUNIX時間との相互変換を行うメソッドは用意されていない。

§2 .NET Framework 4.5以前

上記のようなメソッドが用意されないため、独自に変換処理を実装する必要がある。

§2.1 変換方法と実装

UNIX時間は「unix epoch(UTCでの1970年1月1日 午前0時00分00秒)からの経過秒数」と定義される。 そのため、unix epochの日時を設定したDateTime型インスタンスを用意しておき、それに対してUNIX時間の値を秒数として足す(DateTime.AddSeconds)ことでDateTime型の値に変換することができる。

同様にDateTime型からUNIX時間を求めるには、DateTime.ToUniversalTimeメソッド時刻をUTCに変換してからunix epochとの差をとり(DateTime.Subtract)、その差を秒数として取得することでUNIX時間に変換することができる。

using System;

public class UnixTime {
  // unix epochをDateTimeで表した定数
  public readonly static DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

  // DateTimeをUNIX時間に変換するメソッド
  public static long ToUnixTime(DateTime dateTime)
  {
    // 時刻をUTCに変換
    dateTime = dateTime.ToUniversalTime();

    // unix epochからの経過秒数を求める
    return (long)dateTime.Subtract(UnixEpoch).TotalSeconds;
  }

  // UNIX時間からDateTimeに変換するメソッド
  public static DateTime FromUnixTime(long unixTime)
  {
    // unix epochからunixTime秒だけ経過した時刻を求める
    return UnixEpoch.AddSeconds(unixTime);
  }

  static void Main()
  {
    Console.WriteLine(ToUnixTime(new DateTime(2009, 02, 13, 23, 31, 30, DateTimeKind.Utc)));
    Console.WriteLine(ToUnixTime(new DateTime(2038, 01, 19, 03, 14, 07, DateTimeKind.Utc)));
    Console.WriteLine(ToUnixTime(new DateTime(2038, 01, 19, 12, 14, 07, DateTimeKind.Local)));
    Console.WriteLine();

    Console.WriteLine(FromUnixTime(1000000000));
    Console.WriteLine(FromUnixTime(1000000000).ToLocalTime());
    Console.WriteLine(FromUnixTime(int.MaxValue));
    Console.WriteLine(FromUnixTime(int.MaxValue).ToLocalTime());
  }
}
出力例
1234567890
2147483647
2147483647

2001/09/09 1:46:40
2001/09/09 10:46:40
2038/01/19 3:14:07
2038/01/19 12:14:07

上記サンプルの注意点など。

  1. 上記のFromUnixTimeメソッドは、UNIX時刻をUTCでのDateTimeとして返す点に注意。 結果をローカル時刻に変換するにはToLocalTimeメソッドを使う必要がある。 DateTimeとUTC・ローカル時刻の扱いについては時刻の種類・UTCとの時差・タイムゾーン間の変換を参照。
  2. DateTime型の最小値(System.DateTime.MinValue)は「0001年1月1日 午前0時00分00秒」となっている。 したがってDateTimeはunix epochよりも前の日時を表せるため、上記のToUnixTimeメソッドでDateTimeを変換すると負のUNIX時間を返す可能性がある点に注意。
  3. DateTime型の最大値(System.DateTime.MaxValue)は「9999年12月31日の 23時59分59秒9999999」となっている。 したがってこの日時より先の日時を表すUNIX時間を上記のFromUnixTimeメソッドでDateTimeに変換しようとすると、AddSecondsメソッドがArgumentOutOfRangeExceptionをスローする点に注意。
  4. DateTimeOffset型をUNIX時間に変換したい場合は、上記のメソッドにDateTimeOffset.UtcDateTimeプロパティの値を渡す。 このプロパティは、DateTimeOffsetが表す日時をUTCに変換したDateTimeとして返す。

§3 参考情報

§3.1 現在時刻

現在時刻 (現地時間)
現在時刻 (UTC)
UNIX時間

§3.2 UNIX時間→現在時刻

UNIX時間
現地時間
-
UTC
-