我找到了如何将 DateTime 转换为 ISO 8601 格式,但没有关于如何在 C# 中执行相反的操作。
我有 2010-08-20T15:00:00Z
,我想把它变成一个 DateTime
对象。
我可以自己分离字符串的各个部分,但对于已经成为国际标准的东西来说,这似乎需要做很多工作。
此解决方案利用 DateTimeStyles 枚举,它也适用于 Z。
DateTime d2 = DateTime.Parse("2010-08-20T15:00:00Z", null, System.Globalization.DateTimeStyles.RoundtripKind);
这完美地打印了解决方案。
尽管 MSDN 说“s”和“o”格式反映了标准,但它们似乎只能解析它的有限子集。如果字符串包含时区规范,尤其是它是一个问题。 (对于基本的 ISO8601 格式或降低精度的格式,它都不是——但这不完全是你的情况。)这就是为什么我在解析 ISO8601 时使用自定义格式字符串的原因。目前我首选的片段是:
static readonly string[] formats = {
// Basic formats
"yyyyMMddTHHmmsszzz",
"yyyyMMddTHHmmsszz",
"yyyyMMddTHHmmssZ",
// Extended formats
"yyyy-MM-ddTHH:mm:sszzz",
"yyyy-MM-ddTHH:mm:sszz",
"yyyy-MM-ddTHH:mm:ssZ",
// All of the above with reduced accuracy
"yyyyMMddTHHmmzzz",
"yyyyMMddTHHmmzz",
"yyyyMMddTHHmmZ",
"yyyy-MM-ddTHH:mmzzz",
"yyyy-MM-ddTHH:mmzz",
"yyyy-MM-ddTHH:mmZ",
// Accuracy reduced to hours
"yyyyMMddTHHzzz",
"yyyyMMddTHHzz",
"yyyyMMddTHHZ",
"yyyy-MM-ddTHHzzz",
"yyyy-MM-ddTHHzz",
"yyyy-MM-ddTHHZ"
};
public static DateTime ParseISO8601String ( string str )
{
return DateTime.ParseExact ( str, formats,
CultureInfo.InvariantCulture, DateTimeStyles.None );
}
如果您不介意解析无 TZ 字符串(我愿意),您可以添加一个“s”行来大大扩展涵盖的格式更改的数量。
formats
数组中添加 "yyyyMMdd"
以将精度降低到几天,因为有时 RFC 5545 RRULE 将依赖 DTSTART 来提供时间。
K
允许您将不同的时区处理组合在一起。我在 stackoverflow.com/a/31246449/400547 有一个更广泛的变体,但它是否过于广泛(接受有效的 ISO 8601 但未在更常见的配置文件中使用的东西)但它确实显示了 K
如何将大小减少三分之一。
using System.Globalization;
DateTime d;
DateTime.TryParseExact(
"2010-08-20T15:00:00",
"s",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal, out d);
这是一个更适合我的版本(LINQPad 版本):
DateTime d;
DateTime.TryParseExact(
"2010-08-20T15:00:00Z",
@"yyyy-MM-dd\THH:mm:ss\Z",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal,
out d);
d.ToString()
生产
true
8/20/2010 8:00:00 AM
完全匹配 ISO 字符串的格式以使 TryParseExact
起作用似乎很重要。我猜Exact就是Exact,这个答案对大多数人来说都是显而易见的,但无论如何......
就我而言,Reb.Cabin 的回答不起作用,因为我的输入与下面的“值”略有不同。
值:2012-08-10T14:00:00.000Z
毫秒内有一些额外的 000,可能还有更多。
但是,如果我在格式中添加一些 .fff
,如下所示,一切都很好。
格式字符串:@"yyyy-MM-dd\THH:mm:ss.fff\Z"
在 VS2010 立即窗口中:
DateTime.TryParseExact(value,@"yyyy-MM-dd\THH:mm:ss.fff\Z", CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal, out d);
真的
您可能还必须使用 DateTimeStyles.AssumeLocal
,具体取决于您的时间所在的区域...
AssumeUniversal
更改为 AdjustToUniversal
。
这在 LINQPad4 中运行良好:
Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00Z"));
Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00"));
Console.WriteLine(DateTime.Parse("2010-08-20 15:00:00"));
DateTime.ParseExact(...)
允许您告诉解析器每个字符代表什么。
DateTime d2= DateTime.Parse("2010-08-20T15:00:00Z", null, DateTimeStyles.RoundtripKind);
的编辑解决方案似乎运行良好。DateTimeStyles.RoundtripKind?
MSDN 描述的人都是空白的。2018-06-19T14:56:14.123Z
被解析为本地时间,而不是 UTC。我使用CultureInfo.InvariantCulture
而不是 null。DateTimeStyles.RoundTripKind
的详细信息,请参阅 stackoverflow.com/q/39572395/2014893