NodaPatternConverter for Instant with numeric (unix) format in 2.x.x

As I can read on https://nodatime.org/2.0.x/userguide/migration-to-2 the support for numeric formatting of Instants has been removed.

Is there currently a way to create a NodaPatternConverter that will convert to a unix / ticks format and back?

SystemClock.Instance.GetCurrentInstant().ToString( "d", CultureInfo.InvariantCulture );

Results in the following exception:

NodaTime.Text.InvalidPatternException : The standard format "d" is not valid for the NodaTime.Instant type.

The solution based on Jon's suggestion I've ended up implementing:

public class InstantUnixTicksConverter : NodaConverterBase<Instant>
{
    protected override Instant ReadJsonImpl( JsonReader reader, JsonSerializer serializer )
    {
        string text = reader.Value.ToString();

        if ( !long.TryParse( text, out var ticks ) )
        {
            throw new InvalidNodaDataException( $"Value \'{text}\'cannot be parsed as numeric format {reader.TokenType}." );
        }

        return Instant.FromUnixTimeTicks( ticks );
    }

    protected override void WriteJsonImpl( JsonWriter writer, Instant value, JsonSerializer serializer )
    {
        writer.WriteValue( value.ToUnixTimeTicks() );
    }
}
Jon Skeet
people
quotationmark

Well, you can implement IPattern<T> yourself. Your parser would just need to use long.Parse then call Instant.FromUnixTicks. The formatter would just need to call Instant.ToUnixTimeTicks and format the result. Ideally, do both of those in the invariant culture.

You can then pass that pattern to the NodaPatternConverter<T> constructor - or just implement JsonConverter directly, to be honest.

Note that this will only give you tick resolution, which matches 1.x but may lose data with 2.x values.

I'd strongly encourage you to move away from this format as soon as you can though.

people

See more on this question at Stackoverflow