简体   繁体   中英

Strange Behaviour in DateTime.TryParse

I'm trying to Parse a DateTime String "5-5-5-5" with

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

I expect this to be converted to

5/5/2005 5:00:00 AM 

But instead it gets converted to

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

Looks like its interpreting the supplied datetime as GMT. Which is a bit counter-intuitive since I've already specified the AssumeLocal flag. Is this a bug in the DateTime class?

I understand your point and debug the dot net framework code to find out what is happening in the background.

TryParse method is ignoring DateTimeStyles.AssumeLocal flag and Only AdjustToUniversal flag is processed.

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

On the other hand TryParseExact method is correctly implemented and it has all the required logic to handle DateTimeStyles.AssumeLocal flag. See how additional case is handled in this implementation.

            // 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;
            }

On side note, It is fun debugging Dot Net framework code. If you are interested then follow steps from here .

If you want the desired result as :

5/5/2005 5:00:00 AM

AdjustToUniversal :

Date and time are returned as a Coordinated Universal Time (UTC). If the input string denotes a local time, through a time zone specifier or AssumeLocal, the date and time are converted from the local time to UTC. If the input string denotes a UTC time, through a time zone specifier or AssumeUniversal, no conversion occurs. If the input string does not denote a local or UTC time, no conversion occurs and the resulting Kind property is Unspecified. This value cannot be used with RoundtripKind.

use the below code as AdjustToUniversal :

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

DateTimeStyles.AdjustToUniversal正是您要找的。

When time zone is NOT specified, you must explicitly indicate the time zone using AssumeLocal or AssumeUniversal and then convert it to UTC using AdjustToUniversal :

DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal

or

DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal

Read more on MSDN and pay attention to the last sentence:

AdjustToUniversal :

If the input string denotes a local time , through a time zone specifier or AssumeLocal , the date and time are converted from the local time to UTC .

If the input string denotes a UTC time , through a time zone specifier or AssumeUniversal , no conversion occurs .

If the input string does not denote a local or UTC time, no conversion occurs and the resulting Kind property is Unspecified.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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