C#转换带UTC标识的yyyy-MM-dd hh:mm:ss字符串为DateTime报错
报错根因
- 直接调用
DateTime.Parse失败:该方法默认使用当前线程关联的区域格式规则解析,默认规则无法识别字符串尾部的UTC文本作为有效时区标识,解析到索引20位置(即UTC起始位置)时匹配失败,抛出格式错误。 - 调用
DateTime.TryParseExact失败:存在两处参数错误:- 格式字符串中小时段使用了12小时制标识
hh,但待解析时间的小时值14属于24小时制取值范围,格式匹配直接失败 - 传入
DateTimeStyles.None参数时,解析逻辑不会对UTC标识做时区适配,即便格式匹配成功,也无法正确标记时间的Kind属性,后续做时间转换时容易出现时区偏差
注意:hh和HH是C#时间格式中极易混淆的标识:hh对应12小时制小时,取值范围01-12;HH对应24小时制小时,取值范围00-23
- 格式字符串中小时段使用了12小时制标识
可行转换方案
方案1:精确格式匹配解析(推荐,稳定性最高)
修正格式字符串的小时标识为24小时制HH,同时调整DateTimeStyles参数为DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,解析后得到的DateTime对象会自动标记Kind = DateTimeKind.Utc,不会出现时区偏移问题,代码如下:
DateTime dt; var parseSuccess = DateTime.TryParseExact( "2022-04-17 14:46:31 UTC", "yyyy-MM-dd HH:mm:ss 'UTC'", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out dt );
执行成功后dt的值为2022/4/17 14:46:31,Kind属性为Utc。
方案2:替换UTC标识为标准偏移格式后解析
将字符串尾部的UTC替换为通用的UTC偏移标识+00:00,即可使用标准解析逻辑处理,无需自定义完整格式串:
var timeStr = "2022-04-17 14:46:31 UTC"; var date = DateTime.Parse( timeStr.Replace("UTC", "+00:00"), CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal );
方案3:通过DateTimeOffset中转解析
如果需要后续做跨时区的时间计算,可先用DateTimeOffset做精确格式匹配,再转换为UTC类型的DateTime对象,时区精度更高:
DateTimeOffset dtOffset; DateTimeOffset.TryParseExact( "2022-04-17 14:46:31 UTC", "yyyy-MM-dd HH:mm:ss 'UTC'", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dtOffset ); DateTime dt = dtOffset.UtcDateTime;
内容的提问来源于stack exchange,提问作者Vlad Breabăn
相关产品推荐
相关产品推荐

