如何以UTC格式打印DateTime?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何以UTC格式打印DateTime?相关的知识,希望对你有一定的参考价值。

我只是尝试以UTC等效时间格式打印DateTime。我究竟做错了什么?

var utcEpoch = DateTime.Parse("1970-01-01", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); //This specifies the time I provided is in UTC
Console.WriteLine(utcEpoch.ToString("yyyy-MM-dd HH:mm:ss zzz")); //This properly shows my UTC offset of -6, so it's not wrong
Console.WriteLine(utcEpoch.ToString("u")); //This just flat out seems wrong because it doesn't specify a timezone or offset in its output

> 1969-12-31 18:00:00 -06:00
> 1969-12-31 18:00:00Z

我期望看到最后一个1970-01-01 00:00:00Z

答案

我认为你误解了API正在做什么。

首先要注意的是,DateTimeStyles.AssumeUniversalDateTimeStyles.AssumeLocal都将返回DateTime,其中Kind = Local

> DateTime.Parse("1970-01-01 00:00:00", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).Kind
=> Local
> DateTime.Parse("1970-01-01 00:00:00", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal).Kind
=> Local

所以无论我们将获得当地约会。这意味着API很可能是为了从UTC日期获得本地时间。如果这是正确的,我们试试吧。

我在瑞典,所以我们在标准时间内是UTC + 1。因此,如果我使用DateTimeStyles.AssumeUniversal并放入今天的日期,我应该在今天的01:00获得当地日期。

在C#Interactive中运行:

> DateTime.Parse("2018-03-03", .CultureInfo.InvariantCulture, .DateTimeStyles.AssumeUniversal)
=> [2018-03-03 01:00:00]

意思是C#假设我输入的字符串是UTC,我希望它在本地,所以它“固定”了它。

AssumeLocal做同样的事情。

DateTime.Parse("2018-03-03", .CultureInfo.InvariantCulture, .DateTimeStyles.AssumeLocal)
=> [2018-03-03 00:00:00]

正如所料,我们现在将输入视为本地字符串并获得相同的值。

要获得UTC日期,您可以指定种类

DateTime.SpecifyKind(DateTime.Parse("2018-03-03", CultureInfo.InvariantCulture), DateTimeKind.Utc).ToString("o")
=> "2018-03-03T00:00:00.0000000Z"
另一答案

来自The Universal Sortable ("u") Format Specifier

虽然结果字符串应将时间表示为协调世界时(UTC),但在格式化操作期间不会执行原始DateTime值的转换。因此,在格式化之前,必须通过调用DateTime.ToUniversalTime方法将DateTime值转换为UTC。相反,DateTimeOffset值会自动执行此转换;在格式化操作之前无需调用DateTimeOffset.ToUniversalTime方法。

你的utcEpoch.Kind不是UTC,它是LocalDateTime's are triciker than you might think。你期望它会将UTC作为Kind财产归还,但事实并非如此。它返回Local

这种情况也在Phil Haack blog post上讨论过,Matt Johnson对此有一个很好的评论;

AssumeLocalAssumeUniversal都与输入字符串的解释方式有关。它们本身也不会改变输出类型。

默认输出类型是Local。要使它成为Utc,您可以使用AdjustToUniversal风格。

DateTimeStyles枚举是基于标志的,因此您可以通过某些有意义的方式将它们组合在一起。要实现您最初设置的目的(将输入解析为UTC并将其输出为UTC),那么您将使用:

DateTime utcDate = DateTime.Parse(“10/01/2006 19:30”,culture,DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);

正如其他人指出的那样,单独调用ToUniversalTime()也会起作用,但这在技术上更正确。

你也可以在referance source上看到它;

case 'u':   // Universal time in sortable format.
if (offset != NullOffset)
{
    // Convert to UTC invariants mean this will be in range
    dateTime = dateTime - offset;
}
else if (dateTime.Kind == DateTimeKind.Local)
{
    InvalidFormatForLocal(format, dateTime);
}

以上是关于如何以UTC格式打印DateTime?的主要内容,如果未能解决你的问题,请参考以下文章

如何将MySQL Datetime UTC转换为实际时区

在填充的数据表中将 datetime 列从 utc 转换为本地时间

如何以 UTC 获取当前时间(现在)?

将存储在mysql(utc格式)中的momentjs datetime格式化为Local DateTime

如何在特定时区转换 DateTime?

如何在特定时区转换 DateTime?