DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DateTimeの代わりにDateTimeOffsetを使用する

ここではSystem.DateTime構造体と比較することによって、System.DateTimeOffset構造体の使い方を説明します。DateTime構造体については説明しませんので、DateTime構造体に関する基本的な知識がないという方は、「指定した日時のDateTimeオブジェクトを作成する」や「日時(DateTimeオブジェクト)の情報を取得する」をご覧ください。

DateTimeとDateTimeOffsetの違い

DateTimeOffset構造体は.NET Framework 2.0 SP1から追加された型で、DateTime構造体と同様に日時を表す型です。DateTimeとの違いは、DateTimeOffsetがUTC(世界協定時刻)との時差(オフセット)をOffsetプロパティに保持している点です。その代わりにDateTimeがKindプロパティとして保持している情報は持っていません。

例えばDateTimeOffsetが表現している日時がUTCの場合、Offsetプロパティは 00:00:00 です。日本時間の場合、Offsetプロパティは 09:00:00 です。

DateTimeオブジェクトのKindプロパティがUtcの時は、そのDateTimeオブジェクトが表している日時は明確です。しかしKindプロパティがLocalやUnspecifiedの時は、一体どこのタイムゾーンの時刻なのか分かりませんので、そのDateTimeオブジェクトが表している日時は不明確です。

DateTimeOffsetは、この問題を解消します。DateTimeOffsetはUTCとのオフセットを保持していますので、DateTimeOffsetオブジェクトが表現している日時が現地時間(ローカル時刻)だとしても、明確な日時を示すことができます。つまり、現地時間を表現する時、明確な日時を表現できるのがDateTimeOffsetです。

ただし、DateTimeOffsetはUTCとの時差を保持しているだけで、タイムゾーンの情報は持っていませんので、サマータイムのように特定の時期だけ時差が変わってしまうケースにまでは対応していません。

DateTimeOffsetオブジェクトを作成する

DateTimeOffsetオブジェクトを作成する方法は、「指定した日時のDateTimeオブジェクトを作成する」で説明しているDateTimeの方法とほぼ同じです。ここでは主な方法を幾つか紹介します。

コンストラクタを呼び出す

コンストラクタを呼び出してDateTimeOffsetオブジェクトを作成する場合、UTCとのオフセットをTimeSpanで指定しなければならない点がDateTimeと異なります。なおTimeSpanについては、「TimeSpanオブジェクトを作成する、情報を取得する」で説明しています。

VB.NET
コードを隠すコードを選択
'2000年8月1日 13時30分00秒 +9時間 を表すDateTimeOffsetオブジェクトを作成する
Dim dto1 As New DateTimeOffset(2000, 8, 1, 13, 30, 0, New TimeSpan(9, 0, 0))
C#
コードを隠すコードを選択
//2000年8月1日 13時30分00秒 +9時間 を表すDateTimeOffsetオブジェクトを作成する
DateTimeOffset dto1 = new DateTimeOffset(2000, 8, 1, 13, 30, 0, new TimeSpan(9, 0, 0));

DateTimeオブジェクトから作成する

既存のDateTimeオブジェクトからDateTimeOffsetオブジェクトを作成することもできます。この場合はオフセットを指定しなくてもOKです。オフセットを指定しなかった場合、DateTimeのKindプロパティがUtcならばオフセットが0になり、それ以外ならばオフセットがローカルコンピュータのタイムゾーンのオフセット(日本の場合は、+9時間)になります。

DateTimeのKindプロパティがUnspecifiedの時は、オフセットに自由な値を指定することもできます。

VB.NET
コードを隠すコードを選択
Dim dtUtc As New DateTime(2000, 9, 24, 15, 30, 0, DateTimeKind.Utc)
Dim dtLocal As New DateTime(2000, 9, 24, 15, 30, 0, DateTimeKind.Local)

'KindがUtcのDateTimeからDateTimeOffsetオブジェクトを作成する
Dim dto4 As New DateTimeOffset(dtUtc)
'2000/09/24 15:30:00 +00:00

'KindがLocalのDateTimeからDateTimeOffsetオブジェクトを作成する
Dim dto5 As New DateTimeOffset(dtLocal)
'2000/09/24 15:30:00 +09:00

'オフセットを指定してDateTimeOffsetオブジェクトを作成する
'KindがUtcのDateTimeの時はオフセットが0でなければならないので、例外が発生する
'Dim dto6 As New DateTimeOffset(dtUtc, New TimeSpan(-5, 0, 0))

'KindをUnspecifiedに変換すれば、自由なオフセットを指定できる
Dim dtUnspecified As DateTime = DateTime.SpecifyKind(dtUtc, DateTimeKind.Unspecified)
Dim dto7 As New DateTimeOffset(dtUnspecified, New TimeSpan(-5, 0, 0))
'2000/09/24 15:30:00 -05:00
C#
コードを隠すコードを選択
DateTime dtUtc = new DateTime(2000, 9, 24, 15, 30, 0, DateTimeKind.Utc);
DateTime dtLocal = new DateTime(2000, 9, 24, 15, 30, 0, DateTimeKind.Local);

//KindがUtcのDateTimeからDateTimeOffsetオブジェクトを作成する
DateTimeOffset dto4 = new DateTimeOffset(dtUtc);
//2000/09/24 15:30:00 +00:00

//KindがLocalのDateTimeからDateTimeOffsetオブジェクトを作成する
DateTimeOffset dto5 = new DateTimeOffset(dtLocal);
//2000/09/24 15:30:00 +09:00

//オフセットを指定してDateTimeOffsetオブジェクトを作成する
//KindがUtcのDateTimeの時はオフセットが0でなければならないので、例外が発生する
//DateTimeOffset dto6 = new DateTimeOffset(dtUtc, new TimeSpan(-5, 0, 0));

//KindをUnspecifiedに変換すれば、自由なオフセットを指定できる
DateTime dtUnspecified = DateTime.SpecifyKind(dtUtc, DateTimeKind.Unspecified);
DateTimeOffset dto7 = new DateTimeOffset(dtUnspecified, new TimeSpan(-5, 0, 0));
//2000/09/24 15:30:00 -05:00

DateTimeオブジェクトを暗黙的に変換する

DateTimeをDateTimeOffsetを変更するならば、上記のようにわざわざコンストラクタを呼びださなくても、暗黙的に変換することができます。この時のオフセットは、上で説明したオフセットを指定しないでDateTimeオブジェクトからDateTimeOffsetオブジェクトを作成した場合と同じになります。

VB.NET
コードを隠すコードを選択
Dim dtUtc As New DateTime(2000, 9, 24, 15, 30, 0, DateTimeKind.Utc)
Dim dtLocal As New DateTime(2000, 9, 24, 15, 30, 0, DateTimeKind.Local)

'DateTimeをDateTimeOffsetに暗黙の型変換をする
Dim dto8 As DateTimeOffset = dtUtc
'2000/09/24 15:30:00 +00:00

Dim dto9 As DateTimeOffset = dtLocal
'2000/09/24 15:30:00 +09:00
C#
コードを隠すコードを選択
DateTime dtUtc = new DateTime(2000, 9, 24, 15, 30, 0, DateTimeKind.Utc);
DateTime dtLocal = new DateTime(2000, 9, 24, 15, 30, 0, DateTimeKind.Local);

//DateTimeをDateTimeOffsetに暗黙の型変換をする
DateTimeOffset dto8 = dtUtc;
//2000/09/24 15:30:00 +00:00

DateTimeOffset dto9 = dtLocal;
//2000/09/24 15:30:00 +09:00

日時を表した文字列を変換する

「2000/09/24 15:30:00 +09:00」のような文字列をDateTimeOffsetオブジェクトに変換することも出来ます。その方法は、「日時を表す文字列をDateTimeオブジェクトに変換する」で説明している方法と同じです。

DateTimeOffset.Parseメソッドを使って、文字列をDateTimeOffsetオブジェクトに変換する簡単な例を幾つか紹介します。詳しくは、「日時を表す文字列をDateTimeオブジェクトに変換する」をご覧ください。

VB.NET
コードを隠すコードを選択
'文字列をDateTimeOffsetに変換する
Dim s1 As String = "2000/09/24 15:30:00 +09:00"
Dim dto10 As DateTimeOffset = DateTimeOffset.Parse(s1)
'2000/09/24 15:30:00 +09:00

'オフセットの記述がない文字列をDateTimeOffsetに変換する
Dim s2 As String = "2000/09/24 15:30:00"
Dim dto11 As DateTimeOffset = DateTimeOffset.Parse(s2)
'2000/09/24 15:30:00 +09:00
C#
コードを隠すコードを選択
//文字列をDateTimeOffsetに変換する
string s1 = "2000/09/24 15:30:00 +09:00";
DateTimeOffset dto10 = DateTimeOffset.Parse(s1);
//2000/09/24 15:30:00 +09:00

//オフセットの記述がない文字列をDateTimeOffsetに変換する
string s2 = "2000/09/24 15:30:00";
DateTimeOffset dto11 = DateTimeOffset.Parse(s2);
//2000/09/24 15:30:00 +09:00

計算を行う

DateTimeOffsetの計算はDateTimeと同じようにできます。メソッドもDateTimeと同じものが用意されています。DateTimeの計算については、「日時、時間の計算をする」で説明しています。

DateTimeの計算とDateTimeOffsetの計算で異なるのは、DateTimeの計算ではKindプロパティが考慮されないのに対して、DateTimeOffsetの計算ではオフセットの値が考慮される点です。

下の例では、日時が同じでオフセットが9時間違う2つのDateTimeOffsetを作成して、引き算しています。結果は、9時間となります。

VB.NET
コードを隠すコードを選択
'オフセットが9時間異なる2つのDateTimeOffsetを作成する
Dim dto1 As New DateTimeOffset(2000, 9, 1, 0, 0, 0, TimeSpan.FromHours(0))
Dim dto2 As New DateTimeOffset(2000, 9, 1, 0, 0, 0, TimeSpan.FromHours(9))

'2つの日時を引く
Dim ts1 As TimeSpan = dto1 - dto2

Console.WriteLine(ts1)
'09:00:00
C#
コードを隠すコードを選択
//オフセットが9時間異なる2つのDateTimeOffsetを作成する
DateTimeOffset dto1 = new DateTimeOffset(2000, 9, 1, 0, 0, 0, TimeSpan.FromHours(0));
DateTimeOffset dto2 = new DateTimeOffset(2000, 9, 1, 0, 0, 0, TimeSpan.FromHours(9));

//2つの日時を引く
TimeSpan ts1 = dto1 - dto2;

Console.WriteLine(ts1);
//09:00:00

ローカル時刻やUTCへの変換を行う

DateTimeOffsetオブジェクトをUTCに変換するには、ToUniversalTimeメソッドを使います。ToUniversalTimeメソッドは、日時をオフセット分減らして、Offsetプロパティを 00:00:00 としたDateTimeOffsetオブジェクトを返します。

DateTimeOffsetオブジェクトをローカル時刻(ローカルコンピュータのタイムゾーンでの時刻)に変換するには、ToLocalTimeメソッドを使います。ToLocalTimeメソッドは、日時をUTCに変換した後、ローカルコンピュータのタイムゾーンのオフセット値を加えて、さらにそれをOffsetプロパティとしたDateTimeOffsetオブジェクトを返します。

以下の例では、オフセットが-5時間のDateTimeOffsetオブジェクトを作成し、そのUTCとローカル時刻(日本時間)を取得しています。

VB.NET
コードを隠すコードを選択
Dim dt As New DateTime(2000, 9, 24, 15, 30, 0)

'オフセットを-5時間としてDateTimeOffsetを作成する
Dim dto As New DateTimeOffset(dt, New TimeSpan(-5, 0, 0))
Console.WriteLine(dto)
'2000/09/24 15:30:00 -05:00

'UTCに変換する
Dim utcTime As DateTimeOffset = dto.ToUniversalTime()
Console.WriteLine(utcTime)
'2000/09/24 20:30:00 +00:00

'ローカル時刻(日本時間)に変換する
Dim localTime As DateTimeOffset = dto.ToLocalTime()
Console.WriteLine(localTime)
'2000/09/25 5:30:00 +09:00
C#
コードを隠すコードを選択
DateTime dt = new DateTime(2000, 9, 24, 15, 30, 0);

//オフセットを-5時間としてDateTimeOffsetを作成する
DateTimeOffset dto = new DateTimeOffset(dt, new TimeSpan(-5, 0, 0));
Console.WriteLine(dto);
//2000/09/24 15:30:00 -05:00

//UTCに変換する
DateTimeOffset utcTime = dto.ToUniversalTime();
Console.WriteLine(utcTime);
//2000/09/24 20:30:00 +00:00

//ローカル時刻(日本時間)に変換する
DateTimeOffset localTime = dto.ToLocalTime();
Console.WriteLine(localTime);
//2000/09/25 5:30:00 +09:00

これらのメソッド以外に、DateTimeOffsetオブジェクトが表している日時をUTCやローカル時刻で取得できるプロパティも用意されています。

UtcDateTimeプロパティによって、UTCをDateTimeオブジェクトで取得できます。また、LocalDateTimeプロパティによって、ローカル時刻をDateTimeオブジェクトで取得できます。

DateTimeOffset構造体のプロパティの内、DateTimeにはないプロパティを表にまとめると、以下のようになります。

プロパティ名 説明 プロパティ値の型 プロパティ値の範囲
Offset UTCからの時差を取得する。 TimeSpan -14:00:00〜14:00:00
DateTime Offsetプロパティを無視した日時の部分だけをDateTimeで取得する。DateTimeOffsetが「02/9/30 13:00 +9:00」ならば、「02/9/30 13:00」となる。DateTimeUtcプロパティにOffsetプロパティを足した値。DateTimeのKindプロパティはDateTimeKind.Unspecifiedになる。 DateTime
LocalDateTime 現地時刻をDateTimeで取得する。UtcDateTimeプロパティの値をローカルコンピュータの現地時刻に変換する。DateTimeのKindプロパティはDateTimeKind.Localになる。 DateTime
UtcDateTime UTCをDateTimeで取得する。DateTimeプロパティからOffsetプロパティを引いた値。DateTimeのKindプロパティはDateTimeKind.Utcになる。 DateTime
UtcTicks UTCのタイマ刻み数を取得する。DateTimeOffset.UtcDateTime.Ticksと同じ。 Int64

以下に、DateTimeOffsetのプロパティによってUTCやローカル時刻を取得する例を示します。

VB.NET
コードを隠すコードを選択
'オフセットが-5時間のDateTimeOffsetを作成する
Dim dto As New DateTimeOffset(2000, 9, 24, 15, 30, 0, _
 TimeSpan.FromHours(-5))
Console.WriteLine(dto)
'2000/09/24 15:30:00 -05:00

'UTCを取得する
Dim utcTime As DateTime = dto.UtcDateTime
Console.WriteLine("{0} {1}", utcTime, utcTime.Kind)
'2000/09/24 20:30:00 Utc

'ローカル時刻(日本時間)を取得する
Dim localTime As DateTime = dto.LocalDateTime
Console.WriteLine("{0} {1}", localTime, localTime.Kind)
'2000/09/25 5:30:00 Local

'DateTimeオブジェクトでdtoが示す日時を取得する
Dim dt As DateTime = dto.DateTime
Console.WriteLine("{0} {1}", dt, dt.Kind)
'2000/09/24 15:30:00 Unspecified
C#
コードを隠すコードを選択
//オフセットが-5時間のDateTimeOffsetを作成する
DateTimeOffset dto = new DateTimeOffset(2000, 9, 24, 15, 30, 0, TimeSpan.FromHours(-5));
Console.WriteLine(dto);
//2000/09/24 15:30:00 -05:00

//UTCを取得する
DateTime utcTime = dto.UtcDateTime;
Console.WriteLine("{0} {1}", utcTime, utcTime.Kind);
//2000/09/24 20:30:00 Utc

//ローカル時刻(日本時間)を取得する
DateTime localTime = dto.LocalDateTime;
Console.WriteLine("{0} {1}", localTime, localTime.Kind);
//2000/09/25 5:30:00 Local

//DateTimeオブジェクトでdtoが示す日時を取得する
DateTime dt = dto.DateTime;
Console.WriteLine("{0} {1}", dt, dt.Kind);
//2000/09/24 15:30:00 Unspecified

DateTimeOffsetオブジェクトを任意のタイムゾーンのローカル時刻に変換するには、TimeZoneInfo.ConvertTimeメソッドTimeZoneInfo.ConvertTimeBySystemTimeZoneIdメソッドを使います。これらのメソッドについては、「ローカル時刻を世界協定時刻(UTC)に変換する」で説明しています。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • .NET Tipsをご利用いただく際は、注意事項をお守りください。