Phi*_*ier 6 c# timezone datetime parsing windows-phone-7
我在解析日期和时间时遇到了一个问题:
我正在尝试解析从德国网站提取的日期时间字符串.它的格式为'day.month.year 24hours:minutes',如:
01.01.2011 17:00
Run Code Online (Sandbox Code Playgroud)
它总是在德国时区.但问题出现了:
我不知道如何实现这一目标.如果我将本地时钟设置为德国时区,并使用DateTime.ParseExact和解析标志DateTimeStyles.AssumeLocal并DateTimeStyles.AdjustToUniversal正确解析它.但是,我希望任何客户端独立于本地时钟和时区解析它.另外,我不想自己做时区偏移,因为它取决于日期(夏天:-2 /冬季:-1).
一旦我有UTC的日期时间,很容易将其转换为任何本地时区.
听起来您知道应该用哪个时区来解析它。假设.NET 3.5(因此TimeZoneInfo)你应该逻辑上:
不幸的DateTime是,这有点棘手。编辑:我以为你想使用DateTimeStyles.AssumeUniversal- 但最终会返回一个local DateTime,令人烦恼。基本上你希望在正确的时间 结束,DateTime以便你可以使用:
parsed = DateTime.SpecifyKind(parsed, DateTimeKind.Unspecified);
Run Code Online (Sandbox Code Playgroud)
然后您可以通过以下方式获取 UTC 值:
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(parsed, germanTimeZone);
Run Code Online (Sandbox Code Playgroud)
请注意,您确实首先需要一个“未指定”的日期时间,以便您可以将其转换为任意时区的 UTC。您还应该记住,由于 DST 更改,当地时间可能不明确(出现两次)或不可能(根本不出现)。
是的,当它完成后,在野田时间里这会容易得多:)
在看到无法在 WP7/Silverlight 框架的帮助下完成该任务后,我编写了一个完成这项工作的小助手:
public static class DateTimeHelper
{
/// <summary>
/// Tries to parse the given datetime string that is not annotated with a timezone
/// information but known to be in the CET/CEST zone and returns a DateTime struct
/// in UTC (so it can be converted to the devices local time). If it could not be
/// parsed, result contains the current date/time in UTC.
/// </summary>
public static bool TryParseCetCest(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
{
// Parse datetime, knowing it is in CET/CEST timezone. Parse as universal as we fix it afterwards
if (!DateTime.TryParseExact(s, format, provider, style, out result))
{
result = DateTime.UtcNow;
return false;
}
result = DateTime.SpecifyKind(result, DateTimeKind.Utc);
// The boundaries of the daylight saving time period in CET and CEST (_not_ in UTC!)
// Both DateTime structs are of kind 'Utc', to be able to compare them with the parsing result
DateTime DstStart = LastSundayOf(result.Year, 3).AddHours(2);
DateTime DstEnd = LastSundayOf(result.Year, 10).AddHours(3);
// Are we inside the daylight saving time period?
if (DstStart.CompareTo(result) <= 0 && result.CompareTo(DstEnd) < 0)
result = result.AddHours(-2); // CEST = UTC+2h
else
result = result.AddHours(-1); // CET = UTC+1h
return true;
}
/// <summary>
/// Returns the last sunday of the given month and year in UTC
/// </summary>
private static DateTime LastSundayOf(int year, int month)
{
DateTime firstOfNextMonth = new DateTime(year, month + 1, 1, 0, 0, 0, DateTimeKind.Utc);
return firstOfNextMonth.AddDays(firstOfNextMonth.DayOfWeek == DayOfWeek.Sunday ? -7 :
(-1 * (int)firstOfNextMonth.DayOfWeek));
}
}
Run Code Online (Sandbox Code Playgroud)
诀窍是在没有DateTimeStyles.AssumeUniversal 标志的情况下解析它(这使得TryParseExact假设日期是 UTC 并返回转换/调整为本地的日期),将其重新指定为 UTC,然后手动将其调整为实际的 UTC 等效值。
它遵循 DST 规则(可在此处找到) 。我在夏令时开始/结束之前/之后对所有 4 个边界情况进行了测试。这再次表明了测试的重要性:我必须将<运算符更改DstStart.CompareTo(result) < 0为<=才能使其产生正确的结果。
我有一种感觉,我在这里重新发明轮子(我讨厌这样做),但不想使用专用的库来完成这个简单的工作。我看过 Noda Time,这是一个很棒的项目,但我认为这没有必要。
我希望通过这个小帮手可以节省一些人的时间。它故意不是对所有时区通用(如果您需要它,请使用像 Noda Time 这样的库),但对于这些只有一个固定的单一时区的情况,就像我的情况一样。
| 归档时间: |
|
| 查看次数: |
4163 次 |
| 最近记录: |