C# 如何解决DateTimeInvalidLocalFormat错误;UTC日期时间正以仅适用于本地时间的格式转换为文本;?

C# 如何解决DateTimeInvalidLocalFormat错误;UTC日期时间正以仅适用于本地时间的格式转换为文本;?,c#,datetime,C#,Datetime,虽然执行了ToString(),但在调试过程中我遇到了此错误: UTC日期时间转换为文本的格式仅为 适合当地时间。打电话时可能会发生这种情况 使用“z”格式说明符的DateTime.ToString,该说明符将包括 输出中的本地时区偏移。在这种情况下,使用“Z” 格式说明符,指定UTC时间,或使用“o”格式 字符串,这是在文本中持久化日期时间的推荐方法。 当传递要序列化的日期时间时,也会发生这种情况 XmlConvert或数据集。如果使用XmlConvert.ToString,请传入 XmlDa

虽然执行了ToString(),但在调试过程中我遇到了此错误:

UTC日期时间转换为文本的格式仅为 适合当地时间。打电话时可能会发生这种情况 使用“z”格式说明符的DateTime.ToString,该说明符将包括 输出中的本地时区偏移。在这种情况下,使用“Z” 格式说明符,指定UTC时间,或使用“o”格式 字符串,这是在文本中持久化日期时间的推荐方法。 当传递要序列化的日期时间时,也会发生这种情况 XmlConvert或数据集。如果使用XmlConvert.ToString,请传入 XmlDateTimeSerializationMode.RoundtripKind以正确序列化。如果 使用DataSet,将DataColumn对象上的DateTimeMode设置为 DataSetDateTime.Utc

在我刚刚开始开发的应用程序中,很多地方都使用这种格式。那我该怎么办呢?用Z替换zzz

更新1: 传递给我的分机的日期时间被初始化为:

DateTimeCreated = DateTime.UtcNow;
奇怪的是,如果我将其他一些DateTime对象传递给这个扩展,我不会收到任何错误/警告。

它只是一个绿色警告


因此,当您似乎知道自己在做什么时,您只需理解消息(正确),并标记复选框以在将来忽略此警告。

正如DateTimeInvalidLocalFormat错误所解释的那样,属性种类设置为“Utc”的DateTime无法将日期值转换为定义日期格式的字符串。即使此错误只是一个警告,并且您的代码仍然可以工作,但在执行此操作后得到的结果日期字符串将不正确。这意味着,如果您将日期转换为字符串,并尝试再次将其解析为DateTime,则生成的DateTime值将与原始DateTime值不同。差异将与UTC时间的时区偏移量一样大。这是一个严重错误,不应忽略,尤其是当您的本地时间与UTC时间不匹配时

例如:

在本例中,我假设本地时区比UTC时间提前2小时

DateTime yourLocalTime = DateTime.Now;    // => 2020-05-15 08:00:00 => yourLocalTime.Kind = Local
DateTime yourTimeInUTC = DateTime.UtcNow; // => 2020-05-15 06:00:00 => yourTimeInUTC.Kind = Utc,  note hours, e.g. 6 vs 8

string dateFormat = "yyyy-MM-ddTHH:mm:sszzz";

string testDateLocal = yourLocalTime.ToString( dateFormat ); // 2020-05-15T08:00:00+02:00 - This is correct date and time
string testDateUtc = yourTimeInUTC.ToString( dateFormat );   // 2020-05-15T06:00:00+02:00 - This date and time is 2 hours behind your actual date and time
要使用日期格式正确打印日期和时间字符串,必须首先将UTC日期和时间转换为本地日期和时间:

string testDateUtc2 = yourTimeInUTC.ToLocalTime().ToString( dateFormat ); // 2020-05-15T08:00:00+02:00 - This is correct date and time
要修复代码,应在方法中添加对本地时间的转换:

public static string ToInterfaceString(this DateTime value)
{
    return value != DateTime.MinValue ? value.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:sszzz") : string.Empty;
}
您还可以通过将日期格式说明符“zzz”替换为“Z”来打印UTC日期和时间,而不是本地日期和时间。但是,在这种情况下,如果传递给方法的日期时间不是UTC类型,而是本地类型,则在转换时会遇到类似的问题,因此,在生成字符串之前,必须始终将其转换为UTC:

public static string ToInterfaceString(this DateTime value)
{
    return value != DateTime.MinValue ? value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") : string.Empty;
}
也可以使用日期格式说明符“o”在不进行转换的情况下打印日期和时间,但生成的日期字符串格式将根据提供的日期时间类型而有所不同,并且此日期格式还包括毫秒

public static string ToInterfaceString(this DateTime value)
{
    return value != DateTime.MinValue ? value.ToString("o") : string.Empty;
}

此异常在ToString()方法内部引发和捕获,因此应用程序将继续进一步运行。它是唯一显示此信息的调试器

它最初可能看起来像一个警告,仅在调试时可见,但实际上,只有在计算机时区为UTC时,此代码才会生成有效结果(在这种情况下似乎也不会出现内部异常)。例如,如果您的本地时区偏移量为UTC+02,则结果如下:

new DateTime(2020,7,30,11,22,33, DateTimeKind.Utc).ToString(@"yyyy-MM-dd\THH:mm:sszzz");
在您的计算机上显示的是“2020-07-30T11:22:33+02:00”,这没有意义,因为结果显然应该将UTC偏移量设置为00:00

当然,这样的内部异常对于控制流来说是一件坏事,如果这种情况发生得太频繁,可能会影响应用程序的性能

为了避免无效的.ToString()结果和内部异常,您只需从给定的DateTime创建DateTimeOffset并为其调用.ToString()。因此,代码:

new DateTimeOffset(new DateTime(2020,7,30,11,22,33, DateTimeKind.Utc)).ToString(@"yyyy-MM-dd\THH:mm:sszzz");
将给出任何本地时区的预期结果“2020-07-30T11:22:33+00:00”


另一个建议是使用,它为DateTime和DateTimerOffset提供正确的结果。

Adrian,您想做什么?您想将
日期时间
转换为字符串表示形式,还是想将其与偏移量一起保存在某个位置?我需要将当前日期时间+某个偏移量(这是用户设置)转换为字符串。该字符串将成为csv消息的一部分。为什么不使用
o
格式说明符?正如这里所指出的,它符合ISO标准,允许您使用其他应用程序从csv文件导入日期。此外,
z
zz
zzz
都不建议用于
DateTime
类型。改用
K
。为
DateTimeOffset
类型保留z。每个说明符的备注中都包含了这一点。这是事实。这不是一个关键的问题。我注意到DateTime属性类型是UTC。对于这一点,只会出现错误。对于其他dateTime对象,我使用的种类是未指定的。这就是警告出现的原因吗?是的。它不适用于当地时间。我不太确定对
Z
的引用。也许这意味着
u
kan可以用作格式说明符,以附加
Z
以将字符串标记为UTC时间。但你不能在这里用这个。
new DateTimeOffset(new DateTime(2020,7,30,11,22,33, DateTimeKind.Utc)).ToString(@"yyyy-MM-dd\THH:mm:sszzz");