I'm developing for .NET Core, so I'm using the unstable latest alpha of Noda Time (2.0.0-alpha20160729). Data is being handled with JSON.
I will be accepting user input for a date of birth field, and I want to support multiple input formats in case the user can't follow directions gets confused. For example, I want to accept both MM-dd-yyyy
and M/d/yy
, among others.
The serialization docs specifically state the following:
Custom converters can be created easily from patterns using NodaPatternConverter.
I cannot for the life of me figure out how to do this though. From what I understand, I will need to implement both NodaPatternConverter<LocalDate>
itself, IPattern<LocalDate>
for parsing, and Action<T>
for validation.
I started writing IPattern.Parse<LocalDate>
, but that function returns ParseResult<LocalDate>
which is apparently inaccessible. It cannot be instantiated or used in any way that I have found. I'm therefore stuck.
How do I properly create a custom JSON converter for Noda Time?
Firstly, this doesn't sound like the right thing to do in a JSON converter. If you're accepting user input directly in your JSON, that should be treated as a string, and parsed later, IMO. JSON is a machine-to-machine format, not a human-to-machine format. Assuming this is a web app, you might want to use moment.js to parse the data at the client and reformat it as ISO-8601. Alternatively, deserialize it as a string and then convert it in your server-side code.
Anyway, for a JSON converter you only need to implement IPattern<LocalDate>
- you don't need to implement NodaPatternConverter<LocalDate>
as that already exists. You just need:
var pattern = ...;
var converter = new NodaPatternConverter<LocalDate>(pattern);
Now, to implement your pattern, you probably want to actually create it out of existing patterns - write an implementation which delegates to one IPattern<LocalDate>
after another until the result is a ParseResult<T>
which is successful - or return the final unsuccessful ParseResult<T>
. Note that ParseResult<T>
isn't inaccessible - but you can't (currently) create your own instance of it. That's something I should probably address, but in this case you don't really need to.
The code you need already exists but isn't exposed - you want the Parse
part of CompositePattern
. To implement the Format
part, you could just use the first of your patterns to format the value... if you even need to.
See more on this question at Stackoverflow