質問

[更新フォーマット指定子はフォーマット文字列と同じものではありません。書式指定子はカスタム書式文字列の一部であり、書式文字列は「ストック」であり、カスタマイズを提供しません。私の問題はフォーマットではなく指定子にあります]

「zzz」形式指定子を使用する形式文字列を使用して、DateTimeの往復変換を実行しようとしていますが、これはローカル時間にバインドされていることがわかっています。したがって、UTC日付時刻でラウンドトリップを試みると、DateTimeInvalidLocalFormat例外がスローされます。

UTC DateTimeは、現地時間にのみ正しい形式のテキストに変換されています。これは、出力にローカルタイムゾーンオフセットが含まれる 'z'形式指定子を使用してDateTime.ToStringを呼び出すときに発生する可能性があります。 その場合、UTC時間を指定する「Z」形式指定子を使用するか、「o」形式文字列を使用します。これは、DateTimeをテキストで保持するための推奨される方法です。これは、XmlConvertまたはDataSetによってシリアル化されるDateTimeを渡すときにも発生する可能性があります。 XmlConvert.ToStringを使用する場合は、XmlDateTimeSerializationMode.RoundtripKindを渡して正しくシリアル化してください。 DataSetを使用する場合、DataColumnオブジェクトのDateTimeModeをDataSetDateTime.Utcに設定します。

この提案に基づいて、コードを機能させるために必要なことは、 'zzz'を 'ZZZ'に置き換えるだけで、UTC形式で立つことができます。問題は、「Z」がドキュメントのどこにも見つからず、私が試みる「Z」形式の組み合わせ、つまり「Z」、「ZZ」、「ZZZ」は、常にリテラルのように扱われるZでDateTimeインスタンスを変換するだけです。

誰かが例外メッセージの作成者に通知せずに 'Z'を実装するのを忘れたか、または有効なローカル時間オフセットを" + 0000"と交換する方法がありません。ハッキングせずに

コード例:

// This is the format with 'zzzzz' representing local time offset
const string format = "ddd MMM dd HH:mm:ss zzzzz yyyy";

// create a UTC time
const string expected = "Fri Dec 19 17:24:18 +0000 2008";
var time = new DateTime(2008, 12, 19, 17, 24, 18, 0, DateTimeKind.Utc);

// If you're using a debugger this will rightfully throw an exception
// with .NET 3.5 SP1 because 'z' is for local time only; however, the exception
// asks me to use the 'Z' specifier for UTC times, but it doesn't exist, so it
// just spits out 'Z' as a literal.
var actual = time.ToString(format, CultureInfo.InvariantCulture);

Assert.AreEqual(expected, actual);
役に立ちましたか?

解決

おそらく「K」書式指定子は何らかの用途に役立ちます。これは、大文字の「Z」の使用に言及していると思われる唯一のものです。

" Z" DateTimesのユニークなケースです。リテラル" Z"実際にはUTC時間のISO 8601日時標準の一部です。 「Z」が(ズールー語)は時間の終わりに付けられ、その時間はUTCであるため、実際には文字Zは時間の一部です。これは、おそらく.NETの日付形式ライブラリにいくつかの問題を作成します。これは、実際には形式指定子ではなくリテラルであるためです。

他のヒント

DateTimeを使用すると、変数内に日付と時刻を保存できます。

日付は現地時間でもUTC時間でもかまいませんが、あなた次第です。

たとえば、私はイタリアにいます(+2 UTC)

var dt1 = new DateTime(2011, 6, 27, 12, 0, 0); // store 2011-06-27 12:00:00
var dt2 = dt1.ToUniversalTime()  // store 2011-06-27 10:00:00

では、タイムゾーンを含むdt1とdt2を印刷するとどうなりますか?

dt1.ToString("MM/dd/yyyy hh:mm:ss z") 
// Compiler alert...
// Output: 06/27/2011 12:00:00 +2

dt2.ToString("MM/dd/yyyy hh:mm:ss z") 
// Compiler alert...
// Output: 06/27/2011 10:00:00 +2

dt1およびdt2には、日付と時刻の情報のみが含まれます。 dt1とdt2にはタイムゾーンオフセットが含まれていません。

したがって、「+ 2」 dt1およびdt2変数に含まれていない場合に由来しますか?

マシンのクロック設定から取得されます。

コンパイラは、「zzz」形式を使用すると、「日付と時刻」を組み合わせた文字列を記述していると言っています。 (これらはdt1とdt2に保存されます)+ " TIMEZONE OFFSET" (DateTymeタイプであるためdt1およびdt2には含まれません)、コードを実行しているサーバーマシンのオフセットを使用します。

コンパイラは、「警告:コードの出力はマシンクロックオフセットに依存しています」と表示します

ロンドン(UTC + 1)に位置するサーバーでこのコードを実行すると、結果は完全に異なります:" +2 " " +1 "

と書き込みます。
...
dt1.ToString("MM/dd/yyyy hh:mm:ss z") 
// Output: 06/27/2011 12:00:00 +1

dt2.ToString("MM/dd/yyyy hh:mm:ss z") 
// Output: 06/27/2011 10:00:00 +1

正しい解決策は、DateTimeの代わりにDateTimeOffsetデータ型を使用することです。 2008バージョン以降のSQL Serverおよび3.5バージョン以降の.Netフレームワークで利用可能です

文字列を介したラウンドトリップ日付は常に苦痛でした...しかし、 'o'指定子がUTC状態をキャプチャするラウンドトリップに使用するものであることを示すドキュメント。解析時に、元のファイルがUTCである場合、結果は通常Kind == Utcになります。最善の方法は、シリアル化する前に常に日付をUTCまたはローカルに正規化してから、選択した正規化のパーサーに指示することです。

DateTime now = DateTime.Now;
DateTime utcNow = now.ToUniversalTime();

string nowStr = now.ToString( "o" );
string utcNowStr = utcNow.ToString( "o" );

now = DateTime.Parse( nowStr );
utcNow = DateTime.Parse( nowStr, null, DateTimeStyles.AdjustToUniversal );

Debug.Assert( now == utcNow );

MSDNのこのページには、標準のDateTime形式の文字列がリストされています。 「Z」を使用した文字列。

更新:日付文字列の残りの部分も正しいパターンに従うことを確認する必要があります(送信したものの例を提供していないため、送信したかどうかを言うのは困難です)。 UTC形式が機能するには、次のようになります。

// yyyy'-'MM'-'dd HH':'mm':'ss'Z'
DateTime utcTime = DateTime.Parse("2009-05-07 08:17:25Z");
Label1.Text = dt.ToString("dd MMM yyyy | hh:mm | ff | zzz | zz | z");

出力されます:

07 Mai 2009 | 08:16 | 13 | +02:00 | +02 | +2

私はデンマークにいます。GMTからのオフセットは+2時間で、魔女は正しいです。

クライアントオフセットを取得する必要がある場合は、私がやったちょっとしたトリック。このページは、GMTが+00:00の英国のサーバーにあり、ご覧のとおり、ローカルGMTオフセットを取得できます。


コメントについて、私はしました:

DateTime dt1 = DateTime.Now;
DateTime dt2 = dt1.ToUniversalTime();

Label1.Text = dt1.ToString("dd MMM yyyy | hh:mm | ff | zzz | zz | z");
Label2.Text = dt2.ToString("dd MMM yyyy | hh:mm | FF | ZZZ | ZZ | Z");

そして、私はこれを得る:

07 Mai 2009 | 08:24 | 14 | +02:00 | +02 | +2
07 Mai 2009 | 06:24 | 14 | ZZZ | ZZ | Z 

例外は発生しません、ただ...大文字のZでは何もしません:(

申し訳ありませんが、何か不足していますか?


カスタムの日付と時刻の形式文字列

大文字の「Z」はサポートされていません。

DateTimeOffset を扱っていましたが、残念ながら" o" " + 0000"を出力します。 " Z"ではありません。

だから私は結局:

dateTimeOffset.UtcDateTime.ToString("o")
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top