Args.event.start in Scheduler sometimes returns date in ISO8601 format

So I’ve noticed that one of my calendar events is not working properly, and it seems that for this particular event only, the “args.event.start” value is not what I would expect.

First of all, I’ve set up a test page to look at here:
https://app.benjicare.com/test.php

It’s a simplified version of my code but it serves the purpose.

If you debug the following part:

  onEventClick: function (args, inst) {
    var scheduleid = args.event.Id;
    var scheduleUTCdate = args.event.start;
    var year = scheduleUTCdate.getFullYear();
    var month = scheduleUTCdate.getMonth() + 1;
    var day = scheduleUTCdate.getDate();
    var scheduledate = year + '-' + padLeft(month,2) + '-' + padLeft(day,2);
    viewSchedule(scheduleid,scheduledate);

You’ll find that if you click on the first event, args.event.start is returned as

"2022-06-09T08:40:00"

But if you click on the second event, args.event.start is returned as a UTC object, as I would expect. I obviously need that code to behave consistently, so why is my first event returning an ISO formatted date string? Is this a bug in mobiscroll? Or am I doing something wrong?

EDIT: To see what I mean, please navigate to June 9th, 2022 to see the two events.

So I realize now that the difference is that the recurring event returns a UTC date object and the non-recurring event returns an ISO date string. Is this by design? It seems inconsistent to me.

This is also making things difficult for drag to resize. On a recurring event, the onEventDragEnd event does not return the new end time. Again, is this by design? Or do I need to tell my users that they can’t drag to resize a recurring event?

Hi Vincent,

Could you please provide me the login credentials so I can take a look at your test page?

Credentials? It shouldn’t be asking you for login credentials.

Sorry Gabi. I tested it on another computer and it was indeed checking for authentication, which I never noticed on my own computer because I’m always authenticated. Anyway, please take a look again. It should not be redirecting you now, and please navigate to June 9th, 2022 to see the two events I am referring to.

Hi,

For event handlers we pass the original calendar event objects, as they were passed to the calendar. E.g. if in your data the start/end dates were strings, the event argument passed to the onEventClick handler will also contain the start/end dates as strings. This is because we don’t modify the original event objects (except adding an id field if there’s none).

Recurring events are a bit different, since we need to create multiple occurrences of the same single event. For calculations we need to work with date objects, so the occurence start/end dates will be Date objects. The onEventClick will receive the occurrence event object, while the original reccuring event object can be also accessed via event.original.

While we still don’t want to modify the original event objects, we’re thinking of ways to provide the start/end dates for event handlers in a consistent way, maybe even multiple formats (ISO string, Date object), to choose from.

I hope this explains.

1 Like

That explains it. Thank you!

I do think it would make a lot of sense if the user could choose the format. That way if I have both recurring and non-recurring events I could choose to return it as an object so that my code can be consistent regardless of which type of event I’m working with, and if I decide to only allow non-recurring events then I would have the flexibility to work with dates in the format I prefer. That would be the best solution, in my opinion.

Isti, I’m revisiting this issue, and I understand that I get the date data out in the format that I pass it in, which means in this case I’m getting the date back as a string (2021-05-19T09:30:00), and you explained that in recurring events I get it back as an object, for reasons, which is fine.

So what I’d like to do is make this consistent, which means since I have no option but to receive the date as an object on a recurring event I would like to always receive the date back as an object, even for non-recurring events. However, I don’t see how that’s possible as I have to pass the data in json format. How can I ensure I always get the date back as an object? Is this even possible?

Hi @Vincent_Wansink,

If I understand you correctly, you would like to work with date objects in all cases. In this case, you’ll have to pass the dates as data objects.

Hi gabi. You say I should pass in the dates as an object, but how do I do that? I’m passing in a json string of calendar events. For example, my json looks like this:

{“Recurrence”:false,“AllDay”:false,“Id”:187,“text”:“Fred”,“description”:null,“color”:"#DEC1E3",“start”:“2022-07-22T09:00:00”,“end”:“2022-07-22T11:00:00-06:00”,“services”:“1”,“textcolour”:“black”,“staffid”:5,“resource”:5}

And I pass it in like this

// Set calendar data
calendar.setEvents(JSON.parse(data));

So how do I pass in the date as an object when I have to pass in a json object? Can you give me an example?

Hi @Vincent_Wansink!

Thanks for sharing the code snippets you use. The problem is the JSON.parse function can’t parse date string, because of the many formats they can have. Also, it can’t distiguish the type, because it doesn’t know if you want a string or date object.

So you will need to parse them individually. If you store your dates in ISO8601, you could check for that format. You can use a regex, to detect strings that are like dates and then pass them to the Date constructor.

The JSON.parse function takes a reviver parameter that can be used for this. Check out the MDN link for more details! Here’s an idea of how should it be implemented:

JSON.parse(data, (key, value) => {
  // looks like a date?
  if (/^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+$/.test(value)) {
    return new Date(value); // return date object
  }
  return value;
});

Let me know if that helps!

1 Like

Thank you for the example. I couldn’t get your regex to work, so I ended up doing this and it works!

  calendar.setEvents(JSON.parse(data, (key, value) => {
    if (/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?$/i.test(value)) {
      value = new Date(value); 
    }
    return value;
  }));  

And to simplify things even further, I wrapped it in a function.

function fixScheduleData(data){
  var fixed = JSON.parse(data, (key, value) => {
    if (/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?$/i.test(value)) {
      value = new Date(value);
    }
    return value;
  })
  return fixed;
}

And then I use it like so:

calendar.setEvents(fixScheduleData(data));