From a8595cd81f661c582ea96182f348ef84fc7094f5 Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Wed, 24 Aug 2022 20:20:47 +0200
Subject: [PATCH 01/15] docs: fixed instructions to run examples locally
---
README.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index e3ec3533e1..7f20a6bf18 100644
--- a/README.md
+++ b/README.md
@@ -25,11 +25,13 @@ element has a height, or the calendar won't be visible. To provide your own cust
## Run examples locally
+Note: node >= 16 is required to run the storybook
+
```sh
$ 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).
From 7799567450adb0a254fd6ba3357baf9b8cea0017 Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Wed, 24 Aug 2022 20:22:12 +0200
Subject: [PATCH 02/15] fix: luxon story now uses luxon instead of moment
---
stories/demos/luxon.stories.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/stories/demos/luxon.stories.js b/stories/demos/luxon.stories.js
index 32178738fd..7fa3604324 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
From 5ebe9dc34ba001b0f0e21ce4dfee13d34bef27ea Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Wed, 24 Aug 2022 20:27:55 +0200
Subject: [PATCH 03/15] fix(moment localizer): removed comments about 'day' and
'date' in the call to isSame()
---
src/localizers/moment.js | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/src/localizers/moment.js b/src/localizers/moment.js
index a63b0451fb..7421d28d37 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')
}
/**
From cf065fcd7be71b52bf727b6e27423302781c0bfc Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Wed, 24 Aug 2022 20:29:13 +0200
Subject: [PATCH 04/15] feat: created dayjs localizer
---
README.md | 41 ++-
package.json | 1 +
src/index.js | 1 +
src/localizers/dayjs.js | 386 +++++++++++++++++++++++++++++
stories/demos/dayjs.stories.js | 20 ++
stories/demos/exampleCode/dayjs.js | 67 +++++
yarn.lock | 5 +
7 files changed, 520 insertions(+), 1 deletion(-)
create mode 100644 src/localizers/dayjs.js
create mode 100644 stories/demos/dayjs.stories.js
create mode 100644 stories/demos/exampleCode/dayjs.js
diff --git a/README.md b/README.md
index 7f20a6bf18..e762209c12 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ $ yarn storybook
### 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.
+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:
@@ -120,6 +120,45 @@ const MyCalendar = (props) => (
)
```
+```js
+import { Calendar, dayjsLocalizer } from 'react-big-calendar'
+import dayjs from 'dayjs'
+
+// import necessary dayjs plugins
+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 timezone from 'dayjs/plugin/timezone'
+import utc from 'dayjs/plugin/utc'
+
+// load necessary dayjs plugins
+dayjs.extend(isBetween)
+dayjs.extend(isSameOrAfter)
+dayjs.extend(isSameOrBefore)
+dayjs.extend(localeData)
+dayjs.extend(localizedFormat)
+dayjs.extend(minMax)
+dayjs.extend(timezone)
+dayjs.extend(utc)
+
+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 a399c8a0f2..1dccbe4859 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 afa51c186a..85034943dd 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 0000000000..cfc7f55c5b
--- /dev/null
+++ b/src/localizers/dayjs.js
@@ -0,0 +1,386 @@
+import { DateLocalizer } from '../localizer'
+
+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) {
+ const locale = (dj, c) => (c ? dj.locale(c) : dj)
+
+ // if a default timezone is set (dayjsLib.tz.setDefault()),
+ // then use the timezone aware version
+ const dayjs = dayjsLib.tz().$x.$timezone ? 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 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 = dayjs.min(dtA, dtB)
+ return minDt.toDate()
+ }
+
+ function max(dateA, dateB) {
+ const dtA = dayjs(dateA)
+ const dtB = dayjs(dateB)
+ const maxDt = dayjs.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 dayjs(`${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 ? dayjs.localeData(culture) : dayjs.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 mStart = dayjs(start)
+ const mFirst = dayjs(first)
+ return mStart.isBefore(mFirst, 'day')
+ }
+
+ function continuesAfter(start, end, last) {
+ const mEnd = dayjs(end)
+ const mLast = dayjs(last)
+ return mEnd.isSameOrAfter(mLast, '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/stories/demos/dayjs.stories.js b/stories/demos/dayjs.stories.js
new file mode 100644
index 0000000000..51d3e8f763
--- /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 0000000000..ef0a3af272
--- /dev/null
+++ b/stories/demos/exampleCode/dayjs.js
@@ -0,0 +1,67 @@
+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'
+import * as dates from '../../../src/utils/dates'
+
+// import dayjs plugins
+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 timezone from 'dayjs/plugin/timezone'
+import utc from 'dayjs/plugin/utc'
+
+// load dayjs plugins
+dayjs.extend(isBetween)
+dayjs.extend(isSameOrAfter)
+dayjs.extend(isSameOrBefore)
+dayjs.extend(localeData)
+dayjs.extend(localizedFormat)
+dayjs.extend(minMax)
+dayjs.extend(timezone)
+dayjs.extend(utc)
+
+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: dates.add(dates.endOf(new Date(2015, 17, 1), 'day'), -1, 'hours'),
+ views: Object.keys(Views).map((k) => Views[k]),
+ }),
+ []
+ )
+
+ return (
+
+
+
+
+
+
+ )
+}
diff --git a/yarn.lock b/yarn.lock
index 84cf95982b..6258f5d9da 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6755,6 +6755,11 @@ dateformat@^3.0.0:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
+dayjs@^1.11.5:
+ version "1.11.5"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
+ integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
+
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
From d7d5767a1cde817fca2799702d215022d810c531 Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Thu, 25 Aug 2022 13:45:19 +0200
Subject: [PATCH 05/15] fix(dayjs localizer): min() & max() now both behave
correctly when a default timezone is applied
---
src/localizers/dayjs.js | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/localizers/dayjs.js b/src/localizers/dayjs.js
index cfc7f55c5b..8081a34a91 100644
--- a/src/localizers/dayjs.js
+++ b/src/localizers/dayjs.js
@@ -150,14 +150,14 @@ export default function (dayjsLib) {
function min(dateA, dateB) {
const dtA = dayjs(dateA)
const dtB = dayjs(dateB)
- const minDt = dayjs.min(dtA, dtB)
+ const minDt = dayjsLib.min(dtA, dtB)
return minDt.toDate()
}
function max(dateA, dateB) {
const dtA = dayjs(dateA)
const dtB = dayjs(dateB)
- const maxDt = dayjs.max(dtA, dtB)
+ const maxDt = dayjsLib.max(dtA, dtB)
return maxDt.toDate()
}
@@ -210,7 +210,7 @@ export default function (dayjsLib) {
}
function firstOfWeek(culture) {
- const data = culture ? dayjs.localeData(culture) : dayjs.localeData()
+ const data = culture ? dayjsLib.localeData(culture) : dayjsLib.localeData()
return data ? data.firstDayOfWeek() : 0
}
@@ -264,15 +264,15 @@ export default function (dayjsLib) {
// These two are used by DateSlotMetrics
function continuesPrior(start, first) {
- const mStart = dayjs(start)
- const mFirst = dayjs(first)
- return mStart.isBefore(mFirst, 'day')
+ const djStart = dayjs(start)
+ const djFirst = dayjs(first)
+ return djStart.isBefore(djFirst, 'day')
}
function continuesAfter(start, end, last) {
- const mEnd = dayjs(end)
- const mLast = dayjs(last)
- return mEnd.isSameOrAfter(mLast, 'minutes')
+ const djEnd = dayjs(end)
+ const djLast = dayjs(last)
+ return djEnd.isSameOrAfter(djLast, 'minutes')
}
// These two are used by eventLevels
From edb1e2538c8c156b4612343be7675bd1c0e1abda Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Sat, 24 Sep 2022 17:11:06 +0200
Subject: [PATCH 06/15] docs(localizer guide): edited last two paragraphs to
include the new localizer
---
stories/guides/localizer.stories.mdx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/stories/guides/localizer.stories.mdx b/stories/guides/localizer.stories.mdx
index f1f78ba115..d6885676c6 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`.
From 28a82471f690ad562e8b3d4af7816c97727b08bc Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Fri, 30 Sep 2022 10:25:30 +0200
Subject: [PATCH 07/15] fix(dayjs localizer): dayjs plugins are now loaded by
the localizer
---
src/localizers/dayjs.js | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/src/localizers/dayjs.js b/src/localizers/dayjs.js
index 8081a34a91..07cb9119ef 100644
--- a/src/localizers/dayjs.js
+++ b/src/localizers/dayjs.js
@@ -1,5 +1,26 @@
+import dayjs from 'dayjs'
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'
+
+// load dayjs plugins
+dayjs.extend(isBetween)
+dayjs.extend(isSameOrAfter)
+dayjs.extend(isSameOrBefore)
+dayjs.extend(localeData)
+dayjs.extend(localizedFormat)
+dayjs.extend(minMax)
+dayjs.extend(utc)
+
const weekRangeFormat = ({ start, end }, culture, local) =>
local.format(start, 'MMMM DD', culture) +
' – ' +
@@ -53,9 +74,9 @@ function fixUnit(unit) {
export default function (dayjsLib) {
const locale = (dj, c) => (c ? dj.locale(c) : dj)
- // if a default timezone is set (dayjsLib.tz.setDefault()),
+ // if the timezone plugin is loaded,
// then use the timezone aware version
- const dayjs = dayjsLib.tz().$x.$timezone ? dayjsLib.tz : dayjsLib
+ const dayjs = dayjsLib.tz ? dayjsLib.tz : dayjsLib
function getTimezoneOffset(date) {
// ensures this gets cast to timezone
@@ -66,7 +87,10 @@ export default function (dayjsLib) {
// 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
From e3d68f0c338f3fc44df4f038ec66505592be374a Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Fri, 30 Sep 2022 10:28:22 +0200
Subject: [PATCH 08/15] docs: updated README.md & exampleCode to reflect dayjs
plugins being loaded by the localizer
---
README.md | 22 ++--------------------
stories/demos/exampleCode/dayjs.js | 18 +-----------------
2 files changed, 3 insertions(+), 37 deletions(-)
diff --git a/README.md b/README.md
index e762209c12..34b5f578b5 100644
--- a/README.md
+++ b/README.md
@@ -120,30 +120,12 @@ const MyCalendar = (props) => (
)
```
+#### Day.js
+
```js
import { Calendar, dayjsLocalizer } from 'react-big-calendar'
import dayjs from 'dayjs'
-// import necessary dayjs plugins
-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 timezone from 'dayjs/plugin/timezone'
-import utc from 'dayjs/plugin/utc'
-
-// load necessary dayjs plugins
-dayjs.extend(isBetween)
-dayjs.extend(isSameOrAfter)
-dayjs.extend(isSameOrBefore)
-dayjs.extend(localeData)
-dayjs.extend(localizedFormat)
-dayjs.extend(minMax)
-dayjs.extend(timezone)
-dayjs.extend(utc)
-
const localizer = dayjsLocalizer(dayjs)
const MyCalendar = (props) => (
diff --git a/stories/demos/exampleCode/dayjs.js b/stories/demos/exampleCode/dayjs.js
index ef0a3af272..cba0a6c1ae 100644
--- a/stories/demos/exampleCode/dayjs.js
+++ b/stories/demos/exampleCode/dayjs.js
@@ -5,25 +5,9 @@ import DemoLink from '../../DemoLink.component'
import events from '../../resources/events'
import * as dates from '../../../src/utils/dates'
-// import dayjs plugins
-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'
+// add optional time zone support
import timezone from 'dayjs/plugin/timezone'
-import utc from 'dayjs/plugin/utc'
-
-// load dayjs plugins
-dayjs.extend(isBetween)
-dayjs.extend(isSameOrAfter)
-dayjs.extend(isSameOrBefore)
-dayjs.extend(localeData)
-dayjs.extend(localizedFormat)
-dayjs.extend(minMax)
dayjs.extend(timezone)
-dayjs.extend(utc)
const djLocalizer = dayjsLocalizer(dayjs)
From c33ee90859517fd19b2819c574b7246267c935df Mon Sep 17 00:00:00 2001
From: Marnix Heuker of Hoek <47228669+marnixhoh@users.noreply.github.com>
Date: Fri, 30 Sep 2022 10:31:40 +0200
Subject: [PATCH 09/15] docs(localizer props): added dayjs example & sorted
examples alphabetically
---
stories/props/localizer.mdx | 39 ++++++++++++++++++++++++-------------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/stories/props/localizer.mdx b/stories/props/localizer.mdx
index 3fb52a7282..e43c6be04d 100644
--- a/stories/props/localizer.mdx
+++ b/stories/props/localizer.mdx
@@ -8,24 +8,24 @@ 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
+
+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 +45,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`.