javascriptc#asp.net-mvcdatetimefullcalendar

Convert fullcalender select event start datetime to C#


https://fullcalendar.io/ select event saves start time using code from answer How to pass tstzrange to postgres

javascript:

document.addEventListener('DOMContentLoaded', function() {
const calOpts = {
  locale: 'ee',
  slotDuration: '00:15:00',
  slotLabelInterval: '00:15',
  allDaySlot: false,
  selectConstraint: 'businessHours',
  select : function( selectionInfo  ) {
     document.getElementById('start').value = selectionInfo.start
     },
    selectable: true,
   events: { url: 'api/fullcalendar' }
   }
  const calendarEl = document.getElementById('calendar')
  calendar = new FullCalendar.Calendar(calendarEl, calOpts)
  calendar.render()
  })

html:

<form action="~/kinnitatud" method="post">
<input type="hidden" name="start" id="start" />
<input type='submit'/>
</form>

selectionInfo.start contains localized value like

Mon Dec 30 2024 09:30:00 GMT+0200 (Ida-Euroopa standardaeg)

.NET 9 MVC controller parses it using

[HttpPost]
public async Task<IActionResult> Kinnitatud(string start) {
DateTime algus = DateTimeOffset.Parse(start,new CultureInfo("ee")).UtcDateTime;
}

DateTimeOffset.Parse throws exeption:

String 'Mon Dec 30 2024 09:30:00 GMT+0200 (Ida-Euroopa standardaeg)' was not recognized as a valid DateTime.

Tried also without

locale: 'ee',

setting but start value is still in ee culture. ee is browser culture. Fullcalendar returns selectionInfo.start in browser culture format always.

Tried in controller to use DateTime.Parse:

DateTime algus = DateTime.Parse(start, new CultureInfo("ee")).ToUniversalTime()

Exception is the same.

How to force fullcalendar to return select start time in invariant culture format ?

Or: users have different cultures in browser. How to parse start selectionInfo.start returned by fullcalendar?


Solution

  • You said that

    Fullcalendar returns selectionInfo.start in browser culture format always

    ...but that isn't true. Fullcalendar - as per the documentation - returns a JavaScript DateTime object in the selectionInfo.start field. That's an object, with properties. It is not a pre-formatted string.

    What's then happening is that, when you use document.getElementById('start').value = selectionInfo.start to write that value into your start hidden field, JS has to turn the date object into a piece of text. And since you didn't specify any other format for the stringified date, it uses the default toString function of the DateTime class. That is what produces the Mon Dec 30 2024 09:30:00 GMT+0200 (Ida-Euroopa standardaeg) kind of string you're seeing. It's nothing to do with fullCalendar at all, it's entirely down to the way you wrote your code.

    A far better way to transmit a date, in a more parseable format, and without any localization baggage, is to use the standard ISO8601 format (e.g. YYYY-MM-DDTHH:mm:ss.sssZ). And the JavaScript Datetime object has a function which outputs the date in that exact format.

    So all you need to do is write

    document.getElementById('start').value = selectionInfo.start.toISOString()
    

    instead.

    Then your .NET code should be able to parse the date no problem. I can't test it right now, but you might even be able to write

    public async Task<IActionResult> Kinnitatud(DateTime start) {
    

    as the method signature, and save yourself the manual call to DateTimeOffset.Parse().