diff --git a/README.md b/README.md
index e3ec3533e..e5c9fc62e 100644
--- a/README.md
+++ b/README.md
@@ -29,15 +29,15 @@ element has a height, or the calendar won't be visible. To provide your own cust
$ git clone git@github.com:jquense/react-big-calendar.git
$ cd react-big-calendar
$ yarn
-$ yarn examples
+$ yarn storybook
```
- Open [localhost:3000/examples/index.html](http://localhost:3000/examples/index.html).
### Localization and Date Formatting
-`react-big-calendar` includes three options for handling the date formatting and culture localization, depending
-on your preference of DateTime libraries. You can use either the [Moment.js](https://momentjs.com/), [Globalize.js](https://github.com/jquery/globalize) or [date-fns](https://date-fns.org/) localizers.
+`react-big-calendar` includes four options for handling the date formatting and culture localization, depending
+on your preference of DateTime libraries. You can use either the [Moment.js](https://momentjs.com/), [Globalize.js](https://github.com/jquery/globalize), [date-fns](https://date-fns.org/), [Day.js](https://day.js.org) localizers.
Regardless of your choice, you **must** choose a localizer to use this library:
@@ -118,6 +118,37 @@ const MyCalendar = (props) => (
)
```
+#### Day.js
+
+Note that the dayjsLocalizer extends Day.js with the following plugins:
+
+- [IsBetween](https://day.js.org/docs/en/plugin/is-between)
+- [IsSameOrAfter](https://day.js.org/docs/en/plugin/is-same-or-after)
+- [IsSameOrBefore](https://day.js.org/docs/en/plugin/is-same-or-before)
+- [LocaleData](https://day.js.org/docs/en/plugin/locale-data)
+- [LocalizedFormat](https://day.js.org/docs/en/plugin/localized-format)
+- [MinMax](https://day.js.org/docs/en/plugin/min-max)
+- [UTC](https://day.js.org/docs/en/plugin/utc)
+
+```js
+import { Calendar, dayjsLocalizer } from 'react-big-calendar'
+import dayjs from 'dayjs'
+
+const localizer = dayjsLocalizer(dayjs)
+
+const MyCalendar = (props) => (
+
+
+
+)
+```
+
## Custom Styling
Out of the box, you can include the compiled CSS files and be up and running. But, sometimes, you may want to style
diff --git a/package.json b/package.json
index b7fcec984..5b6cbc493 100644
--- a/package.json
+++ b/package.json
@@ -107,6 +107,7 @@
"@babel/runtime": "^7.18.6",
"clsx": "^1.2.1",
"date-arithmetic": "^4.1.0",
+ "dayjs": "^1.11.5",
"dom-helpers": "^5.2.1",
"globalize": "^0.1.1",
"invariant": "^2.2.4",
diff --git a/src/index.js b/src/index.js
index afa51c186..85034943d 100644
--- a/src/index.js
+++ b/src/index.js
@@ -13,5 +13,6 @@ export { default as momentLocalizer } from './localizers/moment'
export { default as luxonLocalizer } from './localizers/luxon'
export { default as globalizeLocalizer } from './localizers/globalize'
export { default as dateFnsLocalizer } from './localizers/date-fns'
+export { default as dayjsLocalizer } from './localizers/dayjs'
export { default as move } from './utils/move'
export { views as Views, navigate as Navigate } from './utils/constants'
diff --git a/src/localizers/dayjs.js b/src/localizers/dayjs.js
new file mode 100644
index 000000000..4f8787418
--- /dev/null
+++ b/src/localizers/dayjs.js
@@ -0,0 +1,409 @@
+import { DateLocalizer } from '../localizer'
+
+// import dayjs plugins
+// Note that the timezone plugin is not imported here
+// this plugin can be optionally loaded by the user
+import isBetween from 'dayjs/plugin/isBetween'
+import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'
+import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
+import localeData from 'dayjs/plugin/localeData'
+import localizedFormat from 'dayjs/plugin/localizedFormat'
+import minMax from 'dayjs/plugin/minMax'
+import utc from 'dayjs/plugin/utc'
+
+const weekRangeFormat = ({ start, end }, culture, local) =>
+ local.format(start, 'MMMM DD', culture) +
+ ' – ' +
+ // updated to use this localizer 'eq()' method
+ local.format(end, local.eq(start, end, 'month') ? 'DD' : 'MMMM DD', culture)
+
+const dateRangeFormat = ({ start, end }, culture, local) =>
+ local.format(start, 'L', culture) + ' – ' + local.format(end, 'L', culture)
+
+const timeRangeFormat = ({ start, end }, culture, local) =>
+ local.format(start, 'LT', culture) + ' – ' + local.format(end, 'LT', culture)
+
+const timeRangeStartFormat = ({ start }, culture, local) =>
+ local.format(start, 'LT', culture) + ' – '
+
+const timeRangeEndFormat = ({ end }, culture, local) =>
+ ' – ' + local.format(end, 'LT', culture)
+
+export const formats = {
+ dateFormat: 'DD',
+ dayFormat: 'DD ddd',
+ weekdayFormat: 'ddd',
+
+ selectRangeFormat: timeRangeFormat,
+ eventTimeRangeFormat: timeRangeFormat,
+ eventTimeRangeStartFormat: timeRangeStartFormat,
+ eventTimeRangeEndFormat: timeRangeEndFormat,
+
+ timeGutterFormat: 'LT',
+
+ monthHeaderFormat: 'MMMM YYYY',
+ dayHeaderFormat: 'dddd MMM DD',
+ dayRangeHeaderFormat: weekRangeFormat,
+ agendaHeaderFormat: dateRangeFormat,
+
+ agendaDateFormat: 'ddd MMM DD',
+ agendaTimeFormat: 'LT',
+ agendaTimeRangeFormat: timeRangeFormat,
+}
+
+function fixUnit(unit) {
+ let datePart = unit ? unit.toLowerCase() : unit
+ if (datePart === 'FullYear') {
+ datePart = 'year'
+ } else if (!datePart) {
+ datePart = undefined
+ }
+ return datePart
+}
+
+export default function (dayjsLib) {
+ // load dayjs plugins
+ dayjsLib.extend(isBetween)
+ dayjsLib.extend(isSameOrAfter)
+ dayjsLib.extend(isSameOrBefore)
+ dayjsLib.extend(localeData)
+ dayjsLib.extend(localizedFormat)
+ dayjsLib.extend(minMax)
+ dayjsLib.extend(utc)
+
+ const locale = (dj, c) => (c ? dj.locale(c) : dj)
+
+ // if the timezone plugin is loaded,
+ // then use the timezone aware version
+ const dayjs = dayjsLib.tz ? dayjsLib.tz : dayjsLib
+
+ function getTimezoneOffset(date) {
+ // ensures this gets cast to timezone
+ return dayjs(date).toDate().getTimezoneOffset()
+ }
+
+ function getDstOffset(start, end) {
+ // convert to dayjs, in case
+ const st = dayjs(start)
+ const ed = dayjs(end)
+ // if not using the dayjs timezone plugin
+ if (!dayjs.tz) {
+ return st.toDate().getTimezoneOffset() - ed.toDate().getTimezoneOffset()
+ }
+ /**
+ * If a default timezone has been applied, then
+ * use this to get the proper timezone offset, otherwise default
+ * the timezone to the browser local
+ */
+ const tzName = st.tz().$x.$timezone ?? dayjsLib.tz.guess()
+ // invert offsets to be inline with moment.js
+ const startOffset = -dayjs.tz(+st, tzName).utcOffset()
+ const endOffset = -dayjs.tz(+ed, tzName).utcOffset()
+ return startOffset - endOffset
+ }
+
+ function getDayStartDstOffset(start) {
+ const dayStart = dayjs(start).startOf('day')
+ return getDstOffset(dayStart, start)
+ }
+
+ /*** BEGIN localized date arithmetic methods with dayjs ***/
+ function defineComparators(a, b, unit) {
+ const datePart = fixUnit(unit)
+ const dtA = datePart ? dayjs(a).startOf(datePart) : dayjs(a)
+ const dtB = datePart ? dayjs(b).startOf(datePart) : dayjs(b)
+ return [dtA, dtB, datePart]
+ }
+
+ function startOf(date = null, unit) {
+ const datePart = fixUnit(unit)
+ if (datePart) {
+ return dayjs(date).startOf(datePart).toDate()
+ }
+ return dayjs(date).toDate()
+ }
+
+ function endOf(date = null, unit) {
+ const datePart = fixUnit(unit)
+ if (datePart) {
+ return dayjs(date).endOf(datePart).toDate()
+ }
+ return dayjs(date).toDate()
+ }
+
+ // dayjs comparison operations *always* convert both sides to dayjs objects
+ // prior to running the comparisons
+ function eq(a, b, unit) {
+ const [dtA, dtB, datePart] = defineComparators(a, b, unit)
+ return dtA.isSame(dtB, datePart)
+ }
+
+ function neq(a, b, unit) {
+ return !eq(a, b, unit)
+ }
+
+ function gt(a, b, unit) {
+ const [dtA, dtB, datePart] = defineComparators(a, b, unit)
+ return dtA.isAfter(dtB, datePart)
+ }
+
+ function lt(a, b, unit) {
+ const [dtA, dtB, datePart] = defineComparators(a, b, unit)
+ return dtA.isBefore(dtB, datePart)
+ }
+
+ function gte(a, b, unit) {
+ const [dtA, dtB, datePart] = defineComparators(a, b, unit)
+ return dtA.isSameOrBefore(dtB, datePart)
+ }
+
+ function lte(a, b, unit) {
+ const [dtA, dtB, datePart] = defineComparators(a, b, unit)
+ return dtA.isSameOrBefore(dtB, datePart)
+ }
+
+ function inRange(day, min, max, unit = 'day') {
+ const datePart = fixUnit(unit)
+ const djDay = dayjs(day)
+ const djMin = dayjs(min)
+ const djMax = dayjs(max)
+ return djDay.isBetween(djMin, djMax, datePart, '[]')
+ }
+
+ function min(dateA, dateB) {
+ const dtA = dayjs(dateA)
+ const dtB = dayjs(dateB)
+ const minDt = dayjsLib.min(dtA, dtB)
+ return minDt.toDate()
+ }
+
+ function max(dateA, dateB) {
+ const dtA = dayjs(dateA)
+ const dtB = dayjs(dateB)
+ const maxDt = dayjsLib.max(dtA, dtB)
+ return maxDt.toDate()
+ }
+
+ function merge(date, time) {
+ if (!date && !time) return null
+
+ const tm = dayjs(time).format('HH:mm:ss')
+ const dt = dayjs(date).startOf('day').format('MM/DD/YYYY')
+ // We do it this way to avoid issues when timezone switching
+ return dayjsLib(`${dt} ${tm}`, 'MM/DD/YYYY HH:mm:ss').toDate()
+ }
+
+ function add(date, adder, unit) {
+ const datePart = fixUnit(unit)
+ return dayjs(date).add(adder, datePart).toDate()
+ }
+
+ function range(start, end, unit = 'day') {
+ const datePart = fixUnit(unit)
+ // because the add method will put these in tz, we have to start that way
+ let current = dayjs(start).toDate()
+ const days = []
+
+ while (lte(current, end)) {
+ days.push(current)
+ current = add(current, 1, datePart)
+ }
+
+ return days
+ }
+
+ function ceil(date, unit) {
+ const datePart = fixUnit(unit)
+ const floor = startOf(date, datePart)
+
+ return eq(floor, date) ? floor : add(floor, 1, datePart)
+ }
+
+ function diff(a, b, unit = 'day') {
+ const datePart = fixUnit(unit)
+ // don't use 'defineComparators' here, as we don't want to mutate the values
+ const dtA = dayjs(a)
+ const dtB = dayjs(b)
+ return dtB.diff(dtA, datePart)
+ }
+
+ function minutes(date) {
+ const dt = dayjs(date)
+ return dt.minutes()
+ }
+
+ function firstOfWeek(culture) {
+ const data = culture ? dayjsLib.localeData(culture) : dayjsLib.localeData()
+ return data ? data.firstDayOfWeek() : 0
+ }
+
+ function firstVisibleDay(date) {
+ return dayjs(date).startOf('month').startOf('week').toDate()
+ }
+
+ function lastVisibleDay(date) {
+ return dayjs(date).endOf('month').endOf('week').toDate()
+ }
+
+ function visibleDays(date) {
+ let current = firstVisibleDay(date)
+ const last = lastVisibleDay(date)
+ const days = []
+
+ while (lte(current, last)) {
+ days.push(current)
+ current = add(current, 1, 'd')
+ }
+
+ return days
+ }
+ /*** END localized date arithmetic methods with dayjs ***/
+
+ /**
+ * Moved from TimeSlots.js, this method overrides the method of the same name
+ * in the localizer.js, using dayjs to construct the js Date
+ * @param {Date} dt - date to start with
+ * @param {Number} minutesFromMidnight
+ * @param {Number} offset
+ * @returns {Date}
+ */
+ function getSlotDate(dt, minutesFromMidnight, offset) {
+ return dayjs(dt)
+ .startOf('day')
+ .minute(minutesFromMidnight + offset)
+ .toDate()
+ }
+
+ // dayjs will automatically handle DST differences in it's calculations
+ function getTotalMin(start, end) {
+ return diff(start, end, 'minutes')
+ }
+
+ function getMinutesFromMidnight(start) {
+ const dayStart = dayjs(start).startOf('day')
+ const day = dayjs(start)
+ return day.diff(dayStart, 'minutes') + getDayStartDstOffset(start)
+ }
+
+ // These two are used by DateSlotMetrics
+ function continuesPrior(start, first) {
+ const djStart = dayjs(start)
+ const djFirst = dayjs(first)
+ return djStart.isBefore(djFirst, 'day')
+ }
+
+ function continuesAfter(start, end, last) {
+ const djEnd = dayjs(end)
+ const djLast = dayjs(last)
+ return djEnd.isSameOrAfter(djLast, 'minutes')
+ }
+
+ // These two are used by eventLevels
+ function sortEvents({
+ evtA: { start: aStart, end: aEnd, allDay: aAllDay },
+ evtB: { start: bStart, end: bEnd, allDay: bAllDay },
+ }) {
+ const startSort = +startOf(aStart, 'day') - +startOf(bStart, 'day')
+
+ const durA = diff(aStart, ceil(aEnd, 'day'), 'day')
+
+ const durB = diff(bStart, ceil(bEnd, 'day'), 'day')
+
+ return (
+ startSort || // sort by start Day first
+ Math.max(durB, 1) - Math.max(durA, 1) || // events spanning multiple days go first
+ !!bAllDay - !!aAllDay || // then allDay single day events
+ +aStart - +bStart || // then sort by start time *don't need dayjs conversion here
+ +aEnd - +bEnd // then sort by end time *don't need dayjs conversion here either
+ )
+ }
+
+ function inEventRange({
+ event: { start, end },
+ range: { start: rangeStart, end: rangeEnd },
+ }) {
+ const startOfDay = dayjs(start).startOf('day')
+ const eEnd = dayjs(end)
+ const rStart = dayjs(rangeStart)
+ const rEnd = dayjs(rangeEnd)
+
+ const startsBeforeEnd = startOfDay.isSameOrBefore(rEnd, 'day')
+ // when the event is zero duration we need to handle a bit differently
+ const sameMin = !startOfDay.isSame(eEnd, 'minutes')
+ const endsAfterStart = sameMin
+ ? eEnd.isAfter(rStart, 'minutes')
+ : eEnd.isSameOrAfter(rStart, 'minutes')
+
+ return startsBeforeEnd && endsAfterStart
+ }
+
+ function isSameDate(date1, date2) {
+ const dt = dayjs(date1)
+ const dt2 = dayjs(date2)
+ return dt.isSame(dt2, 'day')
+ }
+
+ /**
+ * This method, called once in the localizer constructor, is used by eventLevels
+ * 'eventSegments()' to assist in determining the 'span' of the event in the display,
+ * specifically when using a timezone that is greater than the browser native timezone.
+ * @returns number
+ */
+ function browserTZOffset() {
+ /**
+ * Date.prototype.getTimezoneOffset horrifically flips the positive/negative from
+ * what you see in it's string, so we have to jump through some hoops to get a value
+ * we can actually compare.
+ */
+ const dt = new Date()
+ const neg = /-/.test(dt.toString()) ? '-' : ''
+ const dtOffset = dt.getTimezoneOffset()
+ const comparator = Number(`${neg}${Math.abs(dtOffset)}`)
+ // dayjs correctly provides positive/negative offset, as expected
+ const mtOffset = dayjs().utcOffset()
+ return mtOffset > comparator ? 1 : 0
+ }
+
+ return new DateLocalizer({
+ formats,
+
+ firstOfWeek,
+ firstVisibleDay,
+ lastVisibleDay,
+ visibleDays,
+
+ format(value, format, culture) {
+ return locale(dayjs(value), culture).format(format)
+ },
+
+ lt,
+ lte,
+ gt,
+ gte,
+ eq,
+ neq,
+ merge,
+ inRange,
+ startOf,
+ endOf,
+ range,
+ add,
+ diff,
+ ceil,
+ min,
+ max,
+ minutes,
+
+ getSlotDate,
+ getTimezoneOffset,
+ getDstOffset,
+ getTotalMin,
+ getMinutesFromMidnight,
+ continuesPrior,
+ continuesAfter,
+ sortEvents,
+ inEventRange,
+ isSameDate,
+ browserTZOffset,
+ })
+}
diff --git a/src/localizers/moment.js b/src/localizers/moment.js
index a63b0451f..7421d28d3 100644
--- a/src/localizers/moment.js
+++ b/src/localizers/moment.js
@@ -55,9 +55,7 @@ export default function (moment) {
function getTimezoneOffset(date) {
// ensures this gets cast to timezone
- return moment(date)
- .toDate()
- .getTimezoneOffset()
+ return moment(date).toDate().getTimezoneOffset()
}
function getDstOffset(start, end) {
@@ -314,13 +312,10 @@ export default function (moment) {
return startsBeforeEnd && endsAfterStart
}
- // moment treats 'day' and 'date' equality very different
- // moment(date1).isSame(date2, 'day') would test that they were both the same day of the week
- // moment(date1).isSame(date2, 'date') would test that they were both the same date of the month of the year
function isSameDate(date1, date2) {
const dt = moment(date1)
const dt2 = moment(date2)
- return dt.isSame(dt2, 'date')
+ return dt.isSame(dt2, 'day')
}
/**
diff --git a/stories/demos/dayjs.stories.js b/stories/demos/dayjs.stories.js
new file mode 100644
index 000000000..51d3e8f76
--- /dev/null
+++ b/stories/demos/dayjs.stories.js
@@ -0,0 +1,20 @@
+import React from 'react'
+import dayjs from 'dayjs'
+import { Calendar, dayjsLocalizer } from '../../src'
+import Dayjs from './exampleCode/dayjs'
+
+export default {
+ title: 'Examples',
+ component: Calendar,
+ parameters: {
+ docs: {
+ page: null,
+ },
+ },
+}
+
+const localizer = dayjsLocalizer(dayjs)
+
+export function DayjsLocalizer() {
+ return
+}
diff --git a/stories/demos/exampleCode/dayjs.js b/stories/demos/exampleCode/dayjs.js
new file mode 100644
index 000000000..12d3bb400
--- /dev/null
+++ b/stories/demos/exampleCode/dayjs.js
@@ -0,0 +1,59 @@
+import React, { Fragment, useMemo } from 'react'
+import dayjs from 'dayjs'
+import { Calendar, Views, dayjsLocalizer } from 'react-big-calendar'
+import DemoLink from '../../DemoLink.component'
+import events from '../../resources/events'
+
+// Note that the dayjsLocalizer extends Day.js with the following plugins:
+// - IsBetween
+// - IsSameOrAfter
+// - IsSameOrBefore
+// - LocaleData
+// - LocalizedFormat
+// - MinMax
+// - UTC
+
+// add optional time zone support
+import timezone from 'dayjs/plugin/timezone'
+dayjs.extend(timezone)
+
+const djLocalizer = dayjsLocalizer(dayjs)
+
+const ColoredDateCellWrapper = ({ children }) =>
+ React.cloneElement(React.Children.only(children), {
+ style: {
+ backgroundColor: 'lightblue',
+ },
+ })
+
+export default function Dayjs({ ...props }) {
+ const { components, defaultDate, max, views } = useMemo(
+ () => ({
+ components: {
+ timeSlotWrapper: ColoredDateCellWrapper,
+ },
+ defaultDate: new Date(2015, 3, 1),
+ max: dayjs().endOf('day').subtract(1, 'hours').toDate(),
+ views: Object.keys(Views).map((k) => Views[k]),
+ }),
+ []
+ )
+
+ return (
+
+
+
+
+
+
+ )
+}
diff --git a/stories/demos/luxon.stories.js b/stories/demos/luxon.stories.js
index 32178738f..7fa360432 100644
--- a/stories/demos/luxon.stories.js
+++ b/stories/demos/luxon.stories.js
@@ -1,6 +1,6 @@
import React from 'react'
-import moment from 'moment'
-import { Calendar, momentLocalizer } from '../../src'
+import { DateTime } from 'luxon'
+import { Calendar, luxonLocalizer } from '../../src'
import Luxon from './exampleCode/luxon'
export default {
@@ -13,7 +13,7 @@ export default {
},
}
-const localizer = momentLocalizer(moment)
+const localizer = luxonLocalizer(DateTime)
export function LuxonLocalizer() {
return
diff --git a/stories/guides/Timezones.stories.mdx b/stories/guides/Timezones.stories.mdx
index c3faaa4c7..295bdf214 100644
--- a/stories/guides/Timezones.stories.mdx
+++ b/stories/guides/Timezones.stories.mdx
@@ -34,4 +34,4 @@ const MyCalendar = (props) => (
The `momentLocalizer` will now handle all dates and date math as if the date is in the timezone you specified. It is important to note that [changing moment's default timezone](https://momentjs.com/timezone/docs/#/using-timezones/default-timezone/) affects all dates, created by moment, from that point forward, so you may want to reset the default when your component unmounts. And, if switching timezones 'on-the-fly', you want to update your `localizer` and any Date based props (min, max, getNow, etc) at the same time.
-**Note:** The new `luxonLocalizer` operates in a similar fashion. View the 'Luxon Localizer' demo and view it's source for an example of it's usage.
+**Note:** The `luxonLocalizer` and `dayjsLocalizer` operate in a similar fashion. View their respective demos and source for examples of their usage.
diff --git a/stories/guides/localizer.stories.mdx b/stories/guides/localizer.stories.mdx
index f1f78ba11..d6885676c 100644
--- a/stories/guides/localizer.stories.mdx
+++ b/stories/guides/localizer.stories.mdx
@@ -45,6 +45,6 @@ Each `localizer`, when created, creates an instance of `DateLocalizer` class, an
- `startOfWeek(culture) => number` (alias of `firstOfWeek()`)
- `visibleDays(date:Date) => Array[Date]`
-Many of these methods are used by Big Calendar in the background for determining layout. You can create your own custom `localizer`, to utilize some other library (for instance [Day.js](https://day.js.org/)), as long as they implement these methods. The `DateLocalizer` class defaults these methods to methods from the [date-arithmetic](https://www.npmjs.com/package/date-arithmetic) package.
+Many of these methods are used by Big Calendar in the background for determining layout. You can create your own custom `localizer`, to utilize some other library, as long as they implement these methods. The `DateLocalizer` class defaults these methods to methods from the [date-arithmetic](https://www.npmjs.com/package/date-arithmetic) package.
-For examples of building your own custom `localizer` look at the [momentLocalizer](https://github.com/jquense/react-big-calendar/blob/master/src/localizers/moment.js) or [luxonLocalizer](https://github.com/jquense/react-big-calendar/blob/master/src/localizers/luxon.js) as an example. If you do build your own `localizer`, please consider publishing it to [npm](https://npmjs.org). We suggest a common naming convention like `rbc-addon-mylocalizername`.
+For examples of building your own custom `localizer` take a look at the [currently implemented localizers](https://github.com/jquense/react-big-calendar/blob/master/src/localizers). If you do build your own `localizer`, please consider publishing it to [npm](https://npmjs.org). We suggest a common naming convention like `rbc-addon-mylocalizername`.
diff --git a/stories/props/localizer.mdx b/stories/props/localizer.mdx
index 3fb52a728..c0670e914 100644
--- a/stories/props/localizer.mdx
+++ b/stories/props/localizer.mdx
@@ -8,24 +8,33 @@ import LinkTo from '@storybook/addon-links/react'
The localizer used for **formatting dates** and times according to the formats and culture. To format buttons and messaging use the messages prop.
```js
-// When using `Globalize`
-import { globalizeLocalizer } from 'react-big-calendar'
-import globalize from 'globalize'
+// When using `Day.js`
+import { dayjsLocalizer } from 'react-big-calendar'
+import dayjs from 'dayjs'
+// and, for optional time zone support
+import timezone from 'dayjs/plugin/timezone'
-const localizer = globalizeLocalizer(globalize)
+dayjs.extend(timezone)
+// end optional time zone support
+
+// Note that the dayjsLocalizer extends Day.js with the following plugins:
+// - IsBetween
+// - IsSameOrAfter
+// - IsSameOrBefore
+// - LocaleData
+// - LocalizedFormat
+// - MinMax
+// - UTC
+
+const localizer = dayjsLocalizer(dayjs)
```
```js
-// When using `moment`
-import { momentLocalizer } from 'react-big-calendar'
-import moment from 'moment'
-// and, for optional time zone support
-import 'moment-timezone'
-
-moment.tz.setDefault('America/Los_Angeles')
-// end optional time zone support
+// When using `Globalize`
+import { globalizeLocalizer } from 'react-big-calendar'
+import globalize from 'globalize'
-const localizer = momentLocalizer(moment)
+const localizer = globalizeLocalizer(globalize)
```
```js
@@ -45,6 +54,19 @@ Settings.defaultZone = 'America/Los_Angeles'
const localizer = luxonLocalizer(DateTime, { firstDayOfWeek: 7 })
```
+```js
+// When using `moment`
+import { momentLocalizer } from 'react-big-calendar'
+import moment from 'moment'
+// and, for optional time zone support
+import 'moment-timezone'
+
+moment.tz.setDefault('America/Los_Angeles')
+// end optional time zone support
+
+const localizer = momentLocalizer(moment)
+```
+
See the Localization Example for another example of combining `rtl`, `localizer`, `culture` and `messages`.