如果不是 Utc 时间,将 DateTime 转换为 Utc

12

我正在使用Jon Skeet在创建一个特定时区的DateTime(c# fx 3.5)中发布的DateTimeWithZone结构。

对于我的情况,这并没有完全起作用,因为它假设传递给构造函数的DateTime是本地时间,因此会使用指定的时区将其转换为UTC。

在我的情况下,我们主要将传递已经处于UTC的DateTime对象(因为这是我们所存储的),因此我们只需要在源DateTime.Kind不是Utc时执行转换。

因此,我将构造函数更改为:

    public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone, DateTimeKind kind = DateTimeKind.Utc) {
        dateTime = DateTime.SpecifyKind(dateTime, kind);
        utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZone);
        this.timeZone = timeZone;
    }

在这里,我们有一个可选的Kind参数,默认为Utc。

然而,运行此代码并传递一个 Utc DateTime 会生成以下异常:

不能完成转换,因为提供的 DateTime 没有正确设置 Kind 属性。例如,当 Kind 属性为 DateTimeKind.Local 时,源时区必须为 TimeZoneInfo.Local。

根据文档 (http://msdn.microsoft.com/en-us/library/bb495915.aspx):

如果 dateTime 参数的 Kind 属性等于 DateTimeKind.Utc 并且 sourceTimeZone 参数等于 TimeZoneInfo.Utc,则此方法返回 dateTime 而不执行任何转换。

由于输入时间和时区都具有 Utc 的 Kind 属性,因此我不希望得到此异常。

我是否理解错了?

1个回答

13

根据 MSDN 文档所述,如果您传入的 DateTime 对象的 Kind 属性值不是 DateTimeKind.Utc,并且指定了一个非 Utc 的 TimeZone,那么转换函数将会抛出异常。这可能就是这里出现问题的原因。在代码中,您应该检查传入的 DateTime 是否已经是 Utc 标准时间,如果是则可以跳过转换操作。

此外,由于您传入的 DateTime 对象本身已经包含日期时间信息,可能不需要再传递独立的 Kind 参数。

来自文档

将指定时区中的时间转换为协调世界时(UTC)。

也就是说,它会将给定时区的时间转换为 Utc 时间。

如果以下条件成立,则该函数会抛出参数异常:

dateTime.Kind 是 DateTimeKind.Utc 而 sourceTimeZone 不等于 TimeZoneInfo.Utc。

- 或 -

dateTime.Kind 是 DateTimeKind.Local,而 sourceTimeZone 不等于 TimeZoneInfo.Local。

- 或 -

sourceTimeZone.IsInvalidDateTime(dateTime) 返回 true。


在上面的示例中,输入日期、目标时区和本地时区(TimeZoneInfo.Local)都具有DateTimeKind.Utc的类型,因此不应该产生异常。 - Ben Foster
@Ben 是的,应该可以。ConvertTimeToUtc将从指定时区转换为UTC。如果时区是本地时区,则传递的 DateTime 必须是 DateTimeKind.Local - Yaur
@ben 我已经更新了答案,包括MSDN文档的相关部分。 - Yaur
不知道为什么要花那么长时间才理解 :) 没有意识到 Utc 和 Local 是 TimeZoneInfo 的静态属性。正如您所说,检查源时间的类型并跳过转换比按照上述规则检查时区要容易得多。 - Ben Foster

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