Skip to content

Commit

Permalink
fix: Correct display of beginning DST
Browse files Browse the repository at this point in the history
This corrects jquense#1617, fixing the display of the TimeGutter times as well as correcting event layouts from the momentLocalizer, while maintaining date math within the localizers.
  • Loading branch information
cutterbl authored Feb 3, 2022
1 parent 14f060c commit bd8e0e9
Show file tree
Hide file tree
Showing 7 changed files with 367 additions and 322 deletions.
29 changes: 26 additions & 3 deletions src/TimeGutter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,45 @@ import React, { Component } from 'react'
import * as TimeSlotUtils from './utils/TimeSlots'
import TimeSlotGroup from './TimeSlotGroup'

/**
* Since the TimeGutter only displays the 'times' of slots in a day, and is separate
* from the Day Columns themselves, we check to see if the range contains an offset difference
* and, if so, change the beginning and end 'date' by a day to properly display the slots times
* used.
*/
function adjustForDST({ min, max, localizer }) {
if (localizer.getTimezoneOffset(min) !== localizer.getTimezoneOffset(max)) {
return {
start: localizer.add(min, -1, 'day'),
end: localizer.add(max, -1, 'day'),
}
}
return { start: min, end: max }
}

export default class TimeGutter extends Component {
constructor(...args) {
super(...args)

const { min, max, timeslots, step, localizer } = this.props
const { start, end } = adjustForDST({ min, max, localizer })
this.slotMetrics = TimeSlotUtils.getSlotMetrics({
min,
max,
min: start,
max: end,
timeslots,
step,
localizer,
})
}

UNSAFE_componentWillReceiveProps(nextProps) {
this.slotMetrics = this.slotMetrics.update(nextProps)
const { min, max, localizer } = nextProps
const { start, end } = adjustForDST({ min, max, localizer })
this.slotMetrics = this.slotMetrics.update({
...nextProps,
min: start,
max: end,
})
}

renderSlot = (value, idx) => {
Expand Down
7 changes: 4 additions & 3 deletions src/less/time-grid.less
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

.rbc-time-gutter {
white-space: nowrap;
text-align: right;
}

.rbc-allday-cell {
Expand Down Expand Up @@ -95,9 +96,9 @@
border-right: 1px solid @cell-border;
}

>.rbc-row.rbc-row-resource {
border-bottom: 1px solid @cell-border;
flex-shrink: 0;
> .rbc-row.rbc-row-resource {
border-bottom: 1px solid @cell-border;
flex-shrink: 0;
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/localizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ export class DateLocalizer {
this.visibleDays = spec.visibleDays || visibleDays

this.getSlotDate = spec.getSlotDate || getSlotDate
this.getTimezoneOffset =
spec.getTimezoneOffset || (value => value.getTimezoneOffset())
this.getDstOffset = spec.getDstOffset || getDstOffset
this.getTotalMin = spec.getTotalMin || getTotalMin
this.getMinutesFromMidnight =
spec.getMinutesFromMidnight || getMinutesFromMidnight
Expand Down
35 changes: 34 additions & 1 deletion src/localizers/moment.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,37 @@ function fixUnit(unit) {
export default function(moment) {
const locale = (m, c) => (c ? m.locale(c) : m)

function getTimezoneOffset(date) {
// ensures this gets cast to timezone
return moment(date)
.toDate()
.getTimezoneOffset()
}

function getDstOffset(start, end) {
// convert to moment, in case
const st = moment(start)
const ed = moment(end)
// if not using moment timezone
if (!moment.tz) {
return st.toDate().getTimezoneOffset() - ed.toDate().getTimezoneOffset()
}
/**
* If using moment-timezone, and a timezone has been applied, then
* use this to get the proper timezone offset, otherwise default
* the timezone to the browser local
*/
const tzName = st?._z?.name ?? moment.tz.guess()
const startOffset = moment.tz.zone(tzName).utcOffset(+st)
const endOffset = moment.tz.zone(tzName).utcOffset(+ed)
return startOffset - endOffset
}

function getDayStartDstOffset(start) {
const dayStart = moment(start).startOf('day')
return getDstOffset(dayStart, start)
}

/*** BEGIN localized date arithmetic methods with moment ***/
function defineComparators(a, b, unit) {
const datePart = fixUnit(unit)
Expand Down Expand Up @@ -242,7 +273,7 @@ export default function(moment) {
function getMinutesFromMidnight(start) {
const dayStart = moment(start).startOf('day')
const day = moment(start)
return day.diff(dayStart, 'minutes')
return day.diff(dayStart, 'minutes') + getDayStartDstOffset(start)
}

// These two are used by DateSlotMetrics
Expand Down Expand Up @@ -358,6 +389,8 @@ export default function(moment) {
minutes,

getSlotDate,
getTimezoneOffset,
getDstOffset,
getTotalMin,
getMinutesFromMidnight,
continuesPrior,
Expand Down
7 changes: 4 additions & 3 deletions src/sass/time-grid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

.rbc-time-gutter {
white-space: nowrap;
text-align: right;
}

.rbc-allday-cell {
Expand Down Expand Up @@ -95,9 +96,9 @@
border-right: 1px solid $cell-border;
}

>.rbc-row.rbc-row-resource {
border-bottom: 1px solid $cell-border;
flex-shrink: 0;
> .rbc-row.rbc-row-resource {
border-bottom: 1px solid $cell-border;
flex-shrink: 0;
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/utils/TimeSlots.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ export function getSlotMetrics({
)

function positionFromDate(date) {
const diff = localizer.getTotalMin(start, date)
const diff =
localizer.diff(start, date, 'minutes') +
localizer.getDstOffset(start, date)
return Math.min(diff, totalMin)
}

Expand Down
Loading

0 comments on commit bd8e0e9

Please sign in to comment.