c# 将日期时间对象转换为 iso 8601 字符串

c# convert datetime object to iso 8601 string

我正在尝试将 DateTime 对象转换为 ISO8601 字符串,但总是得到错误的结果。我在 Whosebug 上四处寻找,但找不到合适的解决方案。

我从日期时间字符串“2017-06-26T20:45:00.070Z”开始,它由 newtonsoft 从 json 反序列化并转换为 C# 中的 DateTime 对象,相当于:

var theTime = new DateTime(2017, 6, 26, 20, 45, 00, 70, DateTimeKind.Utc);

现在我需要将那个时间转换回它的原始 UTC 格式字符串以在另一个算法中使用它,但我尝试的每个转换都不会 return 将它转换为原始字符串。不知道我做错了什么。

我试过:

var newTime = theTime.UtcNow.ToString("o");
// returns "2017-06-26T00:00:00.0000000Z"

var newTime2 = theTime.Date.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.sssZ");
// returns "2017-06-26T00:00:00.00Z"

我做错了什么?我想要等效于 js 使用 toISOString() 所做的事情,这是我在 newTime2 日期时间格式中列出的内容,但它也没有显示时间。

谢谢!

问题是您使用 UTCUniversalTime 等文化标准会失去准确性。如果你只是打印你的 DateTime:

var theTime = new DateTime(2017, 6, 26, 20, 45, 00, 70, 
    DateTimeKind.Utc);
Console.WriteLine(theTime);

6/26/2017 8:45:00 PM

您可以阅读有关此问题的更多信息here

解决方案是不使用任何 "culture"。 (例如,UniversalTimeUtcNow)。这些文化标准从不包括毫秒......因为没有一种文化让人们真正关心毫秒。

解法:

var newTime = theTime.ToString("o");
Console.WriteLine(newTime);

2017-06-26T20:45:00.0700000Z

观察:

// Your input
DateTime dt = new DateTime(2017, 6, 26, 20, 45, 0, 70, DateTimeKind.Utc);

// ISO8601 with 7 decimal places
string s1 = dt.ToString("o", CultureInfo.InvariantCulture);
//=> "2017-06-26T20:45:00.0700000Z"

// ISO8601 with 3 decimal places
string s2 = dt.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", CultureInfo.InvariantCulture);
//=> "2017-06-26T20:45:00.070Z"

几件事:

  • 不要在格式字符串中使用 Z。那不是 valid format specifier,所以它只是作为一个字符来输出。无论输入日期时间的 .Kind 设置如何,它都会出现在每个字符串中。

  • DateTime 一起使用 K - 通过在 DateTimeKind.Utc 的输出中附加 Z 来正确传达 .Kind ,或 DateTimeKind.Local 的 UTC 偏移量,或 DateTimeKind.Unspecified.

  • 的偏移量
  • 尽管 T 将作为字符输出,因为它不是有效的格式说明符,但我建议始终明确说明这些内容,所以更喜欢 'T'.

  • 使用fff 将始终返回三位小数(毫秒)。如果您希望在零时省略小数点,请改用 FFF。您使用的 sss 无效。

  • 传递 CultureInfo.InvariantCulture 是一个很好的做法,因为它可以帮助您避免当前文化可能使用不同日历系统的问题。例如 ar-SA 使用 UmAlQuraCalendar,而不是 ISO 8601 要求的公历。

  • 在您尝试的代码中,您调用了 theTime.UtcNow - 无法编译。 UtcNow 是静态 属性,不是实例 属性。

  • 同样在您调用的代码中 theTime.Date.ToUniveralTime() - 也不要那样做。 .Date 会将时间分量设置为零,而 .ToUniversalTime() 将无效,因为输入值已经有 DateTimeKind.Utc.