Skip to content

Commit

Permalink
fix(calendar): show offDays and eventDays for different timezones (#1233
Browse files Browse the repository at this point in the history
)

* fix(calendar): show offDays and eventDays for different timezones

* fix(calendar): use binary search; add separate function checkDaysIgnoringTimezone

* test(calendar): fix tests

Co-authored-by: Полонский Роман Вадимович <RPolonskiy@alfabank.ru>
  • Loading branch information
rpolonsky and Полонский Роман Вадимович committed Dec 18, 2020
1 parent dd81855 commit 128d9f4
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 4 deletions.
16 changes: 14 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"dependencies": {
"@babel/runtime-corejs2": "^7.7.6",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/lodash.sortedindexby": "^4.6.6",
"bem-react-classname": "1.2.1",
"bezier-easing": "2.1.0",
"cn-decorator": "^2.1.0",
Expand All @@ -91,6 +92,7 @@
"inputmask-core": "2.2.0",
"libphonenumber-js": "1.0.24",
"lodash.debounce": "4.0.8",
"lodash.sortedindexby": "^4.6.0",
"lodash.sortedindexof": "4.1.0",
"matches-selector-polyfill": "1.0.0",
"prop-types": "15.7.2",
Expand Down
1 change: 1 addition & 0 deletions src/calendar/__snapshots__/calendar.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
exports[`calendar should render without problems 1`] = `
<Calendar
eventDays={Array []}
ignoreTimezone={false}
isKeyboard={true}
month={1529020800000}
months={
Expand Down
38 changes: 38 additions & 0 deletions src/calendar/calendar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -362,4 +362,42 @@ describe('calendar', () => {

expect(days.length).toBe(42);
});

it('should render eventDays for different timezone with enabled ignoreTimezone', () => {
const eventDays = [
1604696400000,
1604782800000,
1605042000000,
];
const calendar = mount(
<Calendar
value={startOfDay(new Date('2020-11-15')).valueOf()}
ignoreTimezone={ true }
eventDays={ eventDays }
/>
);

const days = calendar.find('.calendar__event');

expect(days.length).toBe(3);
});

it('should render offDays for different timezone with enabled ignoreTimezone', () => {
const offDays = [
1605387600000,
1605992400000,
1606597200000,
];
const calendar = mount(
<Calendar
value={startOfDay(new Date('2020-11-15')).valueOf()}
ignoreTimezone={ true }
offDays={ offDays }
/>
);

const days = calendar.find('.calendar__day_type_weekend-off');

expect(days.length).toBe(3);
});
});
32 changes: 30 additions & 2 deletions src/calendar/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import setYear from 'date-fns/set_year';
import endOfMonth from 'date-fns/end_of_month';
import eachDay from 'date-fns/each_day';
import sortedIndexOf from 'lodash.sortedindexof';
import sortedIndexBy from 'lodash.sortedindexby';

import keyboardCode from '../lib/keyboard-code';
import performance from '../performance';
Expand All @@ -36,6 +37,7 @@ const EARLY_YEARS_LIMIT = 100;
const LATER_YEARS_LIMIT = 1;
const TOTAL_WEEK_NUMBER = 6;
const SUNDAY_INDEX = 6;
const WITHOUT_TIME_FORMAT = 'YYYY-MM-DD';

export type CalendarProps = {

Expand Down Expand Up @@ -119,6 +121,12 @@ export type CalendarProps = {
*/
isKeyboard?: boolean;

/**
* Игнорировать различие часовых поясов клиента и сервера. Для корректного отображения offDays и eventDays
* в том случае, если часовой пояс клиента отличается от часового пояса дат в offDays и eventDays
*/
ignoreTimezone?: boolean;

/**
* Управление шириной календаря. При значении 'available' растягивает кнопку на ширину родителя
*/
Expand Down Expand Up @@ -190,6 +198,7 @@ export class Calendar extends React.Component<CalendarProps, CalendarState> {
showToday: false,
showArrows: true,
isKeyboard: true,
ignoreTimezone: false,
};

state: CalendarState = {
Expand Down Expand Up @@ -723,6 +732,9 @@ export class Calendar extends React.Component<CalendarProps, CalendarState> {
*/
private isOffDay(date: Date | number) {
if (this.props.offDays && Array.isArray(this.props.offDays)) {
if (this.props.ignoreTimezone) {
return Calendar.checkDaysIgnoringTimezone(this.props.offDays, date);
}
const timestamp = date.valueOf();

// Поскольку offDays - отсортирован, используем бинарный поиск, O(log n) против O(n) для обычного поиска
Expand All @@ -733,15 +745,18 @@ export class Calendar extends React.Component<CalendarProps, CalendarState> {
}

/**
* Возвращает `true`, если переданная дата является днм с событиями.
* Возвращает `true`, если переданная дата является днем с событиями.
*
* @param date Дата для проверки
*/
private isEventDay(date: Date | number) {
if (this.props.eventDays && Array.isArray(this.props.eventDays) && date !== null) {
if (this.props.ignoreTimezone) {
return Calendar.checkDaysIgnoringTimezone(this.props.eventDays, date);
}
const timestamp = date.valueOf();

// Поскольку events - отсортирован, используем бинарный поиск, O(log n) против O(n) для обычного поиска
// Поскольку eventDays - отсортирован, используем бинарный поиск, O(log n) против O(n) для обычного поиска
return sortedIndexOf(this.props.eventDays, timestamp) !== -1;
}

Expand Down Expand Up @@ -925,6 +940,19 @@ export class Calendar extends React.Component<CalendarProps, CalendarState> {
? normalizeDate(nextProps.selectedFrom) : null;
}
}

/**
* Проверяет наличие даты в списке дат с игнорированием таймзоны.
*
* @param date Дата
* @param daysToСheck Список дат для проверки
*/
private static checkDaysIgnoringTimezone(daysToCheck: readonly number[], date: Date | number) {
const dateWithoutTime = formatDate(date, WITHOUT_TIME_FORMAT);
/* Используем бинарный поиск */
const index = sortedIndexBy<string | number>(daysToCheck, dateWithoutTime, (day) => formatDate(day, WITHOUT_TIME_FORMAT));
return dateWithoutTime === formatDate(daysToCheck[index], WITHOUT_TIME_FORMAT);
}
}

export default withTheme<CalendarProps, Calendar>(Calendar);

0 comments on commit 128d9f4

Please sign in to comment.