Importing list of dates from a timezone with Noda Time

213 views Asked by At

I need to import measured data (one datapoint each hour) and want to represent the dates with noda time. The series is affected by daylight saving transitions - and with those I have some issues.

I created some test dates with the daylight saving time changing days of 2016 (Europe/Berlin): (year, month, day, hour)

2016,3,27,0
2016,3,27,1
2016,3,27,3
2016,3,27,4
2016,10,20,0
2016,10,20,1
2016,10,20,2
2016,10,20,2
2016,10,20,3

Each line is incremented by one hour. The gap and the double data is dur to daylight saving time transition

I use the following code to test the import:

private void TestImport()
{
    List<ZonedDateTime> resultSet = new List<ZonedDateTime>();

    IDateTimeZoneProvider provider = DateTimeZoneProviders.Tzdb;
    DateTimeZone dtz = provider.GetZoneOrNull("Europe/Berlin");
    bool first = true;

    foreach (string line in File.ReadAllLines(@"C:\tmp\problemdates.txt"))
    {
        string[] split = line.Split(",".ToCharArray());
        LocalDateTime ldt = new LocalDateTime(Convert.ToInt32(split[0]), Convert.ToInt32(split[1]), Convert.ToInt32(split[2]), Convert.ToInt32(split[3]), 0);

        resultSet.Add(Convert2Zoned(ldt, dtz, ref first));
    }

    DataGrid_Results.DataContext =  return resultSet;
}


private ZonedDateTime Convert2Zoned(LocalDateTime ldt, DateTimeZone dtz, ref bool isFirstAmbigue)
{
    try
    {
        return ldt.InZoneStrictly(dtz);
    }
    catch (SkippedTimeException ex)
    {
        // rethrow
    }
    catch (AmbiguousTimeException ex)
    {
        if (isFirstAmbigue)
        {
            isFirstAmbigue = false;
            return ldt.InZone(dtz, Resolvers.CreateMappingResolver(Resolvers.ReturnEarlier, Resolvers.ThrowWhenSkipped));
        }
        else
        {
            isFirstAmbigue = true;
            return ldt.InZoneLeniently(dtz);
        }
    }
}

Edith: Here is a simple GUI application that executes the import

What I'd expected -

27.03. Hour 3: TickOfDay 7200... instead of 10800... because this is the second hour of the day

20.10. Hour 2: The second appearing should be TickOfDay 10800... instead of 7200... again, as it is one hour later than the first appearing. Also, Offset should be +01 instead of +02 from the second appearing on, as we are in wintertime again.

I'd also would have expected LocalDateTime to be "normalized" (e.g. 1:00, 2:00, 3:00 ...) but this migfht relate to the Offset ...

Thanks for your help,
Frank

2

There are 2 answers

3
Jorge Gomez On

My clock shows the local time in Berlin.

Something (A) happens when my clock shows 2016-03-27T00:00:00.

Something (B) happens when my clock shows 2016-03-27T03:00:00.

The elapsed time between (A) and (B) is 2 hours. It's the only "valid" expectation, because it's the truth.

The question is if we can represent this valid expectation with any software artifact. If not, the software is invalid, not the expectation.

2
Matt Johnson-Pint On

The .TickOfDay property on a ZonedDateTime or an OffsetDateTime is related to its LocalDateTime, which is timezoneless. It's not related to its instantaneous point in time, but rather the wall-clock time as displayed.

Therefore, the expectations you described are invalid. A local time of 03:00 is always going to have TickOfDay == 10800.

If you wanted to normalize these values such that 3:00 was identified as the second hour of the day, you'd have to first adjust them all to use the same offset - the one that was in effect at the start of the day.