nodatime / nodatime.serialization

Serialization projects for Noda Time

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Different formats used in TypeConverters and serialization for Durations

lundmikkel opened this issue · comments

I love the new type converters in NodaTime 3.0, but the converter for Duration is giving me a headache.

There isn't an ISO 8601 format for Duration (the duration mention there is a Period), but I would have preferred that Noda Time at least used a consistent format.

Noda Time's DurationTypeConverter uses DurationPattern.Roundtrip with the format -D:hh:mm:ss.FFFFFFFFF, whereas NodaTime.Serialization's ConfigureForNodaTime() uses (a custom format equal to) DurationPattern.JsonRoundtrip with the format -H:mm:ss.FFFFFFFFF instead.

That means that in order to have a consistent format everywhere, we need to write code like this:

serializerSettings
    // Adds default serializers
    .ConfigureForNodaTime(DateTimeZoneProviders.Tzdb)

    // Change Duration format to match TypeConverter
    .Converters.Insert(0, new NodaPatternConverter<Duration>(DurationPattern.Roundtrip));

I personally prefer the standard round trip format with days, as it is much easier to understand by a human. But regardless of which format is chosen, I think the two formats should agree.

Ah, this is unfortunate. (When you say "NodaTime.Serialization" do you mean NodaTime.Serialization.JsonNet by the way? We have a few serialization packages now.)

While the inconsistency is definitely annoying, changing either of them would be a breaking change. A few other options:

  • Add another ConfigureForNodaTime overload or different method name that allows the duration pattern to be specified
  • Add a static property that is used when DurationTypeConverter is initialized

In terms of which format is preferred, we might want to look at the default serialization for TimeSpan, and additionally what the TypeConverter does for TimeSpan.

Any other options you can think of would be gratefully listened to :)

Yes, the NodaTime.Serialization.JsonNet.Extensions.ConfigureForNodaTime() method.

Extension methods like WithIsoIntervalConverter() and WithIsoDateIntervalConverter() could also be an option. So you would have a WithDurationRoundTripConverter() that replaced the existing one, making my code example above a bit more simple:

serializerSettings
    // Adds default serializers
    .ConfigureForNodaTime(DateTimeZoneProviders.Tzdb)

    // Change Duration format to match TypeConverter
    .WithDurationRoundTripConverter();

Right - WithDurationRoundTripConverter would definitely be an easy and non-breaking fix. Will transfer this issue to the serialization repo.

Alternatively, you could use the CompositePatternBuilder<T> to accept both formats in the TypeConverter. But I expect that would fail for ConvertTo 🤔

This is now slightly easier to do with NodaJsonSettings:

serializerSettings.ConfigureForNodaTime(new NodaJsonSettings { DurationConverter = new NodaPatternConverter<Duration>(DurationPattern.Roundtrip) })

... but adding a DurationRoundTripConverter would make it even easier:

serializerSettings.ConfigureForNodaTime(new NodaJsonSettings { DurationConverter = NodaConverters.DurationRoundTripConverter })

That's probably the solution we'll end up with - so I just need to add DurationRoundTripConverter and finally get round to adding some documentation for NodaJsonSettings.

This is now merged (but not released) - with a name of RoundtripDurationConverter, to be consistent with the other properties.