24

さて、私はここ数週間非常に一生懸命働いてきました、そして私は小さな問題に遭遇しました。私の心は今のところ仕事に完全に対応しているとは思わない:)だから私はいくつかのヒント/助けが必要です!非常に単純な可能性がありますが、私の頭はまだクリックされていません。

ユーザーはAESTに日付と時刻を入力します。アプリケーションセット「デフォルト」タイムゾーン(変更が必要になる場合があるため)もあり、現在は「AUS東部標準時」に設定されています。

したがって、米国のサーバーにはタイムゾーンのないユーザー文字列と定義されたシステムタイムゾーンがあります(したがって、ローカルは一致せず、変更または使用できません)

ここで必要なのは、「タイムゾーンXを使用してこのユーザーが入力した文字列を解析する」と言う方法です。夏時間の有無にかかわらず、オフセットとして+10または+11を入力することはできません。はい、同じタイムゾーンでも+10と+11の間で変更されます。

現在のAEST時刻もDSTの内外にある可能性があるため、UTC日付を現在のAEST時刻に変換して「zzz」文字列を取得し、入力したものの日付が1時間ずれるので、それを添付することはできません。現在のDST設定の。

今のところ、コードは実際にはそれを実行します:

TimeZoneInfo ConvTo = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["DefaultTimeZone"]);
DateTimeOffset getDate = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, ConvTo);
string TimeZoneId = " " + getDate.ToString("zzz");
DateTimeOffset cvStartDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(StartDate + TimeZoneId, out cvStartDate);

次に、日付がまだ== DateTimeOffset.MinValueであるかどうかを確認するか、UTCに変換してデータベースに追加することにより、日付が有効でないかどうかを確認します。表示されると、AESTに変換されます。ただし、一部の日付は1時間ずれており、他の日付は(予想どおり)完璧です:)

これを解決するための最もエレガントな方法は何ですか?

編集:

問題を説明するのを助けるために、私はいくつかのテストコードをWindowsテストアプリケーションとして書きました:

// User entered date
string EnteredDate = "2011/01/01 10:00:00 AM";

// Get the timezone we want to use
TimeZoneInfo myTimeZone = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");

// Find the timezone string of the selected timezone to parse the user string
// This is the part that is incorrect and what i need help with.
DateTimeOffset getDate = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, myTimeZone);
string TimeZoneId = " " + getDate.ToString("zzz");

// Parse the string into the date object
DateTimeOffset cvEnteredDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(EnteredDate + TimeZoneId, out cvEnteredDate);

// Display
textBox1.Text += "Parsed: " + cvEnteredDate.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;

// Convert to UTC and display
cvEnteredDate = cvEnteredDate.ToUniversalTime();
textBox1.Text += "UTC: " + cvEnteredDate.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;

// Convert back to AEST and display
cvEnteredDate = TimeZoneInfo.ConvertTime(cvEnteredDate, myTimeZone);
textBox1.Text += "Changed Back: " + cvEnteredDate.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;

これの出力は何ですか?

解析済み:2011/01/01 10:00:00 +10:00
UTC:2011/01/01 00:00:00 +00:00
元に戻しました:2011/01/01 11:00:00 +11:00

時間は1時間ずれており、オフセットが異なることに注意してください。さらに、入力した日付を次のように変更した場合はどうなりますか。

string EnteredDate = "2011/04/20 10:00:00 AM";

我々が得る:

解析済み:2011/04/20 10:00:00 +10:00
UTC:2011/04/20 00:00:00 +00:00
元に戻しました:2011/04/20 10:00:00 +10:00

同じコードを使用して、入力した日付を変えるだけで、これは完全に問題ありません。

これは、現在のDST設定と入力された日付のDST設定が異なるために発生します。これは、私が解決策を求めているものです:)

鶏が先か卵が先かという問題のように考えてください。文字列を解析する前に、入力した文字列の正しいタイムゾーンデータが必要です。これは、文字列を解析した後にのみ取得できます(したがって、複雑な解決策になります)

または、myTimeZoneオブジェクトを使用して文字列を解析するために.NETが必要です。これにより、文字列をそれ自体に設定する内容がわかりますが、これを実行する関数は表示されません。これらはすべて、すでに解析されて設定されたdatetimeまたはdatetimeoffsetオブジェクトを取得します。

だから私は他の人がしたかもしれないエレガントな解決策を探していますか?確かにこれに気付いたのは私だけではありませんか?

EDIT2:

さて、私が思う問題を解決する「動作する」関数を作成しました。ここに例があります(ac#windowsアプリにテキストボックスを追加し、以下のコードを使用して自分自身をテストします):

private void Form1_Load(object sender, EventArgs e)
{
    TimeZoneInfo myTimeZone = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");

    DateTimeOffset get1Date = ReadStringWithTimeZone("2011/01/01 10:00:00 AM", myTimeZone);
    textBox1.Text += "Read1: " + get1Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;
    get1Date = get1Date.ToUniversalTime();
    textBox1.Text += "Read1 - UTC: " + get1Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;
    get1Date = TimeZoneInfo.ConvertTime(get1Date, myTimeZone);
    textBox1.Text += "Changed Back: " + get1Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine + Environment.NewLine;

    DateTimeOffset get2Date = ReadStringWithTimeZone("2011/04/20 10:00:00 AM", myTimeZone);
    textBox1.Text += "Read2: " + get2Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;
    get2Date = get2Date.ToUniversalTime();
    textBox1.Text += "Read2 - UTC: " + get2Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;
    get2Date = TimeZoneInfo.ConvertTime(get2Date, myTimeZone);
    textBox1.Text += "Changed Back: " + get2Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine + Environment.NewLine;
}

public DateTimeOffset ReadStringWithTimeZone(string EnteredDate, TimeZoneInfo tzi)
{
    DateTimeOffset cvUTCToTZI = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, tzi);
    DateTimeOffset cvParsedDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(EnteredDate + " " + cvUTCToTZI.ToString("zzz"), out cvParsedDate);
    if (tzi.SupportsDaylightSavingTime)
    {
        TimeSpan getDiff = tzi.GetUtcOffset(cvParsedDate);
        string MakeFinalOffset = (getDiff.Hours < 0 ? "-" : "+") + (getDiff.Hours > 9 ? "" : "0") + getDiff.Hours + ":" + (getDiff.Minutes > 9 ? "" : "0") + getDiff.Minutes;
        textBox1.Text += "Diff: " + MakeFinalOffset + Environment.NewLine;
        DateTimeOffset.TryParse(EnteredDate + " " + MakeFinalOffset, out cvParsedDate);
        return cvParsedDate;
    }
    else
    {
        return cvParsedDate;
    }
}

そして出力:

差分:+11:00
読む1:2011/01/01 10:00:00 +11:00
読み取り1-UTC:2010/12/31 23:00:00 +00:00
元に戻しました:2011/01/01 10:00:00 +11:00

差分:+10:00
読む2:2011/04/20 10:00:00 +10:00
Read2-UTC:2011/04/20 00:00:00 +00:00
元に戻しました:2011/04/20 10:00:00 +10:00

唯一の問題は、ユーザーが入力した日付がDSTの1時間の変更で正しい場合、現在のオフセットを読み取ってそれを使用し、それが夏時間であるかどうかを確認するため、1時間オフになる可能性があることです。そうではなく、そこにある場合は正しく読み取れません。しかし、それは私が今持っているものよりもはるかに優れています。

誰かがこの関数のクリーンアップを手伝ってくれるでしょうか?これは私が必要とするもののために行くのに最適なルートですか?アイデア?

4

5 に答える 5

17

事前定義されたフォーマットの簡単なソリューションを次に示します。これも動的にすることができます。私は個人的にこれをjavascriptと話すために使用します:

public DateTimeOffset ParseDateExactForTimeZone(string dateTime, TimeZoneInfo timezone)
{
    var parsedDateLocal = DateTimeOffset.ParseExact(dateTime, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    var tzOffset = timezone.GetUtcOffset(parsedDateLocal.DateTime);
    var parsedDateTimeZone = new DateTimeOffset(parsedDateLocal.DateTime, tzOffset);
    return parsedDateTimeZone;
}
于 2014-03-04T23:04:53.523 に答える
2

これは、既知のタイムゾーンからローカルタイムゾーンに日時文字列を解析する必要がある場合に機能するようです。多くの場合テストしていませんが、これまでのところ、EU内のどこかのサーバーで時間を解析するのに最適です。

TimeZoneInfo.ConvertTime(DateTime.Parse( "2012-05-25 23:17:15"、CultureInfo.CreateSpecificCulture( "en-EU"))、TimeZoneInfo.FindSystemTimeZoneById("W。EuropeStandard Time")、TimeZoneInfo.Local)
于 2012-05-25T21:21:26.313 に答える
1

誰もより良い解決策を提供していないので(これは非常に驚くべきことです!)、私は自分の関数を答えとして受け入れますが、関数をより簡潔にして少し後でやり直すかもしれません:

public DateTimeOffset ReadStringWithTimeZone(string EnteredDate, TimeZoneInfo tzi)
{
    DateTimeOffset cvUTCToTZI = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, tzi);
    DateTimeOffset cvParsedDate = DateTimeOffset.MinValue;
    DateTimeOffset.TryParse(EnteredDate + " " + cvUTCToTZI.ToString("zzz"), out cvParsedDate);
    if (tzi.SupportsDaylightSavingTime)
    {
        TimeSpan getDiff = tzi.GetUtcOffset(cvParsedDate);
        string MakeFinalOffset = (getDiff.Hours < 0 ? "-" : "+") + (getDiff.Hours > 9 ? "" : "0") + getDiff.Hours + ":" + (getDiff.Minutes > 9 ? "" : "0") + getDiff.Minutes;
        DateTimeOffset.TryParse(EnteredDate + " " + MakeFinalOffset, out cvParsedDate);
        return cvParsedDate;
    }
    else
    {
        return cvParsedDate;
    }
}
于 2011-04-19T06:10:34.090 に答える
0

TimeZoneInfoConvertTimeToUtc日時とタイムゾーンを指定できる静的メソッドがあります。これにより、時間調整が行われ、UTC日付が返されます。

MSDNのドキュメントはhttp://msdn.microsoft.com/en-us/library/bb495915.aspxで、例が含まれています。

于 2011-04-11T00:14:26.437 に答える
0

最も簡単な解決策:最初に文字列をローカルのDateTimeに解析し、任意の解析メソッドを使用してから呼び出します

new DateTimeOffset(dateTimeLocal.Ticks, timezone.BaseUtcOffset)
于 2017-10-27T14:00:13.203 に答える