web-dev-qa-db-ja.com

DateTimeOffsetからタイムゾーンオフセットを削除しますか?

このコード:

_DateTimeOffset testDateAndTime =
    new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0));

//CLEAN TIME AND DATE 
testDateAndTime = testDateAndTime.DateTime.Date; 

var datesTableEntry = db.DatesTable.First(dt => dt.Id == someTestId);
datesTableEntry.test= testDateAndTime;

db.SaveChangesAsync(); 
_

...この結果をデータベースに生成します:_2008-05-01 00:00:00.0000000 -04:00_

testDateAndTimeのタイムゾーンオフセットを_-4:00_から_+00:00_に変更するように、コードをどのように修正する必要がありますか?

私も試しました:

_public Task<DateTimeOffset> SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj)
{
    TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0);
    return dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan);
}
_

...しかし、そのコードは何もしません。

私の最終目標は、時間やタイムゾーンのオフセットなしで日付を設定することです。私はnot時間を別のタイムゾーンに変換したいです。 (つまり、_00:00:00.0000000_時間から4時間を引いて、設定時間オフセットを_+00:00_に削除したくない。Ijustオフセットを_+00:00_。)

これが私が他の場所で出くわした別のアプローチです:

_DateTimeOffset testDateAndTime =
    new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0));

testDateAndTime = testDateAndTime.DateTime.Date; //Zero out time portion

testDateAndTime = DateTime.SpecifyKind(
    testDateAndTime.Date, DateTimeKind.Utc); //"Zero out" offset portion
_

SpecifyKindconvert my DateTimeOffsetになると確信していました。つまり、変更両方時間およびタイムゾーンオフセット。しかし、私のテストでは、このコードjustがタイムゾーンオフセットを変更することが示されています。これは私が望むものです。このようにすることに問題はありますか?

8
VSO

この問題は、実際にはデータベースとは何の関係もありません。ブレークポイントを設定するか、出力をどこかに記録すると、次のコードの直後にオフセットが追加されていることがわかります。

testDateAndTime = testDateAndTime.DateTime.Date;

これを分解しましょう:

  • DateTimeOffsetの値2008-05-01T08:06:32+01:00から始めました
  • 次に、.DateTimeを呼び出した結果、DateTimeの値は2008-05-01T08:06:32DateTimeKind.Unspecifiedになりました。
  • 次に、.Dateを呼び出した結果、DateTimeの値は2008-05-01T00:00:00DateTimeKind.Unspecifiedになりました。
  • 結果をtestDateAndTimeに戻します。これはタイプDateTimeOffsetです。これにより、DateTimeからDateTimeOffset-への暗黙的なキャストが呼び出され、localタイムゾーン。あなたの場合、ローカルタイムゾーンでのこの値のオフセットは-04:00であるように見えるため、説明したように、結果の値は2008-05-01T00:00:00-04:00DateTimeOffsetになります。

あなたが言った:

最終目標は、時間またはタイムゾーンのオフセットなしで日付を設定することです。

ええと、currently時間のない日付だけのネイティブC#データ型はありません。 corefxlabSystem.Timeパッケージには純粋なDate型がありますが、これは一般的な本番アプリケーションの準備が整っていません。 Noda Time ライブラリには今日使用できるLocalDateがありますが、データベースに保存する前にネイティブタイプに変換し直す必要があります。その間、あなたができる最善のことは次のとおりです。

  • フィールドでdate型を使用するようにSQLServerを変更します。
  • .NETコードでは、DateTime00:00:00およびDateTimeKind.Unspecifiedの時間で使用します。時間の部分を無視することを忘れないでください(特定のタイムゾーンでは、ローカルの深夜がない日付が実際に存在するため)。
  • test小道具をDateTimeではなくDateTimeOffsetに変更します。

一般に、DateTimeOffsetは多数のシナリオ(timestampingイベントなど)に適合しますが、日付のみの値には適合しません。

オフセットがゼロの現在の日付が必要です。

本当にこれをDateTimeOffsetとして必要な場合は、次のようにします。

testDateAndTime = new DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero);

しかし、私はこれに反対することをお勧めします。そうすることで、元の値のlocal日付を取得し、UTCであると主張します。元のオフセットがゼロ以外の場合、それは誤ったアサーションになります。実際には、作成した時点とは異なる時点(日付が異なる可能性がある)について話しているため、後で他のエラーが発生する可能性があります。

編集で尋ねられた追加の質問について-DateTimeKind.Utcを指定すると、暗黙的なキャストの動作が変更されます。ローカルタイムゾーンを使用する代わりに、常にゼロのオフセットを持つUTC時間を使用します。結果は、上記で示したより明示的な形式と同じです。同じ理由で、私はまだこれに反対することをお勧めします。

2016-12-31T22:00:00-04:00で始まる例を考えてみましょう。あなたのアプローチでは、データベース2016-12-31T00:00:00+00:00に保存します。ただし、これらは2つの非常に異なる時点です。 UTCに正規化された最初のものは2017-01-01T02:00:00+00:00になり、他のタイムゾーンに変換された2番目のものは2016-12-30T20:00:00-04:00になります。変換の日付の変更に注意してください。これはおそらく、アプリケーションに忍び寄りたい動作ではありません。

15