DateTimeOffset解析和自定义时区

7
我们正在将XML DateTime值解析为DateTimeOffset值。根据W3C XSD documentation for DateTime,该类型可能具有时区信息或没有。
我们的要求是:
- 如果XML中提供了时区信息,请使用此时区 - 如果未提供时区信息,则假定它是预定义的、可配置的时区中的本地时间(不是服务器上的时区)。
问题在于,当将没有时区的XML DateTime解析为DateTimeOffset时,默认情况下会使用本地(系统)时区。似乎无法覆盖默认时区,并且也无法确定时区是在解析期间被解析还是自动添加的。
有没有办法指定DateTimeOffset解析使用的默认时区? 如果没有,如何确定是否在DateTimeOffset解析期间解析了时区或自动添加了时区?
对我来说,似乎奇怪的是,没有像设置当前文化一样设置.NET应用程序的时区的支持。
因此,解决这个问题的唯一方法似乎是先将值解析为DateTime,然后检查其Kind属性。如果Kind不是未指定,则再次将值解析为DateTimeOffset:
/*
sample values:
- 2015-06-03T10:47:01
- 2015-06-03T07:47:01Z
- 2015-06-03T10:47:01+03:00
*/

DateTimeOffset dto;
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["DefaultTimeZone"]);
var dt = DateTime.Parse(value);

if (dt.Kind == DateTimeKind.Unspecified)
{
    dto = new DateTimeOffset(dt, timeZone.GetUtcOffset(dt));
}
else
{
    dto = DateTimeOffset.Parse(value);
}

从您的第一个要求开始:“如果在XML中提供了时区信息,请使用此时区。” 这意味着“时区”数据是您的代码用于解析DateTime对象的输入参数之一,对吗? 因此,如果未定义此参数,您不能只使用相同的代码,但将此参数分配为您想要用作默认值的任何时区吗? - Zoomzoom
1个回答

7

最简单的方法是事先测试字符串,以查看它是否包含偏移量。 正则表达式非常适合这种情况。

以下是一个适用于您所描述情况的函数:

static DateTimeOffset ParseAsDateTimeOffset(string s, TimeSpan defaultOffset)
{
    if (Regex.IsMatch(s, @"(Z|[+-]\d{2}:\d{2})$"))
        return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture);

    var dt = DateTime.Parse(s, CultureInfo.InvariantCulture);
    return new DateTimeOffset(dt, defaultOffset);
}

您也可以考虑一种略微不同的方法,即提供默认的时区,而不是默认的偏移量。这是一个重要的区别,因为时区的偏移量取决于具体日期是否处于夏令时期间。请参见时区标签维基中的“时区!= 偏移量”。

static DateTimeOffset ParseAsDateTimeOffset(string s, TimeZoneInfo defaultTimeZone)
{
    if (Regex.IsMatch(s, @"(Z|[+-]\d{2}:\d{2})$"))
        return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture);

    var dt = DateTime.Parse(s, CultureInfo.InvariantCulture);
    return new DateTimeOffset(dt, defaultTimeZone.GetUtcOffset(dt));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接