Skip to content

Commit

Permalink
Add formatDay prop, fix Day ignoring locale when formatting day numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
wojtekmaj committed Apr 16, 2021
1 parent 1349806 commit a77389f
Show file tree
Hide file tree
Showing 8 changed files with 332 additions and 97 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ Displays a complete, interactive calendar.
|defaultActiveStartDate|The beginning of a period that shall be displayed by default. If you wish to use React-Calendar in a controlled way, use `activeStartDate` instead.|(today)|`new Date(2017, 0, 1)`|
|defaultValue|Calendar value that shall be selected initially. Can be either one value or an array of two values. If you wish to use React-Calendar in a controlled way, use `value` instead.|n/a|<ul><li>Date: `new Date()`</li><li>An array of dates: `[new Date(2017, 0, 1), new Date(2017, 7, 1)]`|
|defaultView|Determines which calendar view shall be opened initially. Does not disable navigation. Can be `"month"`, `"year"`, `"decade"` or `"century"`. If you wish to use React-Calendar in a controlled way, use `view` instead.|The most detailed view allowed|`"year"`|
|formatLongDate|Function called to override default formatting of day tiles. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'dd MMM YYYY')`|
|formatDay|Function called to override default formatting of day tile labels. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'dd')`|
|formatLongDate|Function called to override default formatting of day tile `abbr` labels. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'dd MMM YYYY')`|
|formatMonth|Function called to override default formatting of month names. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'MMM')`|
|formatMonthYear|Function called to override default formatting of months and years. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'MMMM YYYY')`|
|formatShortWeekday|Function called to override default formatting of weekday names. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'dd')`|
Expand Down
3 changes: 3 additions & 0 deletions src/Calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ export default class Calendar extends Component {
}
case 'month': {
const {
formatDay,
formatLongDate,
formatShortWeekday,
onClickWeekNumber,
Expand All @@ -536,6 +537,7 @@ export default class Calendar extends Component {
return (
<MonthView
calendarType={calendarType}
formatDay={formatDay}
formatLongDate={formatLongDate}
formatShortWeekday={formatShortWeekday}
onClickWeekNumber={onClickWeekNumber}
Expand Down Expand Up @@ -664,6 +666,7 @@ Calendar.propTypes = {
defaultActiveStartDate: isActiveStartDate,
defaultValue: isLooseValue,
defaultView: isView,
formatDay: PropTypes.func,
formatLongDate: PropTypes.func,
formatMonth: PropTypes.func,
formatMonthYear: PropTypes.func,
Expand Down
13 changes: 13 additions & 0 deletions src/Calendar.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,19 @@ describe('Calendar', () => {
expect(navigation.prop('formatYear')).toBe(formatYear);
});

it('passes formatDay to MonthView component', () => {
const formatDay = () => 'Day';
const component = shallow(
<Calendar
formatDay={formatDay}
/>,
);

const monthView = component.find('MonthView');

expect(monthView.prop('formatDay')).toBe(formatDay);
});

it('passes formatLongDate to MonthView component', () => {
const formatLongDate = () => 'Long date';
const component = shallow(
Expand Down
15 changes: 15 additions & 0 deletions src/MonthView.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,21 @@ describe('MonthView', () => {
expect(days.prop('calendarType')).toBe('US');
});

it('passes formatDay flag to Days component', () => {
const formatDay = () => 'Day';

const component = shallow(
<MonthView
{...defaultProps}
formatDay={formatDay}
/>,
);

const days = component.find('Days');

expect(days.prop('formatDay')).toBe(formatDay);
});

it('passes formatLongDate flag to Days component', () => {
const formatLongDate = () => 'Long date';

Expand Down
13 changes: 9 additions & 4 deletions src/MonthView/Day.jsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import React from 'react';
import PropTypes from 'prop-types';
import { getDate, getDayStart, getDayEnd } from '@wojtekmaj/date-utils';
import { getDayStart, getDayEnd } from '@wojtekmaj/date-utils';

import Tile from '../Tile';

import { isWeekend } from '../shared/dates';
import { formatLongDate as defaultFormatLongDate } from '../shared/dateFormatter';
import {
formatDay as defaultFormatDay,
formatLongDate as defaultFormatLongDate,
} from '../shared/dateFormatter';
import { tileProps } from '../shared/propTypes';

const className = 'react-calendar__month-view__days__day';

export default function Day({
formatDay = defaultFormatDay,
formatLongDate = defaultFormatLongDate,
calendarType,
classes,
currentMonthIndex,
...otherProps
}) {
const { date } = otherProps;
const { date, locale } = otherProps;

return (
<Tile
Expand All @@ -33,13 +37,14 @@ export default function Day({
minDateTransform={getDayStart}
view="month"
>
{getDate(date)}
{formatDay(locale, date)}
</Tile>
);
}

Day.propTypes = {
...tileProps,
currentMonthIndex: PropTypes.number.isRequired,
formatDay: PropTypes.func,
formatLongDate: PropTypes.func,
};
22 changes: 22 additions & 0 deletions src/MonthView/Day.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,28 @@ describe('Day', () => {
expect(testContent).toHaveLength(1);
});

it('uses formatDay if given', () => {
const locale = 'en-US';
const date = new Date(2018, 0, 1);
const formatDay = jest.fn();
formatDay.mockReturnValue('Mock format');

const component = mount(
<Day
{...tileProps}
date={date}
formatDay={formatDay}
locale={locale}
/>,
);

const tile = component.find('Tile');

expect(formatDay).toHaveBeenCalled();
expect(formatDay).toHaveBeenCalledWith(locale, date);
expect(tile.text()).toBe('Mock format');
});

it('uses formatLongDate if given', () => {
const locale = 'en-US';
const date = new Date(2018, 0, 1);
Expand Down
6 changes: 4 additions & 2 deletions src/shared/dateFormatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,19 @@ function getSafeFormatter(options) {
}

const formatDateOptions = { day: 'numeric', month: 'numeric', year: 'numeric' };
const formatDayOptions = { day: 'numeric' };
const formatLongDateOptions = { day: 'numeric', month: 'long', year: 'numeric' };
const formatMonthOptions = { month: 'long' };
const formatMonthYearOptions = { month: 'long', year: 'numeric' };
const formatYearOptions = { year: 'numeric' };
const formatShortWeekdayOptions = { weekday: 'short' };
const formatWeekdayOptions = { weekday: 'long' };
const formatYearOptions = { year: 'numeric' };

export const formatDate = getSafeFormatter(formatDateOptions);
export const formatDay = getSafeFormatter(formatDayOptions);
export const formatLongDate = getSafeFormatter(formatLongDateOptions);
export const formatMonth = getSafeFormatter(formatMonthOptions);
export const formatMonthYear = getSafeFormatter(formatMonthYearOptions);
export const formatYear = getSafeFormatter(formatYearOptions);
export const formatShortWeekday = getSafeFormatter(formatShortWeekdayOptions);
export const formatWeekday = getSafeFormatter(formatWeekdayOptions);
export const formatYear = getSafeFormatter(formatYearOptions);
Loading

0 comments on commit a77389f

Please sign in to comment.