如何以UTC格式打印DateTime?

时间:2018-03-03 17:57:27

标签: c# datetime timezone

我只是尝试以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

2 个答案:

答案 0 :(得分:1)

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

  

虽然结果字符串应将时间表示为Coordinated   世界时(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枚举是基于标志的,因此您可以将它们组合在一起   一些有意义的方法。实现您最初设定的目标   do(将输入解析为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);
}

答案 1 :(得分:1)

我认为你很难理解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"