DateTime.TryParse中的奇怪行为

时间:2015-06-30 06:08:37

标签: c# .net

我试图解析DateTime字符串" 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类中的错误吗?

4 个答案:

答案 0 :(得分:3)

我理解您的观点并调试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框架代码很有趣。如果您有兴趣,请按照here中的步骤操作。

答案 1 :(得分:0)

如果您想要所需的结果:

  

5/5/2005 5:00:00 AM

AdjustToUniversal

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

将以下代码用作AdjustToUniversal

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

答案 2 :(得分:0)

DateTimeStyles.AdjustToUniversal是您正在寻找的。

答案 3 :(得分:0)

如果您希望它将其视为本地并将其转换为 UTC,则必须组合这些标志:

DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal

或者如果源已经是通用的并且您希望 DateTimeKind 为 UTC:

DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal

阅读更多关于 MSDN

<块引用>

调整通用

如果 s 包含时区偏移量,或者如果 s 不包含时区信息但样式包含 DateTimeStyles.AssumeLocal 标志,则该方法解析字符串,调用 ToUniversalTime 将返回的 DateTime 值转换为UTC,并将 Kind 属性设置为 DateTimeKind.Utc