This library adds support for NodaTime types to MessagePack C#.
This library is provided in NuGet.
Support for .NET Framework 4.5, .NET Framework 4.6.1, .NET Standard 1.6 and .NET Standard 2.0.
In the Package Manager Console -
Install-Package MessagePack.NodaTime
or download directly from NuGet.
To use the NodaTime resolver, you will have to add it to the composite resolver, as shown in the example below:
CompositeResolver.RegisterAndSetAsDefault(
BuiltinResolver.Instance,
AttributeFormatterResolver.Instance,
SourceGeneratedFormatterResolver.Instance,
NodatimeResolver.Instance,
DynamicEnumAsStringResolver.Instance,
ContractlessStandardResolver.Instance
);For more information on either MessagePack or NodaTime, please follow the respective links below.
This is a quick guide on a basic serialization and de-serialization of a NodaTime type.
Instant inst = new Instant();
var bin = MessagePackSerializer.Serialize(inst);
var res = MessagePackSerializer.Deserialize<Instant>(bin);
// inst == resInsant, LocalTime, LocalDate, LocalDateTime,Offset, OffsetDateTime, Period and ZonedDateTime
As per the MessagePack spec, when we serialize a NodaTime type of LocalDateTime, LocalDate or Instant, an extension type of -1 is received meaning it is a MessagePack timestamp.
Timestamp spec can be found here.
An example of this in C# is shown below:
LocalDateTime ldt = LocalDateTime.FromDateTime(DateTime.Now);
// This date is within the range for timestamp32
var localDateTimeBinary = MessagePackSerializer.Serialize(ldt);
// Once serialized we can expect the format to be [0xd6, -1, data] (format, extension type, data in bytes),
// and ‘localDateTimeBinary’ to be a byte array of size 6In the same way we can support serialization from NodaTime (eg, LocalDate) to MessagePack (timestamp), the same is applied for deserialization.
From a timestamp, we can deserialize into a LocalDate (if time part is 0), LocalDateTime or an Instant.
From the snippet of code in serialization, shown below is deserialization:
var res = MessagePackSerializer.Deserialize<LocalDateTime>(localDateTimeBinary);❗ Deserializing a LocalDateTime into a LocalDate, will not work if the time value is not 0.
While NodaTime supports nanoseconds accuracy, we currently do not. The lowest common level of precision between us and NodaTime is ticks. This means our serialization and deserialization process truncates at 100 nanoseconds because 100ns = 1 tick. Below are two examples explaining this:
LocalDateTime ldt = new LocalDateTime(2016, 08, 21, 0, 0, 0, 0).PlusNanoseconds(1)
var localDateTimeBinary = MessagePackSerializer.Serialize(ldt);
var result MessagePackSerializer.Deserialize<LocalDateTime>(localDateTimeBinary);
// ldt != result, nanosecond accuracy is lost in process.LocalDateTime ldt = new LocalDateTime(2016, 08, 21, 0, 0, 0, 0).PlusNanoseconds(100);
var localDateTimeBinary = MessagePackSerializer.Serialize(ldt);
var result = MessagePackSerializer.Deserialize<LocalDateTime>(localDateTimeBinary);
// ldt == result, returns truncated value equal to 1 tick.In the base MessagePack library, DateTime values are converted to UTC before being serialized. While using our library, you must specify DateTimeKind as UTC before serializing when using DateTime and the LocalDateTime type, and expect it as UTC when deserializing.
As explained previously, we use the timestamp format for some of our serialized NodaTime types. The timestamp format is interoperable with MessagePack for C#, the official MsgPack library and any other MessagePack implementations that support the extension type of -1.
TBC
This project is licensed under the MIT License - see the LICENSE.md file for details

