【问题标题】:How do I convert "2015-11-06T18:34:07+05:30" string to UTC DateTime object in C#如何在 C# 中将“2015-11-06T18:34:07+05:30”字符串转换为 UTC DateTime 对象
【发布时间】:2015-11-07 05:12:32
【问题描述】:

我需要将来自服务器的“2015-11-06T18:34:07+05:30”时间戳转换为 C# 中的 DateTime 对象。然后我需要将此 DateTime 转换为 UTC 以便在同步过程中进行比较。以及时间这个时间戳中的区域可能会有所不同。那么我如何创建一个独立于时区的功能来从这个时间戳字符串中获取一个 UTC DateTime 对象。

【问题讨论】:

  • 使用解析:DateTime date = DateTime.Parse("2015-11-06T18:34:07+05:30");您无需转换为 UTC。日期以 UTC 格式自动存储在 PC 中。您的日期时间包含一个时区,因此它会自动正确存储并且不需要转换。当将 DateTime 显示为字符串时,PC 将使用 PC 时区设置将 UTC 存储时间转换为本地时间。仅当您想在与本地 PC 时区设置不同的时区中显示时才进行转换。从字符串转换为 DateTime 时,在未指定时区时使用 PC 时区设置。
  • @jdweng - 不正确。如果没有标志,DateTime.Parse 会将给定的时间戳调整为用户的本地时区,而不是 UTC。您可以检查.Kind 的结果,看到它会是Local
  • 马特:你说的正是我所说的。它只是看起来好像时间已调整为本地时间,但计算机中的实际存储始终是UTC。如果您更改计算机上的时区设置,计算机不会更改存储在计算机中的实际时间,只是更改其显示方式。从标准时间到夏令时时也会发生同样的情况。时间没有改变,只是时间的显示方式。
  • 永远不要将 DataTime 转换为另一个 Timezone,否则会产生问题。转换一词是个问题。应始终使用捕获数据的时区输入日期时间。如果输入数据的计算机不在同一时区,请确保在输入数据时包括时区。如果您需要在不同的时区显示 DateTime 对象,那么计算机时区设置只能在不同的时区显示,切勿将 DateTime 转换为另一个时区。
  • @jdweng - 感谢您的热情,但您所说的一些事情是不正确的。不幸的是,我们对这些特定值是如何存储(文件、数据库等)一无所知——我们所知道的是,我们得到了一个 ISO8601 扩展格式的字符串,带有一个偏移量,我们将其解析为内存中的DateTime。 .Net 中的DateTime 对象确实始终保持其UTC 值。它有一个内部长整数,它是.Ticks.Kind 的组合。刻度是自0001-01-01 00:00:00 以来的 100ns 间隔数,但它们未调整为 UTC。

标签: c# datetime timezone utc timestamp-with-timezone


【解决方案1】:
DateTime dt = DateTime.Parse("2015-11-06T18:34:07+05:30",
               CultureInfo.InvariantCulture,
               DateTimeStyles.AdjustToUniversal);

或者:

DateTime dt = DateTime.ParseExact("2015-11-06T18:34:07+05:30",
                                  "yyyy-MM-dd'T'HH:mm:ssK",
                                  CultureInfo.InvariantCulture,
                                  DateTimeStyles.AdjustToUniversal);

或者:

DateTimeOffset dto = DateTimeOffset.Parse("2015-11-06T18:34:07+05:30",
                                          CultureInfo.InvariantCulture);
DateTime dt = dto.UtcDateTime;

或者:

DateTimeOffset dto = DateTimeOffset.ParseExact("2015-11-06T18:34:07+05:30",
                                               "yyyy-MM-dd'T'HH:mm:sszzz",
                                               CultureInfo.InvariantCulture);
DateTime dt = dto.UtcDateTime;

当然,如果您需要验证,还有TryParseTryParseExact 变体。

就个人而言,我建议将其保留为DateTimeOffset,而不是返回DateTime

还有Noda Time:

OffsetDateTimePattern pattern = OffsetDateTimePattern.ExtendedIsoPattern;
OffsetDateTime odt = pattern.Parse("2015-11-06T18:34:07+05:30").Value;
DateTimeOffset dto = odt.ToDateTimeOffset();
DateTime dt = dto.UtcDateTime;

【讨论】:

  • 如果字符串是“2015-11-06T18:34:07-02:30”会起作用吗?
  • 是的,这与ISO8601 扩展格式相同。另见RFC 3339
  • 小心 Matt 结果。它可能不正确。它正在进入时间,就好像它是进入通用时间而不是转换为通用时间的东西。例如,如果您在标准时间上午 8:00(-5 小时)在纽约市。使用 Matts 方法 结果将是当地时间下午 1:00(不是 UTC)。您确实想输入当地时间上午 8:00,但显示结果为下午 1:00。
  • @jdweng - 抱歉,这是不正确的。在我在这里展示的方法的所有结果中,dt 结果具有 UTC 值,并且具有DateTimeKind.UtcKind。在您的示例中,结果将是 1:00 PM UTC。 See demo code and results here.
  • 马特:我是对的。时间应始终以输入的时区输入。仅当以 UTC 收集时间时,您的代码才是正确的。如果您想查看 UTC 时间,然后以 UTC 显示时间,请不要转换。如果您在美国东部标准时间上午 5:00 收集数据,则输入时间为美国东部标准时间上午 5:00 或世界标准时间上午 10:00。不要将时间输入为 5:00 AM UTC,这是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-11
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多