Skip to content

Instantly share code, notes, and snippets.

@laoneo
Created October 21, 2024 13:56
Show Gist options
  • Save laoneo/fa1b210f7a056ea46fb1311760ffca02 to your computer and use it in GitHub Desktop.
Save laoneo/fa1b210f7a056ea46fb1311760ffca02 to your computer and use it in GitHub Desktop.
Dayjs ES6 module for fullcalendar
import { createPlugin } from '@fullcalendar/core/index.js';
import { CalendarImpl } from '@fullcalendar/core/internal.js';
import dayjs from 'dayjs/esm/index';
import arraySupport from 'dayjs/esm/plugin/arraySupport';
import customParseFormat from 'dayjs/esm/plugin/customParseFormat';
import duration from 'dayjs/esm/plugin/duration';
import updateLocale from 'dayjs/esm/plugin/updateLocale';
import utc from 'dayjs/esm/plugin/utc';
dayjs.extend(arraySupport);
dayjs.extend(customParseFormat);
dayjs.extend(duration);
dayjs.extend(updateLocale);
dayjs.extend(utc);
function toDayjs(date, calendar) {
if (!(calendar instanceof CalendarImpl)) {
throw new Error('must supply a CalendarApi instance');
}
let { dateEnv } = calendar.getCurrentData();
return convertToDayjs(date, dateEnv.timeZone, null, dateEnv.locale.codes[0]);
}
function toDayjsDuration(fcDuration) {
return dayjs.duration(fcDuration); // dayjs accepts all the props that fc.Duration already has!
}
// Internal Utils
function convertToDayjs(input, timeZone, timeZoneOffset, locale) {
let mom;
if (timeZone === 'local') {
mom = dayjs(input);
}
else if (timeZone === 'UTC') {
mom = dayjs.utc(input);
}
else if (dayjs.tz) {
mom = dayjs.tz(input, timeZone);
}
else {
mom = dayjs.utc(input);
if (timeZoneOffset != null) {
mom.utcOffset(timeZoneOffset);
}
}
mom.locale(locale);
return mom;
}
function formatWithCmdStr(cmdStr, arg) {
let cmd = parseCmdStr(cmdStr);
if (arg.end) {
let startMom = convertToDayjs(arg.start.array, arg.timeZone, arg.start.timeZoneOffset, arg.localeCodes[0]);
let endMom = convertToDayjs(arg.end.array, arg.timeZone, arg.end.timeZoneOffset, arg.localeCodes[0]);
return formatRange(cmd, createDayjsFormatFunc(startMom), createDayjsFormatFunc(endMom), arg.defaultSeparator);
}
return convertToDayjs(arg.date.array, arg.timeZone, arg.date.timeZoneOffset, arg.localeCodes[0]).format(cmd.whole); // TODO: test for this
}
function createDayjsFormatFunc(mom) {
return (cmdStr) => (cmdStr ? mom.format(cmdStr) : '' // because calling with blank string results in ISO8601 :(
);
}
function parseCmdStr(cmdStr) {
let parts = cmdStr.match(/^(.*?)\{(.*)\}(.*)$/); // TODO: lookbehinds for escape characters
if (parts) {
let middle = parseCmdStr(parts[2]);
return { head: parts[1], middle, tail: parts[3], whole: parts[1] + middle.whole + parts[3] };
}
return { head: null, middle: null, tail: null, whole: cmdStr, };
}
function formatRange(cmd, formatStart, formatEnd, separator) {
if (cmd.middle) {
let startHead = formatStart(cmd.head);
let startMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
let startTail = formatStart(cmd.tail);
let endHead = formatEnd(cmd.head);
let endMiddle = formatRange(cmd.middle, formatStart, formatEnd, separator);
let endTail = formatEnd(cmd.tail);
if (startHead === endHead && startTail === endTail) {
return startHead +
(startMiddle === endMiddle ? startMiddle : startMiddle + separator + endMiddle) +
startTail;
}
}
let startWhole = formatStart(cmd.whole);
let endWhole = formatEnd(cmd.whole);
if (startWhole === endWhole) {
return startWhole;
}
return startWhole + separator + endWhole;
}
var index = createPlugin({
name: 'fullcalendar/dayjs',
cmdFormatter: formatWithCmdStr,
});
export { index as default, toDayjs, toDayjsDuration };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment