繁体   English   中英

DateTime.TryParse 中的奇怪行为

[英]Strange Behaviour in DateTime.TryParse

我正在尝试解析日期时间字符串“5-5-5-5”

DateTime.TryParse("5-5-5-5", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out result);

我希望这可以转换为

5/5/2005 5:00:00 AM 

但相反,它被转换为

5/5/2005 10:30:00 AM.

看起来它将提供的日期时间解释为 GMT。 这有点违反直觉,因为我已经指定了AssumeLocal标志。 这是DateTime类中的错误吗?

我理解您的观点并调试 dot net 框架代码以了解后台发生的情况。

TryParse方法忽略DateTimeStyles.AssumeLocal标志并且只处理AdjustToUniversal标志。

if ((styles & DateTimeStyles.AdjustToUniversal) != 0) {
            return (AdjustTimeZoneToUniversal(ref result));
        }
        return (AdjustTimeZoneToLocal(ref result, bTimeOnly));

另一方面, TryParseExact方法已正确实现,它具有处理DateTimeStyles.AssumeLocal标志所需的所有逻辑。 查看此实现中如何处理其他案例。

            // If AssumeLocal or AssumeLocal is used, there will always be a kind specified. As in the
            // case when a time zone is present, it will default to being local unless AdjustToUniversal
            // is present. These comparisons determine whether setting the kind is sufficient, or if a
            // time zone adjustment is required. For consistentcy with the rest of parsing, it is desirable
            // to fall through to the Adjust methods below, so that there is consist handling of boundary
            // cases like wrapping around on time-only dates and temporarily allowing an adjusted date
            // to exceed DateTime.MaxValue
            if ((styles & DateTimeStyles.AssumeLocal) != 0) {
                if ((styles & DateTimeStyles.AdjustToUniversal) != 0) {
                    result.flags |= ParseFlags.TimeZoneUsed;
                    result.timeZoneOffset = TimeZoneInfo.GetLocalUtcOffset(result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime);
                }
                else {
                    result.parsedDate = DateTime.SpecifyKind(result.parsedDate, DateTimeKind.Local);
                    return true;
                }
            }
            else if ((styles & DateTimeStyles.AssumeUniversal) != 0) {
                if ((styles & DateTimeStyles.AdjustToUniversal) != 0) {
                    result.parsedDate = DateTime.SpecifyKind(result.parsedDate, DateTimeKind.Utc);
                    return true;
                }
                else {
                    result.flags |= ParseFlags.TimeZoneUsed;
                    result.timeZoneOffset = TimeSpan.Zero;
                }
            }
            else {
                // No time zone and no Assume flags, so DateTimeKind.Unspecified is fine
                Contract.Assert(result.parsedDate.Kind == DateTimeKind.Unspecified, "result.parsedDate.Kind == DateTimeKind.Unspecified");
                return true;
            }

旁注,调试 Dot Net 框架代码很有趣。 如果您有兴趣,请按照此处的步骤操作。

如果你想要想要的结果:

2005/5/5 上午 5:00:00

调整到通用

日期和时间作为协调世界时 (UTC) 返回。 如果输入字符串表示本地时间,则通过时区说明符或 AssumeLocal,日期和时间将从本地时间转换为 UTC。 如果输入字符串通过时区说明符或 AssumeUniversal 表示 UTC 时间,则不会发生转换。 如果输入字符串不表示本地时间或 UTC 时间,则不会发生转换,并且生成的 Kind 属性为 Unspecified。 此值不能与 RoundtripKind 一起使用。

使用以下代码作为AdjustToUniversal

DateTime result;
dt= DateTime.TryParse("5-5-5-5" , CultureInfo.InvariantCulture,DateTimeStyles.AdjustToUniversal , out result);

DateTimeStyles.AdjustToUniversal正是您要找的。

当未指定时区时,您必须使用AssumeLocalAssumeUniversal明确指示时区,然后使用AdjustToUniversal将其转换为 UTC:

DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal

或者

DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal

MSDN上阅读更多内容并注意最后一句话:

调整到通用

如果输入字符串表示本地时间,则通过时区说明符或AssumeLocal将日期和时间从本地时间转换为 UTC

如果输入字符串通过时区说明符或AssumeUniversal表示UTC 时间,则不会发生转换

如果输入字符串不表示本地时间或 UTC 时间,则不会发生转换,并且生成的 Kind 属性为 Unspecified。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM