【问题标题】:c# convert datetime object to iso 8601 stringc# 将 datetime 对象转换为 iso 8601 字符串
【发布时间】:2017-06-27 19:25:25
【问题描述】:

我正在尝试将 DateTime 对象转换为 ISO8601 字符串,但总是得到错误的结果。我在stackoverflow上环顾四周,但找不到正确的解决方案。

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

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

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

我试过了:

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 日期时间格式中列出的内容,但它也没有显示时间。

谢谢!

【问题讨论】:

  • 那么你得到了什么结果?我强烈建议明确指定不变的文化,你的.sss 应该是.fff,但除此之外它看起来还可以。
  • 我检查了“其他”列表,但“yyyy-MM-ddTHH\\:mm\\:ss.fffffffzzz”给我一个运行时错误,指出它需要使用 Z,而不是一个z。不太明白错误信息。但如前所述,我没有得到“时间”。并且格式与原始 js 转换字符串不太一样。
  • 根据 Max,看起来错过时间的原因是我无缘无故地添加日期。但是我仍然在毫秒内再次复制确切的字符串。
  • 这个问题的替代方法是如何让 Newtonsoft 不将日期时间字符串转换为它似乎自动执行的日期时间。所以我可以使用原始字符串。

标签: c# datetime iso8601


【解决方案1】:

观察:

// 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 - 通过将Z 附加到DateTimeKind.Utc 的输出或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

【讨论】:

  • 发送!日期,max 指出它不需要。至于 sssZ,我是从 toISOString js 字符串规范中得到的。 Tx 以获得完整的解释。
  • 当谈到格式化说明符(令牌,无论你怎么称呼它们),几乎每种语言和库都会略有不同。始终检查文档。
  • .ToString("o") 确实是最简单的方法,您也不需要在那里指定文化。根据the Microsoft docs:“由于“O”或“o”标准格式说明符符合国际标准,因此使用说明符的格式化或解析操作始终使用不变的文化和公历。”
【解决方案2】:

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

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

2017 年 6 月 26 日晚上 8:45:00

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

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

解决方案:

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

2017-06-26T20:45:00.0700000Z

【讨论】:

  • 当我尝试 Time.Date.ToString("o") 我得到“2017-06-26T00:00:00.0000000Z”...哦等等..当我删除 DATE 部分..我抓紧时间。
  • 好的,有了这个。但我怎么能得到相同的呢?这意味着我需要与原始字符串相同!我试过 strTime = theTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.sssZ");但它缺少你所说的毫秒......我需要在哈希中使用原始字符串,所以我需要完全相同。
  • 另外问题是问题开头列出的原始 DATETIME UTC 包含毫秒。我只复制了 c# datetime var 中的内容。
  • @user1161137 我给出了答案。您的日期时间具有毫秒精度,我以毫秒精度将其打印回给您。 Solution 下时间戳中“0700000Z”中的“07”是毫秒列中的“70”。
  • theTime.ToString("o") 没有返回我问的内容。这正是它的原样。 "yyyy-MM-dd'T'HH:mm:ss.fffK" 确实返回了它......马特识别并解释了......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
  • 2011-07-19
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多