ss2k
ss2k

Reputation: 1278

.NET Roundtrip timezone conversion mismatch (IsAmbiguousTime issue?)

This round trip fails I suspect due to the resultant middle time being ambiguous. Is there anything that can be done about this? It doesn't match the result of:

http://www.timeanddate.com/worldclock/converted.html?month=11&day=6&year=2011&hour=1&min=59&sec=0&p1=179&p2=75

Is that just coincidence that .NET pick one possibly ambiguous time and that web site picked the other and that was the one I expected back?

I recognize the solution is to store times in UTC, but I'm dealing with a legacy app.

public const string EASTERN_TIMEZONEID = "Eastern Standard Time";
public const string MOUNTAIN_TIMEZONEID = "Mountain Standard Time";

[TestMethod]
public void MountainToEasternToMountain_DaylightSavings_Test()
{
    DateTime originalTime = new DateTime(2011, 11, 5, 23, 59, 0);   //  November 5, 2011 - 11:59pm
    DateTime expectedMiddle = new DateTime(2011, 11, 6, 1, 59, 0);  //  November 6, 2011 - 1:59am
    DateTime expectedEnd = originalTime;                            //  November 5, 2011 - 11:59pm

    TimeZoneInfo easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById(EASTERN_TIMEZONEID);
    TimeZoneInfo mountainTimeZone = TimeZoneInfo.FindSystemTimeZoneById(MOUNTAIN_TIMEZONEID);

    var middleTime = TimeZoneInfo.ConvertTime(originalTime, mountainTimeZone, easternTimeZone);

    var isSourceAmbiguous = mountainTimeZone.IsAmbiguousTime(originalTime);
    var isMiddleAmbiguous = easternTimeZone.IsAmbiguousTime(middleTime);

    Assert.AreEqual(expectedMiddle, middleTime);

    var destTime = TimeZoneInfo.ConvertTime(middleTime, easternTimeZone, mountainTimeZone);

    var isMiddleSourceAmbiguous = easternTimeZone.IsAmbiguousTime(middleTime);
    var isDestAmbiguous = mountainTimeZone.IsAmbiguousTime(destTime);

    Assert.AreEqual(expectedEnd, destTime);
}     

Upvotes: 1

Views: 212

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1503280

This round trip fails I suspect due to the resultant middle time being ambiguous. Is there anything that can be done about this?

Not if you want to keep things in a DateTime representing local time, no. Fundamentally, you're losing data: there are two input values which map to the same output value, which obviously prohibits round tripping.

I'm assuming that being a legacy app prohibits the possibility of using Noda Time instead too, which allows all of this to be handled a bit more sensibly...

It's not clearer what the bigger picture is, but you won't be able to get away from the fact that converting from a local time (without offset) in one time zone to either another local time or to a universal time fundamentally has three possible outcomes:

  • 2 results: the local time occurred twice
  • 1 result: the local time was unambiguous
  • 0 results: the local time was skipped

Upvotes: 1

Related Questions