Skip to content

Commit

Permalink
fix(ui-calendar): fix duplicate dates for certain timezones
Browse files Browse the repository at this point in the history
  • Loading branch information
balzss committed Oct 2, 2024
1 parent 13790d1 commit 68bfc78
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 106 deletions.
206 changes: 103 additions & 103 deletions packages/instui-config/package-lists/v11/package-list.json
Original file line number Diff line number Diff line change
@@ -1,104 +1,104 @@
[
"@instructure/babel-plugin-transform-imports",
"@instructure/browserslist-config-instui",
"@instructure/canvas-high-contrast-theme",
"@instructure/canvas-theme",
"@instructure/command-utils",
"@instructure/console",
"@instructure/cz-lerna-changelog",
"@instructure/debounce",
"@instructure/emotion",
"@instructure/instui-config",
"@instructure/shared-types",
"@instructure/theme-registry",
"@instructure/ui",
"@instructure/ui-a11y-content",
"@instructure/ui-a11y-utils",
"@instructure/ui-alerts",
"@instructure/ui-avatar",
"@instructure/ui-axe-check",
"@instructure/ui-badge",
"@instructure/ui-billboard",
"@instructure/ui-breadcrumb",
"@instructure/ui-buttons",
"@instructure/ui-byline",
"@instructure/ui-calendar",
"@instructure/ui-checkbox",
"@instructure/ui-code-editor",
"@instructure/ui-codemods",
"@instructure/ui-color-picker",
"@instructure/ui-color-utils",
"@instructure/ui-date-input",
"@instructure/ui-date-time-input",
"@instructure/ui-decorator",
"@instructure/ui-dialog",
"@instructure/ui-dom-utils",
"@instructure/ui-drawer-layout",
"@instructure/ui-drilldown",
"@instructure/ui-editable",
"@instructure/ui-expandable",
"@instructure/ui-file-drop",
"@instructure/ui-flex",
"@instructure/ui-focusable",
"@instructure/ui-form-field",
"@instructure/ui-grid",
"@instructure/ui-heading",
"@instructure/ui-i18n",
"@instructure/ui-icons",
"@instructure/ui-icons-build",
"@instructure/ui-img",
"@instructure/ui-link",
"@instructure/ui-list",
"@instructure/ui-menu",
"@instructure/ui-metric",
"@instructure/ui-modal",
"@instructure/ui-motion",
"@instructure/ui-navigation",
"@instructure/ui-number-input",
"@instructure/ui-options",
"@instructure/ui-overlays",
"@instructure/ui-pages",
"@instructure/ui-pagination",
"@instructure/ui-pill",
"@instructure/ui-popover",
"@instructure/ui-portal",
"@instructure/ui-position",
"@instructure/ui-progress",
"@instructure/ui-prop-types",
"@instructure/ui-radio-input",
"@instructure/ui-range-input",
"@instructure/ui-rating",
"@instructure/ui-react-utils",
"@instructure/ui-responsive",
"@instructure/ui-select",
"@instructure/ui-selectable",
"@instructure/ui-side-nav-bar",
"@instructure/ui-simple-select",
"@instructure/ui-source-code-editor",
"@instructure/ui-spinner",
"@instructure/ui-svg-images",
"@instructure/ui-table",
"@instructure/ui-tabs",
"@instructure/ui-tag",
"@instructure/ui-test-locator",
"@instructure/ui-test-queries",
"@instructure/ui-test-sandbox",
"@instructure/ui-test-utils",
"@instructure/ui-testable",
"@instructure/ui-text",
"@instructure/ui-text-area",
"@instructure/ui-text-input",
"@instructure/ui-theme-tokens",
"@instructure/ui-themes",
"@instructure/ui-time-select",
"@instructure/ui-toggle-details",
"@instructure/ui-tooltip",
"@instructure/ui-top-nav-bar",
"@instructure/ui-tray",
"@instructure/ui-tree-browser",
"@instructure/ui-truncate-list",
"@instructure/ui-truncate-text",
"@instructure/ui-utils",
"@instructure/ui-view",
"@instructure/uid"
]
"@instructure/babel-plugin-transform-imports",
"@instructure/browserslist-config-instui",
"@instructure/canvas-high-contrast-theme",
"@instructure/canvas-theme",
"@instructure/command-utils",
"@instructure/console",
"@instructure/cz-lerna-changelog",
"@instructure/debounce",
"@instructure/emotion",
"@instructure/instui-config",
"@instructure/shared-types",
"@instructure/theme-registry",
"@instructure/ui",
"@instructure/ui-a11y-content",
"@instructure/ui-a11y-utils",
"@instructure/ui-alerts",
"@instructure/ui-avatar",
"@instructure/ui-axe-check",
"@instructure/ui-badge",
"@instructure/ui-billboard",
"@instructure/ui-breadcrumb",
"@instructure/ui-buttons",
"@instructure/ui-byline",
"@instructure/ui-calendar",
"@instructure/ui-checkbox",
"@instructure/ui-code-editor",
"@instructure/ui-codemods",
"@instructure/ui-color-picker",
"@instructure/ui-color-utils",
"@instructure/ui-date-input",
"@instructure/ui-date-time-input",
"@instructure/ui-decorator",
"@instructure/ui-dialog",
"@instructure/ui-dom-utils",
"@instructure/ui-drawer-layout",
"@instructure/ui-drilldown",
"@instructure/ui-editable",
"@instructure/ui-expandable",
"@instructure/ui-file-drop",
"@instructure/ui-flex",
"@instructure/ui-focusable",
"@instructure/ui-form-field",
"@instructure/ui-grid",
"@instructure/ui-heading",
"@instructure/ui-i18n",
"@instructure/ui-icons",
"@instructure/ui-icons-build",
"@instructure/ui-img",
"@instructure/ui-link",
"@instructure/ui-list",
"@instructure/ui-menu",
"@instructure/ui-metric",
"@instructure/ui-modal",
"@instructure/ui-motion",
"@instructure/ui-navigation",
"@instructure/ui-number-input",
"@instructure/ui-options",
"@instructure/ui-overlays",
"@instructure/ui-pages",
"@instructure/ui-pagination",
"@instructure/ui-pill",
"@instructure/ui-popover",
"@instructure/ui-portal",
"@instructure/ui-position",
"@instructure/ui-progress",
"@instructure/ui-prop-types",
"@instructure/ui-radio-input",
"@instructure/ui-range-input",
"@instructure/ui-rating",
"@instructure/ui-react-utils",
"@instructure/ui-responsive",
"@instructure/ui-select",
"@instructure/ui-selectable",
"@instructure/ui-side-nav-bar",
"@instructure/ui-simple-select",
"@instructure/ui-source-code-editor",
"@instructure/ui-spinner",
"@instructure/ui-svg-images",
"@instructure/ui-table",
"@instructure/ui-tabs",
"@instructure/ui-tag",
"@instructure/ui-test-locator",
"@instructure/ui-test-queries",
"@instructure/ui-test-sandbox",
"@instructure/ui-test-utils",
"@instructure/ui-testable",
"@instructure/ui-text",
"@instructure/ui-text-area",
"@instructure/ui-text-input",
"@instructure/ui-theme-tokens",
"@instructure/ui-themes",
"@instructure/ui-time-select",
"@instructure/ui-toggle-details",
"@instructure/ui-tooltip",
"@instructure/ui-top-nav-bar",
"@instructure/ui-tray",
"@instructure/ui-tree-browser",
"@instructure/ui-truncate-list",
"@instructure/ui-truncate-text",
"@instructure/ui-utils",
"@instructure/ui-view",
"@instructure/uid"
]
19 changes: 17 additions & 2 deletions packages/ui-calendar/src/Calendar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -499,10 +499,25 @@ class Calendar extends Component<CalendarProps, CalendarState> {
const currDate = DateTime.getFirstDayOfWeek(
visibleMonth.clone().startOf('month')
)

const arr: Moment[] = []
for (let i = 0; i < Calendar.DAY_COUNT; i++) {
arr.push(currDate.clone())
currDate.add({ days: 1 })

// This workaround is needed because moment's `.add({days: 1})` function has a bug that happens when the date added lands perfectly onto the DST cutoff,
// in these cases adding 1 day results in 23 hours added instead,
// so `moment.tz('2024-09-07T00:00:00', 'America/Santiago').add({days: 1})` results
// in "Sat Sep 07 2024 23:00:00 GMT-0400" instead of "Sun Sep 08 2024 00:00:00 GMT-0400".
// which would cause duplicate dates in the calendar.
// More info on the bug: https://github.com/moment/moment/issues/4743
// Please note that this causes one hour of time difference in the affected timezones/dates and to
// fully solve this bug we need to change to something like luxon which handles this properly
if (currDate.clone().format('HH') === '23') {
arr.push(currDate.clone().add({hours: 1}))
} else {
arr.push(currDate.clone())
}

currDate.add({days: 1})
}
return arr.map((date) => {
const dateStr = date.toISOString()
Expand Down
12 changes: 12 additions & 0 deletions packages/ui-date-time-input/src/DateTimeInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,18 @@ class DateTimeInput extends Component<DateTimeInputProps, DateTimeInputState> {
for (let i = 0; i < Calendar.DAY_COUNT; i++) {
arr.push(currDate.clone())
currDate.add({ days: 1 })

// This workaround is needed because moment's `.add({days: 1})` function has a bug that happens when the date added lands perfectly onto the DST cutoff,
// in these cases adding 1 day results in 23 hours added instead,
// so `moment.tz('2024-09-07T00:00:00', 'America/Santiago').add({days: 1})` results
// in "Sat Sep 07 2024 23:00:00 GMT-0400" instead of "Sun Sep 08 2024 00:00:00 GMT-0400".
// which would cause duplicate dates in the calendar.
// More info and source for the workaround: https://github.com/moment/moment/issues/4743
// Please note that this causes one hour of time difference in the affected timezones/dates and to
// fully solve this bug we need to change to something like luxon which handles this properly
if (currDate.clone().format('HH') === '23') {
currDate.add({hours: 1})
}
}
return arr.map((date) => {
const dateStr = date.toISOString()
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-i18n/src/DateTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import moment, { Moment } from 'moment-timezone'
* category: utilities/i18n
* ---
* @deprecated
* #### DEPRECATION WARNING: Will be removed in v9, which wil include a
* #### DEPRECATION WARNING: Will be removed in a future version, which will include a
* time library agnostic API.
* A wrapper for [moment](https://momentjs.com/) utils.
* @module DateTime
Expand Down

0 comments on commit 68bfc78

Please sign in to comment.