6

I am making a prototype project of NodaTime compared to BCL's DateTime, but executing this result gives me recursionLimit exceeded error.

Recursion limit exceeded

This is the function I am using to JSONify my viewmodel. The error happens after this function returns.

    [HttpPost]
    public JsonResult GetDates(int numOfDatesToRetrieve)
    {
        List<DateTimeModel> dateTimeModelList = BuildDateTimeModelList(numOfDatesToRetrieve);

        JsonResult result = Json(dateTimeModelList, JsonRequestBehavior.AllowGet);
        return result;
    }

My view model is built properly when I inspected it. Here is the code for my view model.

public class DateTimeModel
{
    public int ID;

    public LocalDateTime NodaLocalDateTimeUTC;
    public LocalDateTime NodaLocalDateTime
    {
        get
        {
            DateTimeZone dateTimeZone = DateTimeZoneProviders.Bcl.GetZoneOrNull(BCLTimezoneID);

            //ZonedDateTime zonedDateTime = NodaLocalDateTimeUTC.InUtc().WithZone(dateTimeZone);

            OffsetDateTime offsetDateTime = new OffsetDateTime(NodaLocalDateTimeUTC, Offset.Zero);
            ZonedDateTime zonedDateTime = new ZonedDateTime(offsetDateTime.ToInstant(), dateTimeZone);
            return zonedDateTime.LocalDateTime;
        }
    }

    public OffsetDateTime NodaOffsetDateTime;

    public DateTime BclDateTimeUTC;
    public DateTime BclLocalDateTime
    {
        get
        {
            DateTime utcDateTime = DateTime.SpecifyKind(BclDateTimeUTC, DateTimeKind.Utc);
            TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(BCLTimezoneID);
            DateTime result = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);
            return result;
        }
    }

    public DateTimeOffset BclDateTimeOffset;
    //public int Offset;
    public string OriginalDateString;
    public string BCLTimezoneID;
}

I am sure that the NodaTime objects are not serializing correctly because when I comment the code from the viewModel the JsonResult is able to execute.

I read this off this page NodaTime API Reference

Code in this namespace is not currently included in Noda Time NuGet packages; it is still deemed "experimental". To use these serializers, please download and build the Noda Time source code from the project home page.

So I downloaded and built the source code and replaced the dll's my project references but I don't know how to implement the JsonSerialization classes.

Can someone explain to me how to use NodaTime.Serialization.JsonNet classes to make my NodaTime objects serializable?

mac10688
  • 2,145
  • 2
  • 24
  • 37

2 Answers2

11

We don't currently have any support for JavaScriptSerializer: I suspect you'll have to use Json.NET for all your JSON serialization. The user guide page on serialization gives a little bit more information, but it does mostly assume you already know about Json.NET.

The good news is that Json.NET is pretty easy to use - you may well find it's as simple as:

var settings = new JsonSerializerSettings();
settings.ConfigureForNodaTime();
string json = JsonConvert.SerializeObject(model, settings);

(Or use JsonSerializer.)

As an aside, the way you're using the Noda Time types is a little odd to say the least - it may well be worth asking another question with details of what you're trying to achieve, and we can work out a more idiomatic way of doing it :)

Rob
  • 26,989
  • 16
  • 82
  • 98
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I was just making an example project that persists datetime from client -> server -> database and back again. So I can compare the BCL library to NodaTime? What is odd about my technique? If it is because I use properties, I just wanted them to be serializable. – mac10688 Feb 12 '13 at 13:59
  • @mac10688: It's the way you're dealing with the various types - you're going through a lot of hoops for conversions, but it's not clear to me what those conversions are meant to be achieving. The very fact that you've got a field called of `NodaLocalDateTimeUTC` is worrying - because a `LocalDateTime` isn't conceptually in any time zone. I'm keen to help you understand the concepts and types involved - partly because it may lead us to write better documentation :) – Jon Skeet Feb 12 '13 at 14:11
  • I see what you are saying. Is it that LocalDateTime doesn't have a 'Kind' property for a reason, and you think I shouldn't force it? I did this because I wanted to store the datetime in UTC and a timezoneID and with that information I would be able to construct the localized time when I pass it back to the client. In the same example I am also storing datetimeoffset. So maybe the best solution is to store datetimeoffset with the timezoneID. In my prototype project I ultimately want to see how nodatime and bcl differ in side by side comparisons (i.e. persisting DateTimes and manipulating them). – mac10688 Feb 12 '13 at 14:34
  • @mac10688: Yes. You should read up on all the different concepts in Noda Time - http://noda-time.googlecode.com/hg-history/1.0.x/docs/userguide/concepts.html and http://noda-time.googlecode.com/hg-history/1.0.x/docs/userguide/type-choices.html. It sounds like you should actually just be storing a `ZonedDateTime`, which can be stored as an `Instant` (using the `Ticks` property to get a `long` value) and a time zone ID. Of course you could convert to a `DateTimeOffset` (and time zone ID) if that's easier to store in the database. – Jon Skeet Feb 12 '13 at 14:36
  • Hi @JonSkeet: can u tell me what is the advantage of using Nodatime library instead of DotNet built-in datetime ? – Thomas Oct 30 '14 at 07:32
  • @Thomas: See http://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html – Jon Skeet Oct 30 '14 at 08:17
  • @JonSkeet:i have one more question about noda library. i am in situation where i need to fetch timezone id from browser and need to pass that timezone id to server side code and server side code will return current time based on timezone id. the problem is browser return timezone id like this way "India Standard Time or GMT Standard Time" and noda is not accepting this timezone id and i came to know noda will accept if we give timezone id like this way "Asia/Kolkata" or "Etc/GMT".how noda can parse browser returned timezone id and return current time based on that timezone id. – Thomas Oct 30 '14 at 09:07
  • @Thomas: If you have another question, you should ask it *as* a separate question - but there are lots of questions about obtaining time zone IDs from Javascript already. Search on Stack Overflow for those questions. (It's not at all clear where you're getting "India Standard Time" from anyway... "browser return timezone id" doesn't give much detail.) – Jon Skeet Oct 30 '14 at 09:42
  • @JonSkeet: Sorry to disturb you. i have posted a thread on the same already but looking for good answer. here is the url of my thread...if possible please see it and give your suggestion. here is the url http://stackoverflow.com/questions/26626798/nodatime-time-zone-related-issue-using-nodatime-library-c-sharp/26626997?noredirect=1#comment41904193_26626997 – Thomas Oct 30 '14 at 13:00
  • @Thomas: You still haven't explained there where you got the name from (or rather, *how* you got it from the browser). As I said, there are lots of *existing* Stack Overflow questions for getting tzdb IDs from Javascript. – Jon Skeet Oct 30 '14 at 13:44
  • @JonSkeet: sorry jon. i just edit my question a bit and please see my edit portion and then you can see i am achieving timezone id by js which is working with Noda after feeding timezone id to it. looking for your suggestion. thanks – Thomas Oct 30 '14 at 13:51
  • @Thomas: It sounds like you still haven't looked for *other* questions which give the answer you want. See http://stackoverflow.com/questions/6939685/get-client-time-zone-from-browser for example – Jon Skeet Oct 30 '14 at 14:16
  • @JonSkeet If you're curious where "Asia/Kolkata" comes from http://stackoverflow.com/a/26626997/397817 . It wasn't from the browser! – Stephen Kennedy Oct 30 '14 at 14:17
  • @StephenKennedy: Yup, it's where the OP got "Indian Standard Time" from which was confusing me, until he posted the code (now edited out)... – Jon Skeet Oct 30 '14 at 14:25
  • @JonSkeet: i just posted a new thread. here is url http://stackoverflow.com/questions/26655600/nodatime-how-to-parse-timezone-return-by-browser-by-nodatime-library where i explain my problem properly. just need your guide line. thanks – Thomas Oct 30 '14 at 14:27
  • @JonSkeet: would you mind to tell me syntax to get only date from Noda library like (dd/MM/yyyy) and as well as 12hrs & 24hrs format time from Noda Library. thanks – Thomas Oct 31 '14 at 07:25
  • 1
    @Thomas: Please don't ask questions in comments. Ask a *new question* if you really need to - but please read the relevant documentation first. (http://nodatime.org/1.3.x/userguide/core-types.html and http://nodatime.org/1.3.x/userguide/text.html to start with.) – Jon Skeet Oct 31 '14 at 07:33
3

Serialization is supported for JSON.NET in Noda Time 2.0+.

You'll need to install the package with NuGet:

> Install-Package NodaTime.Serialization.JsonNet

And then configure your serializer settings to use it. This won't work with the default serializer/deserializer - you need to configure one explicitly.

We chose to use one statically. Your usage may be different. Here is an example:

using Newtonsoft.Json;
using NodaTime;
using NodaTime.Serialization.JsonNet; // << Needed for the extension method to appear!
using System;

namespace MyProject
{
    public class MyClass
    {
        private static readonly JsonSerializerSettings _JsonSettings;

        static MyClass()
        {
            _JsonSettings = new JsonSerializerSettings
            {
                // To be honest, I am not sure these are needed for NodaTime,
                // but they are useful for `DateTime` objects in other cases.
                // Be careful copy/pasting these.
                DateFormatHandling = DateFormatHandling.IsoDateFormat,
                DateTimeZoneHandling = DateTimeZoneHandling.Utc,
            };

            // Enable NodaTime serialization
            // See: https://nodatime.org/2.2.x/userguide/serialization
            _JsonSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
        }

        // The rest of your code...
    }
}
jocull
  • 20,008
  • 22
  • 105
  • 149