2

I'm passing this DateTimeOffset 2016-08-01 09:30:00.0000000 -04:00 from my SQL Server database to FullCalendar. The events seem to be rendering but they are always 4 hours ahead. I want to note that it was doing the exact same thing when I was using datetime2 instead. I checked SQL Server and it's showing the correct current time so I'm not sure what the problem is.

Here's my FullCalendar implementation:

<script type="text/javascript">
    $(document).ready(function ()
    {
        $('#calendar').fullCalendar(
        {
            header:
            {
                left: 'prev,next today',
                center: 'title',
                right: 'month,agendaWeek,agendaDay'
            },
            editable: false,
            events: "/home/loadevents/"

        })
    });
</script>

ViewModel:

public class CalendarEventsViewModel
{
    //Properties have to conform to the following API standards
    //or the FullCalendar.js library will reject all incoming data.
    //http://fullcalendar.io/docs/event_data/Event_Object/

    public int id { get; set; }
    public string title { get; set; }
    public DateTimeOffset start { get; set; }
    public DateTimeOffset end { get; set; }
}

AcctionResult/Linq:

public ActionResult LoadEvents (DateTime start, DateTime end)
{

    IEnumerable<CalendarEventsViewModel> model =
    db.CalendarEvents
    .Select(r => new CalendarEventsViewModel
    {
        id = r.EventID,
        title = r.EventName,
        start = r.EventScheduleDateTime,
        end = r.EventScheduleDateTime,
    });


    return Json(model, JsonRequestBehavior.AllowGet);
}

Edit:

After a closer look with a breakpoint I've noticed that instead of pushing 2016-08-01 09:30:00.0000000 -04:00 to FullCalendar it's pushing 8/1/2016 09:30:00 AM yet it's still displaying as four hours ahead of my local time. I'm not sure if the offset is getting lost from the db in my linq statement even though I'm using the datetimeoffset in both the db and my viewmodel property. I also added more code above.

Edit 2:

It seems I was wrong and it's sending {8/1/2016 9:30:00 AM -05:00} so I'm not sure what the issue is just yet. My guess is that this might not conform to the FullCalendar requirements?

Edit 3:

In my database I have 2016-08-01 09:30:00.0000000 -04:00 stored. When it get's to the linq query it becomes 8/1/2016 9:30:00 AM -04:00 according to a debug. When the date/event is shown in FullCalendar.js it shows as four hours later than that at 1:30pm. I've got to be misunderstanding something about the offset but I don't know what.

Christopher Johnson
  • 635
  • 2
  • 7
  • 21
  • Have you made any progress with this? I am interested to see the outcome. Is it a personal project or for a client? If it's personal, do you have it in a public repository? I would quite like to have a look, timezone support is not something I have had the chance to play with yet in FC. – Ally Murray Aug 03 '16 at 13:00
  • It's a small project for a client. I haven't done anything since the last edit and I just got up. I'm sure all of the components are there for this to work I'm just missing something. – Christopher Johnson Aug 03 '16 at 15:00
  • Capture some of the actual JSON response via either the browser's F12 tools, or an HTTP tool like Fiddler. What does the JSON of the event data look like? My guess it it's returning the [old style format](http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx) instead of ISO8601. – Matt Johnson-Pint Aug 03 '16 at 16:38
  • Wasn't sure how to do that in Chrome so I tried Fiddler and this is all I could find `[{"id":1,"title":"Some Event","start":"\/Date(1470058200000)\/","end":"\/Date(1470058200000)\/"},{"id":2,"title":"Event 2","start":"\/Date(1471320000000)\/","end":"\/Date(1471320000000)\/"}]` – Christopher Johnson Aug 03 '16 at 18:00
  • @AllyMurray Since I can't comment on the FullCalendar Thai TImeZone question you answered mind if I ask you about it on Twitter or Email? (at)Programazing or chris(at)thatamazingprogrammer.com – Christopher Johnson Aug 04 '16 at 02:22

1 Answers1

1

Because you're using MVC's JsonResult (returned by the call to the Json method of the controller), the JSON serialization is being handled by the JavaScriptSerializer class. Unfortunately, this particular serializer doesn't handle DateTimeOffset values very well. It normalizes them to UTC, then presents them in an antiquated format.

While moment.js can indeed read that format (and thus can FullCalendar), the normalization process means that all times will appear as UTC, thus appearing to be (in your example case) four hours ahead.

There are two ways you might consider approaching this:

  1. You could tell FullCalendar to adjust all timestamps the the user's local time, by setting the timezone parameter to local. This requires no changes to the back-end, but means that users in different time zones will see events relative to themselves, rather than the local time of the event. (This is often desired anyway, so consider this first.)

  2. You could change the serializer used in your MVC code to use JSON.Net instead of the JavaScriptSerializer. By default, JSON.Net will use the standard ISO8601 format, and will preserve the offset of a DateTimeOffset value. If you want to do this globally throughout your project, see this approach, though you could instead simply change the last line of your LoadEvents method to:

    string json = JsonConvert.SerializeObject(model);
    return Content(json, "application/json");
    

    Also worth mentioning that ASP.Net WebAPI does not have this problem, as it already uses JSON.Net by default.

Community
  • 1
  • 1
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • I used the last approach and it worked perfectly. I was just coming back to mention I had realized the calendar was always displaying whatever I sent to it as what that time would be in UTC 0. The requirement is to make the calendar default to the system timezone and not the browser's local timezone. That and give a few options for timezones in a drop-down menu. The rest shouldn't be that difficult now that you've helped me figure this out. Thanks! – Christopher Johnson Aug 03 '16 at 19:47