过去几周我一直在努力工作,但是我遇到了一个小问题。我觉得我的头脑现在还没有适应这个任务:)所以我需要一些技巧/帮助!这可能很简单,但我的思维还没有跟上。
用户将输入AEST日期和时间。还有一个应用设置的“默认”时区(因为它可能需要更改),目前设置为“AUS Eastern Standard Time”。
因此,在美国服务器上有一个具有定义系统时区的用户字符串(因此本地不匹配且无法更改或使用)。
现在我需要的是一种方法来说“使用时区X解析此用户输入的字符串”,我不能只输入+10或+11作为偏移量,因为日期可能在夏令时期间内或外;即使对于相同的时区,这也会导致+10和+11之间的变化!
当前的AEST时间也可能处于夏令时内或外,因此我不能只将UTC日期转换为当前的AEST时间并获取“zzz”字符串并附加它,因为任何输入超出当前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。然而,某些日期有一个小时的误差,而其他日期则完美(如预期):)
最优雅的解决方法是什么?
编辑:
为了帮助解释问题,我编写了一些测试代码作为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
请注意,小时数相差一小时且偏移量不同。另外,如果我们只改变输入的日期,会发生什么?
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
这是非常好的结果,只是使用不同的输入日期而已。
这种情况发生的原因是当前的夏令时设置和输入日期的夏令时设置不同,我想找到一个解决办法 :)
可以把它想象成鸡和蛋的问题。在解析字符串之前,我需要正确的时区数据,但只有在解析完字符串后才能获得它(因此需要一个复杂的解决方案)。
或者我需要 .NET 使用 myTimeZone 对象来解析字符串,以便它知道如何自行设置它,但我看不到任何执行此操作的函数,它们都需要已经解析并设置了日期时间或日期时间偏移对象。
因此,我正在寻找其他人可能已经解决的优雅解决方案?我肯定不是唯一一个注意到这个问题的人吧?
编辑2:
好的,我已经制作了一个“有效”的函数来解决这个问题,下面是一个示例(添加一个文本框到 C# 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 读取2 - UTC: 2011/04/20 00:00:00 +00:00 改回: 2011/04/20 10:00:00 +10:00
唯一的问题是,如果用户输入的日期恰好在夏令时转换点上,则可能会有问题,因为它只读取当前偏移量并使用它,然后检查它是否应该是夏令时,如果超出范围,则会读取不正确。然而,这比我现在拥有的要好得多。
有人可以帮我整理一下这个函数吗?这是我需要走的最佳路线吗?还有其他想法吗?