0

I'm using the https://fullcalendar.io/ calendar plugin in an app. I provide the calendar with data with the dates in iso8601 format, like this, "2021-09-15T14:30:00+01:00", and the calendar does a good job of showing those times adjusted for the timezone set in the browser.

Eg, if the browser is in a "+01:00" timezone then that time shows up as 14:30, but if it's in a "+02:00" timezone it shows up as 15:30, etc.

My problem is that I'd like to show those times in other contexts, outside of the calendar, and I don't want to output different things from the server - I want the conversion to happen in the browser, using javascript.

It occurred to me that I could do something like this: output the time in a span with the iso861 string in a data attribute, perhaps with a class as well which acts as a trigger for some general js on the page. But, is there a simple way in JS to convert the iso8601 time string to a time using the browser's timezone setting? I suppose I would need to have another data attribute that has some info on how I want it to be formatted, something like "%H:%M" in this case (if I want to output "14:30" or "15:30").

Note - we use jquery and i will use that in my example JS below.

Something like this:

<!-- in html - the span contains the default unconverted time -->

<span class="convertable-time" data-iso8601="2021-09-15T14:30:00+01:00" data-datetime-format="%H:%M">14:30</span>

and then in the JS something like this (this is using jquery but the solution doesn't need to)

$(".convertable-time").each(function(i,el){
  el = $(el);
  el.html(convertIso8601StringToLocalTime(el.data("iso8601"), el.data("datetime-format"));
});

function convertIso8601StringToLocalTime(string, format){
  //eg string = "2021-09-15T14:30:00+01:00"
  //eg format = "%H:%M"
  // ??
}

What would I put in the convertIso8601StringToLocalTime function? Note - i'm not wedded to the exact format string of "%H:%M", if there is a more standard way of specifying a datetime format in JS then i'm happy to use it. thanks.

Max Williams
  • 32,435
  • 31
  • 130
  • 197
  • 2
    Just dump it int the `Date` consturctor? `new Date('2021-09-15T14:30:00+01:00')` – Cerbrus Sep 15 '21 at 11:15
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString – mplungjan Sep 15 '21 at 11:18
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat – mplungjan Sep 15 '21 at 11:18
  • @Cerbrus perfect! thanks. Is there a built in way to output that Date object as a string with a given formatting? Similar to ruby's `.strftime("%H:%M")`? – Max Williams Sep 15 '21 at 11:26
  • See @mplungjan's links for what's available, Max. – Cerbrus Sep 15 '21 at 11:28
  • @Cerbrus I saw those but can't see a method that would simply output "14:30". However, I can make my own and use `.getHours()` and `.getMinutes()`. – Max Williams Sep 15 '21 at 11:29

1 Answers1

0

This is what I ended up doing:

//expects timestring to be an iso8601 formatted datetime string eg "2021-09-15T14:30:00+01:00"
//accepted strings for "format": copied from ruby's DateTime#strftime method
// %M - minutes
// %H - hours
// %S - seconds
// %d - day of the month
// %Y - year four digits
// %y - year two digits
// %m - month (as a number)
function convertIso8601StringToLocalTime(timestring, format){
  //set default format
  if((typeof(format) == "undefined") || (format == "")){
    format = "%H:%M";
  }
  var date = new Date(timestring);
  var replacements = {
    "getMinutes": /\%M/g,
    "getHours": /\%H/g,
    "getDate": /\%d/g,
    "getFullYear": /\%Y/g,
    "getMonth": /\%m/g
  }
  for (const [function_name, regex] of Object.entries(replacements)) {
    if(format.match(regex)){
      format = format.replace(regex, date[function_name]());
    }
  }
  // year two digits doesn't have a method we can call on a Date as far as I can see
  // ('getYear()' returns '121' for me which is mysterious)
  // so we do it 'manually' here by modding the full year by 100
  if(format.match(/\%y/g)){
    format = format.replace(/\%y/g, (date.getFullYear() % 100));
  }
  return format;
}
Max Williams
  • 32,435
  • 31
  • 130
  • 197
  • So you just wanted a simple formatter? There's one [here](https://stackoverflow.com/a/57302039/257182) that uses PHP tokens, I think it should be fairly simple to convert to other token schemes. ECMAScript allows default parameters, so instead of `if (typeof format == 'undefined'...)` etc. you can do `function convertIso8601StringToLocalTime(timestring, format = '%H:%M'){...}`. :-) – RobG Sep 17 '21 at 00:34
  • Thanks - the reason I didn't put the default parameter in was that i thought that format might come through as an empty string sometimes, and wanted to pick that up as being equivalent to the "undefined" case, which the default param wouldn't do. – Max Williams Sep 17 '21 at 15:55