From f210b330de933c43eefa5993b233a4209e50407a Mon Sep 17 00:00:00 2001 From: Anurag Date: Thu, 12 Aug 2021 13:13:05 +0530 Subject: [PATCH 1/8] refactor: migrating to dayjs --- package.json | 1 + src/calendar/CalendarCell.ts | 9 +- src/calendar/CalendarCellButton.ts | 3 +- src/calendar/CalendarState.ts | 24 +++--- src/calendar/RangeCalendarState.ts | 9 +- src/calendar/__tests__/Calendar.test.tsx | 2 +- src/calendar/helpers/index.ts | 6 +- src/calendar/stories/CalendarBase.stories.tsx | 3 +- .../stories/CalendarRange.stories.tsx | 8 +- src/datepicker/__tests__/DatePicker.test.tsx | 2 +- .../stories/DatePickerBase.stories.tsx | 7 +- .../stories/DatePickerRange.stories.tsx | 8 +- .../stories/DateRangePickerStyled.stories.tsx | 2 +- src/segment/helpers/index.ts | 2 +- src/timepicker/TimePickerState.ts | 2 +- src/timepicker/helpers.ts | 2 +- src/utils/date.ts | 85 ++++++++++++++++++- yarn.lock | 5 ++ 18 files changed, 148 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 213a2f52f..d7aace3d5 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "@react-aria/spinbutton": "3.0.0", "@react-aria/utils": "3.8.1", "date-fns": "2.22.1", + "dayjs": "^1.10.6", "reakit-system": "0.15.1", "reakit-utils": "0.15.1", "reakit-warning": "^0.6.1" diff --git a/src/calendar/CalendarCell.ts b/src/calendar/CalendarCell.ts index ea8fa2af9..19cb4ef73 100644 --- a/src/calendar/CalendarCell.ts +++ b/src/calendar/CalendarCell.ts @@ -7,9 +7,14 @@ import { useCallback } from "react"; import { callAllHandlers } from "@chakra-ui/utils"; import { RoleHTMLProps, RoleOptions, useRole } from "reakit"; import { createComponent, createHook } from "reakit-system"; -import { getDaysInMonth, isSameDay, isWeekend } from "date-fns"; -import { dataAttr, ariaAttr } from "../utils"; +import { + dataAttr, + ariaAttr, + getDaysInMonth, + isSameDay, + isWeekend, +} from "../utils"; import { CALENDAR_CELL_KEYS } from "./__keys"; import { CalendarStateReturn } from "./CalendarState"; import { RangeCalendarStateReturn } from "./RangeCalendarState"; diff --git a/src/calendar/CalendarCellButton.ts b/src/calendar/CalendarCellButton.ts index 663af6bff..bb684e9a2 100644 --- a/src/calendar/CalendarCellButton.ts +++ b/src/calendar/CalendarCellButton.ts @@ -4,14 +4,13 @@ * to work with Reakit System */ import * as React from "react"; -import { isSameDay } from "date-fns"; import { callAllHandlers } from "@chakra-ui/utils"; import { useDateFormatter } from "@react-aria/i18n"; import { ensureFocus, useForkRef } from "reakit-utils"; import { createComponent, createHook } from "reakit-system"; import { ButtonHTMLProps, ButtonOptions, useButton } from "reakit"; -import { isInvalidDateRange } from "../utils"; +import { isInvalidDateRange, isSameDay } from "../utils"; import { CALENDAR_CELL_BUTTON_KEYS } from "./__keys"; import { CalendarStateReturn } from "./CalendarState"; import { RangeCalendarStateReturn } from "./RangeCalendarState"; diff --git a/src/calendar/CalendarState.ts b/src/calendar/CalendarState.ts index 9e1ec1bdc..25c599460 100644 --- a/src/calendar/CalendarState.ts +++ b/src/calendar/CalendarState.ts @@ -9,7 +9,6 @@ import { addMonths, addWeeks, addYears, - closestTo, endOfMonth, format, getDaysInMonth, @@ -20,19 +19,18 @@ import { subMonths, subWeeks, subYears, -} from "date-fns"; + parseDate, + stringifyDate, + isInvalidDateRange, + useControllableState, +} from "../utils"; +import { closestTo } from "../utils"; import * as React from "react"; import { unstable_useId as useId } from "reakit"; import { useUpdateEffect } from "@chakra-ui/hooks"; import { useDateFormatter } from "@react-aria/i18n"; import { InputBase } from "@react-types/shared"; -import { - parseDate, - stringifyDate, - isInvalidDateRange, - useControllableState, -} from "../utils"; import { announce } from "../utils/LiveAnnouncer"; import { useWeekStart, useWeekDays, generateDaysInMonthArray } from "./helpers"; @@ -77,7 +75,7 @@ export function useCalendarState( const weekStart = useWeekStart(); const weekDays = useWeekDays(weekStart); - let monthStartsAt = (startOfMonth(currentMonth).getDay() - weekStart) % 7; + let monthStartsAt = (startOfMonth(currentMonth).get("day") - weekStart) % 7; if (monthStartsAt < 0) { monthStartsAt += 7; } @@ -103,7 +101,7 @@ export function useCalendarState( const nextDate = closestTo(date, [minValue, maxValue]); if (!isSameMonth(nextDate, currentMonth)) { - setCurrentMonth(startOfMonth(nextDate)); + setCurrentMonth(startOfMonth(nextDate).toDate()); } setFocusedDate(nextDate); } @@ -112,7 +110,7 @@ export function useCalendarState( } if (!isSameMonth(date, currentMonth)) { - setCurrentMonth(startOfMonth(date)); + setCurrentMonth(startOfMonth(date).toDate()); } setFocusedDate(date); @@ -181,10 +179,10 @@ export function useCalendarState( focusCell(subMonths(focusedDate, 1)); }, focusStartOfMonth() { - focusCell(startOfMonth(focusedDate)); + focusCell(startOfMonth(focusedDate).toDate()); }, focusEndOfMonth() { - focusCell(endOfMonth(startOfDay(focusedDate))); + focusCell(endOfMonth(startOfDay(focusedDate).toDate()).toDate()); }, focusNextYear() { focusCell(addYears(focusedDate, 1)); diff --git a/src/calendar/RangeCalendarState.ts b/src/calendar/RangeCalendarState.ts index f5b3372ec..7fcb76b4e 100644 --- a/src/calendar/RangeCalendarState.ts +++ b/src/calendar/RangeCalendarState.ts @@ -4,14 +4,19 @@ * to work with Reakit System */ import * as React from "react"; -import { format, isSameDay } from "date-fns"; import { InputBase, RangeValue } from "@react-types/shared"; import { makeRange } from "./helpers"; import { announce } from "../utils/LiveAnnouncer"; import { useCalendarState } from "./CalendarState"; import { CalendarActions, CalendarState } from "./CalendarState"; -import { parseRangeDate, stringifyDate, useControllableState } from "../utils"; +import { + format, + isSameDay, + parseRangeDate, + stringifyDate, + useControllableState, +} from "../utils"; export function useRangeCalendarState( props: RangeCalendarInitialState = {}, diff --git a/src/calendar/__tests__/Calendar.test.tsx b/src/calendar/__tests__/Calendar.test.tsx index 2c040af0a..1f5bfceea 100644 --- a/src/calendar/__tests__/Calendar.test.tsx +++ b/src/calendar/__tests__/Calendar.test.tsx @@ -1,6 +1,5 @@ import * as React from "react"; import MockDate from "mockdate"; -import { subWeeks, addWeeks, format } from "date-fns"; import { axe, render, press, screen } from "reakit-test-utils"; import { @@ -16,6 +15,7 @@ import { } from "../index"; import { repeat } from "../../utils/test-utils"; import { cleanup } from "@testing-library/react"; +import { addWeeks, format, subWeeks } from "@renderlesskit/react/utils"; export const CalendarComp: React.FC = props => { const state = useCalendarState(props); diff --git a/src/calendar/helpers/index.ts b/src/calendar/helpers/index.ts index 9440b2966..4983657b1 100644 --- a/src/calendar/helpers/index.ts +++ b/src/calendar/helpers/index.ts @@ -2,16 +2,18 @@ * All credit goes to [React Spectrum](https://github.com/adobe/react-spectrum) * for these utils inspiration */ -import { setDay } from "date-fns"; import { RangeValue } from "@react-types/shared"; import { useDateFormatter } from "@react-aria/i18n"; +import dayjs from "dayjs"; export function useWeekDays(weekStart: number) { const dayFormatter = useDateFormatter({ weekday: "short" }); const dayFormatterLong = useDateFormatter({ weekday: "long" }); return [0, 1, 2, 3, 4, 5, 6].map(index => { - const dateDay = setDay(Date.now(), (index + weekStart) % 7); + const dateDay = dayjs(Date.now()) + .set("day", (index + weekStart) % 7) + .toDate(); const day = dayFormatter.format(dateDay); const dayLong = dayFormatterLong.format(dateDay); return { title: dayLong, abbr: day } as const; diff --git a/src/calendar/stories/CalendarBase.stories.tsx b/src/calendar/stories/CalendarBase.stories.tsx index 7a1c81c76..3872440ed 100644 --- a/src/calendar/stories/CalendarBase.stories.tsx +++ b/src/calendar/stories/CalendarBase.stories.tsx @@ -1,7 +1,6 @@ import * as React from "react"; import { Meta, Story } from "@storybook/react"; import { useArgs } from "@storybook/client-api"; -import { addWeeks, format } from "date-fns"; import "./CalendarBase.css"; import { @@ -13,6 +12,8 @@ import { } from "./templates"; import { App as Calendar } from "./CalendarBase.component"; import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; +import { format } from "util"; +import { addWeeks } from "@renderlesskit/react/utils"; export default { component: Calendar, diff --git a/src/calendar/stories/CalendarRange.stories.tsx b/src/calendar/stories/CalendarRange.stories.tsx index a2994ba30..48ec8ccbd 100644 --- a/src/calendar/stories/CalendarRange.stories.tsx +++ b/src/calendar/stories/CalendarRange.stories.tsx @@ -1,7 +1,6 @@ import * as React from "react"; import { Meta, Story } from "@storybook/react"; import { useArgs } from "@storybook/client-api"; -import { addDays, addWeeks, subDays, format, subWeeks } from "date-fns"; import "./CalendarRange.css"; import { @@ -13,6 +12,13 @@ import { } from "./templates"; import { App as RangeCalendar } from "./CalendarRange.component"; import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; +import { + addDays, + addWeeks, + format, + subDays, + subWeeks, +} from "@renderlesskit/react/utils"; export default { title: "Calendar/Range", diff --git a/src/datepicker/__tests__/DatePicker.test.tsx b/src/datepicker/__tests__/DatePicker.test.tsx index eb3880a8d..f2048f2ce 100644 --- a/src/datepicker/__tests__/DatePicker.test.tsx +++ b/src/datepicker/__tests__/DatePicker.test.tsx @@ -1,6 +1,5 @@ import * as React from "react"; import { cleanup } from "@testing-library/react"; -import { format, addWeeks, subWeeks } from "date-fns"; import { axe, render, press, screen } from "reakit-test-utils"; import { @@ -24,6 +23,7 @@ import { CalendarCellButton, } from "../../calendar"; import { repeat } from "../../utils/test-utils"; +import { addWeeks, format, subWeeks } from "@renderlesskit/react/utils"; /* // Mocking useId otherwise snapshots will change each time diff --git a/src/datepicker/stories/DatePickerBase.stories.tsx b/src/datepicker/stories/DatePickerBase.stories.tsx index b76b781f8..cff274241 100644 --- a/src/datepicker/stories/DatePickerBase.stories.tsx +++ b/src/datepicker/stories/DatePickerBase.stories.tsx @@ -1,7 +1,6 @@ import * as React from "react"; import { Meta, Story } from "@storybook/react"; import { useArgs } from "@storybook/client-api"; -import { addWeeks, subWeeks, format, addDays } from "date-fns"; import { datePickerBaseTemplate, @@ -13,6 +12,12 @@ import { import "./DatePickerBase.css"; import { App as DatePicker } from "./DatePickerBase.component"; import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; +import { + addDays, + addWeeks, + format, + subWeeks, +} from "@renderlesskit/react/utils"; export default { component: DatePicker, diff --git a/src/datepicker/stories/DatePickerRange.stories.tsx b/src/datepicker/stories/DatePickerRange.stories.tsx index c7780b00c..93493268f 100644 --- a/src/datepicker/stories/DatePickerRange.stories.tsx +++ b/src/datepicker/stories/DatePickerRange.stories.tsx @@ -1,7 +1,6 @@ import * as React from "react"; import { Meta, Story } from "@storybook/react"; import { useArgs } from "@storybook/client-api"; -import { addDays, format, subDays, addWeeks, subWeeks } from "date-fns"; import { datePickerRangeTemplate, @@ -13,6 +12,13 @@ import { import "./DatePickerRange.css"; import { App as DateRangePicker } from "./DatePickerRange.component"; import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; +import { + addDays, + addWeeks, + format, + subDays, + subWeeks, +} from "@renderlesskit/react/utils"; export default { title: "DatePicker/Range", diff --git a/src/datepicker/stories/DateRangePickerStyled.stories.tsx b/src/datepicker/stories/DateRangePickerStyled.stories.tsx index 1d0258ff0..62551367b 100644 --- a/src/datepicker/stories/DateRangePickerStyled.stories.tsx +++ b/src/datepicker/stories/DateRangePickerStyled.stories.tsx @@ -1,9 +1,9 @@ import * as React from "react"; -import { addWeeks } from "date-fns"; import { Meta, Story } from "@storybook/react"; import "./tailwind/index.css"; import { RangeDatePicker } from "./styled/RangeDatePicker.component"; +import { addWeeks } from "@renderlesskit/react/utils"; export default { component: RangeDatePicker, diff --git a/src/segment/helpers/index.ts b/src/segment/helpers/index.ts index 21d9efedd..b977ed8b9 100644 --- a/src/segment/helpers/index.ts +++ b/src/segment/helpers/index.ts @@ -12,7 +12,7 @@ import { setMonth, setSeconds, setYear, -} from "date-fns"; +} from "../../utils"; export function convertValue(value: Date | undefined): Date | undefined { if (!value) { diff --git a/src/timepicker/TimePickerState.ts b/src/timepicker/TimePickerState.ts index 323c76154..194fda080 100644 --- a/src/timepicker/TimePickerState.ts +++ b/src/timepicker/TimePickerState.ts @@ -7,7 +7,7 @@ import { SegmentInitialState, useSegmentState } from "../segment"; import { useTimePickerColumnState } from "./TimePickerColumnState"; import { PickerBaseInitialState, usePickerBaseState } from "../picker-base"; import { announce } from "../utils/LiveAnnouncer"; -import { format } from "date-fns"; +import { format } from "../utils"; export type TimePickerInitialState = PickerBaseInitialState & ValueBase & diff --git a/src/timepicker/helpers.ts b/src/timepicker/helpers.ts index 75682e83d..b1e0d0feb 100644 --- a/src/timepicker/helpers.ts +++ b/src/timepicker/helpers.ts @@ -1,4 +1,4 @@ -import { format } from "date-fns"; +import { format } from "../utils"; import { isString } from "@chakra-ui/utils"; import { ColumnType } from "./TimePickerColumnState"; diff --git a/src/utils/date.ts b/src/utils/date.ts index 9685e7b7b..6680ec361 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -1,4 +1,6 @@ -import { format, parse } from "date-fns"; +import { parse, format } from "date-fns"; +import dayjs from "dayjs"; + import { RangeValue } from "@react-types/shared"; export function parseDate(dateValue: string | undefined) { @@ -38,3 +40,84 @@ export function isInvalidDateRange( (maxValue != null && value > maxValue)) ); } + +export const subDays = (date: Date, amount: number) => + dayjs(date).subtract(amount, "day").toDate(); + +export const subMonths = (date: Date, amount: number) => + dayjs(date).subtract(amount, "months").toDate(); + +export const subWeeks = (date: Date, amount: number) => + dayjs(date).subtract(amount, "weeks").toDate(); + +export const subYears = (date: Date, amount: number) => + dayjs(date).subtract(amount, "years").toDate(); + +export const addDays = (date: Date, amount: number) => + dayjs(date).add(amount, "day").toDate(); + +export const addMonths = (date: Date, amount: number) => + dayjs(date).add(amount, "months").toDate(); + +export const addYears = (date: Date, amount: number) => + dayjs(date).add(amount, "years").toDate(); + +export const addWeeks = (date: Date, amount: number) => + dayjs(date).add(amount, "weeks").toDate(); + +export const getDaysInMonth = (date: Date) => dayjs(date).daysInMonth(); + +export const isSameMonth = (date1: Date, date2: Date) => + dayjs(date1).isSame(date2, "month"); + +export const isSameDay = (date1: Date, date2: Date) => + dayjs(date1).isSame(date2, "day"); + +export const isWeekend = (date: Date) => { + const day = dayjs(date).get("day"); + return day === 0 || day === 6; +}; + +// export const format = (date: Date, fmt: string) => { +// return dayjs(date).format(fmt); +// }; +export { format, closestTo } from "date-fns"; + +export const startOfMonth = (date: Date) => { + return dayjs(date).startOf("month"); +}; + +export const startOfDay = (date: Date) => { + return dayjs(date).startOf("day"); +}; + +export const endOfMonth = (date: Date) => { + return dayjs(date).endOf("month"); +}; + +export const getDate = (date: Date) => dayjs(date).get("date"); + +export const getHours = (date: Date) => dayjs(date).get("hours"); + +export const getMinutes = (date: Date) => dayjs(date).get("minutes"); + +export const getMonth = (date: Date) => dayjs(date).get("months"); + +export const getSeconds = (date: Date) => dayjs(date).get("seconds"); + +export const getYear = (date: Date) => dayjs(date).get("years"); + +export const setDate = (date: Date, value: number) => + dayjs(date).set("date", value); + +export const setHours = (date: Date, value: number) => + dayjs(date).set("hour", value); + +export const setMinutes = (date: Date, value: number) => + dayjs(date).set("minute", value); +export const setSeconds = (date: Date, value: number) => + dayjs(date).set("second", value); +export const setMonth = (date: Date, value: number) => + dayjs(date).set("month", value); +export const setYear = (date: Date, value: number) => + dayjs(date).set("year", value); diff --git a/yarn.lock b/yarn.lock index 7de2d199c..7761d2868 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6812,6 +6812,11 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +dayjs@^1.10.6: + version "1.10.6" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63" + integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw== + debug@2.6.9, debug@^2.1.3, 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 acdf514c71c0bcd070c0dc58b8cbd66c516a5b81 Mon Sep 17 00:00:00 2001 From: Anurag Date: Thu, 12 Aug 2021 13:24:09 +0530 Subject: [PATCH 2/8] test: fixed tests and updated setters --- src/calendar/__tests__/Calendar.test.tsx | 2 +- src/datepicker/__tests__/DatePicker.test.tsx | 2 +- src/utils/date.ts | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/calendar/__tests__/Calendar.test.tsx b/src/calendar/__tests__/Calendar.test.tsx index 1f5bfceea..704152507 100644 --- a/src/calendar/__tests__/Calendar.test.tsx +++ b/src/calendar/__tests__/Calendar.test.tsx @@ -15,7 +15,7 @@ import { } from "../index"; import { repeat } from "../../utils/test-utils"; import { cleanup } from "@testing-library/react"; -import { addWeeks, format, subWeeks } from "@renderlesskit/react/utils"; +import { addWeeks, format, subWeeks } from "../../utils"; export const CalendarComp: React.FC = props => { const state = useCalendarState(props); diff --git a/src/datepicker/__tests__/DatePicker.test.tsx b/src/datepicker/__tests__/DatePicker.test.tsx index f2048f2ce..f0402a083 100644 --- a/src/datepicker/__tests__/DatePicker.test.tsx +++ b/src/datepicker/__tests__/DatePicker.test.tsx @@ -23,7 +23,7 @@ import { CalendarCellButton, } from "../../calendar"; import { repeat } from "../../utils/test-utils"; -import { addWeeks, format, subWeeks } from "@renderlesskit/react/utils"; +import { addWeeks, format, subWeeks } from "../../utils"; /* // Mocking useId otherwise snapshots will change each time diff --git a/src/utils/date.ts b/src/utils/date.ts index 6680ec361..51c9fe20c 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -108,16 +108,16 @@ export const getSeconds = (date: Date) => dayjs(date).get("seconds"); export const getYear = (date: Date) => dayjs(date).get("years"); export const setDate = (date: Date, value: number) => - dayjs(date).set("date", value); + dayjs(date).set("date", value).toDate(); export const setHours = (date: Date, value: number) => - dayjs(date).set("hour", value); + dayjs(date).set("hour", value).toDate(); export const setMinutes = (date: Date, value: number) => - dayjs(date).set("minute", value); + dayjs(date).set("minute", value).toDate(); export const setSeconds = (date: Date, value: number) => - dayjs(date).set("second", value); + dayjs(date).set("second", value).toDate(); export const setMonth = (date: Date, value: number) => - dayjs(date).set("month", value); + dayjs(date).set("month", value).toDate(); export const setYear = (date: Date, value: number) => - dayjs(date).set("year", value); + dayjs(date).set("year", value).toDate(); From 6674378d1de972136bc1a9862ed81916fd8d8364 Mon Sep 17 00:00:00 2001 From: Anurag Date: Thu, 12 Aug 2021 13:49:31 +0530 Subject: [PATCH 3/8] chore: minor changes --- src/segment/__tests__/utils.test.ts | 6 ++++++ src/utils/date.ts | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/segment/__tests__/utils.test.ts b/src/segment/__tests__/utils.test.ts index bd525f836..14c8d91a3 100644 --- a/src/segment/__tests__/utils.test.ts +++ b/src/segment/__tests__/utils.test.ts @@ -5,36 +5,42 @@ describe("Segment Utils", () => { test("getSegmentLimits", () => { MockDate.set(new Date("2020-02-01T11:30:00.000Z")); + // @ts-ignore expect(getSegmentLimits(new Date(), "month", {})).toEqual({ value: 2, minValue: 1, maxValue: 12, }); + // @ts-ignore expect(getSegmentLimits(new Date(), "year", {})).toEqual({ value: 2020, minValue: 1, maxValue: 9999, }); + // @ts-ignore expect(getSegmentLimits(new Date(), "day", {})).toEqual({ value: 1, minValue: 1, maxValue: 29, }); + // @ts-ignore expect(getSegmentLimits(new Date(), "dayPeriod", {})).toEqual({ value: 12, minValue: 0, maxValue: 12, }); + // @ts-ignore expect(getSegmentLimits(new Date(), "minute", {})).toEqual({ value: 0, minValue: 0, maxValue: 59, }); + // @ts-ignore expect(getSegmentLimits(new Date(), "second", {})).toEqual({ value: 0, minValue: 0, diff --git a/src/utils/date.ts b/src/utils/date.ts index 51c9fe20c..17c43ef1d 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -81,6 +81,7 @@ export const isWeekend = (date: Date) => { // export const format = (date: Date, fmt: string) => { // return dayjs(date).format(fmt); // }; + export { format, closestTo } from "date-fns"; export const startOfMonth = (date: Date) => { @@ -115,9 +116,12 @@ export const setHours = (date: Date, value: number) => export const setMinutes = (date: Date, value: number) => dayjs(date).set("minute", value).toDate(); + export const setSeconds = (date: Date, value: number) => dayjs(date).set("second", value).toDate(); + export const setMonth = (date: Date, value: number) => dayjs(date).set("month", value).toDate(); + export const setYear = (date: Date, value: number) => dayjs(date).set("year", value).toDate(); From 883a1192a528274e9569ef276397f170df75113f Mon Sep 17 00:00:00 2001 From: Anurag Date: Thu, 12 Aug 2021 13:58:20 +0530 Subject: [PATCH 4/8] chore: reorganize functions --- src/utils/date.ts | 62 +++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/utils/date.ts b/src/utils/date.ts index 17c43ef1d..92f04d1ce 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -65,37 +65,6 @@ export const addYears = (date: Date, amount: number) => export const addWeeks = (date: Date, amount: number) => dayjs(date).add(amount, "weeks").toDate(); -export const getDaysInMonth = (date: Date) => dayjs(date).daysInMonth(); - -export const isSameMonth = (date1: Date, date2: Date) => - dayjs(date1).isSame(date2, "month"); - -export const isSameDay = (date1: Date, date2: Date) => - dayjs(date1).isSame(date2, "day"); - -export const isWeekend = (date: Date) => { - const day = dayjs(date).get("day"); - return day === 0 || day === 6; -}; - -// export const format = (date: Date, fmt: string) => { -// return dayjs(date).format(fmt); -// }; - -export { format, closestTo } from "date-fns"; - -export const startOfMonth = (date: Date) => { - return dayjs(date).startOf("month"); -}; - -export const startOfDay = (date: Date) => { - return dayjs(date).startOf("day"); -}; - -export const endOfMonth = (date: Date) => { - return dayjs(date).endOf("month"); -}; - export const getDate = (date: Date) => dayjs(date).get("date"); export const getHours = (date: Date) => dayjs(date).get("hours"); @@ -125,3 +94,34 @@ export const setMonth = (date: Date, value: number) => export const setYear = (date: Date, value: number) => dayjs(date).set("year", value).toDate(); + +export const startOfMonth = (date: Date) => { + return dayjs(date).startOf("month"); +}; + +export const startOfDay = (date: Date) => { + return dayjs(date).startOf("day"); +}; + +export const endOfMonth = (date: Date) => { + return dayjs(date).endOf("month"); +}; + +export const getDaysInMonth = (date: Date) => dayjs(date).daysInMonth(); + +export const isSameMonth = (date1: Date, date2: Date) => + dayjs(date1).isSame(date2, "month"); + +export const isSameDay = (date1: Date, date2: Date) => + dayjs(date1).isSame(date2, "day"); + +export const isWeekend = (date: Date) => { + const day = dayjs(date).get("day"); + return day === 0 || day === 6; +}; + +// export const format = (date: Date, fmt: string) => { +// return dayjs(date).format(fmt); +// }; + +export { format, closestTo } from "date-fns"; From 57654d387e8b302627731320c4e1020a117ec603 Mon Sep 17 00:00:00 2001 From: Anurag Date: Thu, 12 Aug 2021 17:43:08 +0530 Subject: [PATCH 5/8] refactor: migrate format strings to dayjs --- src/calendar/RangeCalendarState.ts | 10 +++++----- src/calendar/__tests__/Calendar.test.tsx | 18 ++++++++--------- src/calendar/stories/CalendarBase.stories.tsx | 10 +++++----- .../stories/CalendarRange.stories.tsx | 20 +++++++++---------- src/datepicker/__tests__/DatePicker.test.tsx | 6 +++--- .../stories/DatePickerBase.stories.tsx | 10 +++++----- .../stories/DatePickerRange.stories.tsx | 20 +++++++++---------- src/utils/date.ts | 15 ++++++++------ 8 files changed, 56 insertions(+), 53 deletions(-) diff --git a/src/calendar/RangeCalendarState.ts b/src/calendar/RangeCalendarState.ts index 7fcb76b4e..498b2ff1a 100644 --- a/src/calendar/RangeCalendarState.ts +++ b/src/calendar/RangeCalendarState.ts @@ -61,15 +61,15 @@ export function useRangeCalendarState( announce( `Selected range, from ${format( highlightedRange.start, - "do MMM yyyy", - )} to ${format(highlightedRange.start, "do MMM yyyy")}`, + "Do MMM YYYY", + )} to ${format(highlightedRange.start, "Do MMM YYYY")}`, ); } else { announce( `Selected range, from ${format( highlightedRange.start, - "do MMM yyyy", - )} to ${format(highlightedRange.end, "do MMM yyyy")}`, + "Do MMM YYYY", + )} to ${format(highlightedRange.end, "Do MMM YYYY")}`, ); } }, [highlightedRange]); @@ -81,7 +81,7 @@ export function useRangeCalendarState( if (!anchorDate) { setAnchorDate(date); - announce(`Starting range from ${format(date, "do MMM yyyy")}`); + announce(`Starting range from ${format(date, "Do MMM YYYY")}`); } else { setValue(makeRange(anchorDate, date)); announceRange(); diff --git a/src/calendar/__tests__/Calendar.test.tsx b/src/calendar/__tests__/Calendar.test.tsx index 704152507..025eb969f 100644 --- a/src/calendar/__tests__/Calendar.test.tsx +++ b/src/calendar/__tests__/Calendar.test.tsx @@ -152,9 +152,9 @@ describe("Calendar", () => { test("should have min/max values", () => { render( , ); const { getByLabelText: label } = screen; @@ -173,9 +173,9 @@ describe("Calendar", () => { test("should be able to go to prev/next month when min/max values are set", () => { render( , ); const { getByLabelText: label } = screen; @@ -199,9 +199,9 @@ describe("Calendar", () => { test("should be able to go to prev/next year when min/max values are set", () => { render( , ); diff --git a/src/calendar/stories/CalendarBase.stories.tsx b/src/calendar/stories/CalendarBase.stories.tsx index 3872440ed..3b5bea4ce 100644 --- a/src/calendar/stories/CalendarBase.stories.tsx +++ b/src/calendar/stories/CalendarBase.stories.tsx @@ -37,10 +37,10 @@ export default { } as Meta; const Base: Story = args => { - args.value &&= format(new Date(args.value), "yyyy-MM-dd"); - args.defaultValue &&= format(new Date(args.defaultValue), "yyyy-MM-dd"); - args.minValue &&= format(new Date(args.minValue), "yyyy-MM-dd"); - args.maxValue &&= format(new Date(args.maxValue), "yyyy-MM-dd"); + args.value &&= format(new Date(args.value), "YYYY-MM-DD"); + args.defaultValue &&= format(new Date(args.defaultValue), "YYYY-MM-DD"); + args.minValue &&= format(new Date(args.minValue), "YYYY-MM-DD"); + args.maxValue &&= format(new Date(args.maxValue), "YYYY-MM-DD"); const [{ value }, updateArgs] = useArgs(); @@ -48,7 +48,7 @@ const Base: Story = args => { - updateArgs({ value: format(new Date(date), "yyyy-MM-dd") }) + updateArgs({ value: format(new Date(date), "YYYY-MM-DD") }) } {...args} /> diff --git a/src/calendar/stories/CalendarRange.stories.tsx b/src/calendar/stories/CalendarRange.stories.tsx index 48ec8ccbd..814c78cc0 100644 --- a/src/calendar/stories/CalendarRange.stories.tsx +++ b/src/calendar/stories/CalendarRange.stories.tsx @@ -51,16 +51,16 @@ export default { const Base: Story = args => { args.value = { - start: args.start && format(new Date(args.start), "yyyy-MM-dd"), - end: args.end && format(new Date(args.end), "yyyy-MM-dd"), + start: args.start && format(new Date(args.start), "YYYY-MM-DD"), + end: args.end && format(new Date(args.end), "YYYY-MM-DD"), }; args.defaultValue = { start: - args.defaultStart && format(new Date(args.defaultStart), "yyyy-MM-dd"), - end: args.defaultEnd && format(new Date(args.defaultEnd), "yyyy-MM-dd"), + args.defaultStart && format(new Date(args.defaultStart), "YYYY-MM-DD"), + end: args.defaultEnd && format(new Date(args.defaultEnd), "YYYY-MM-DD"), }; - args.minValue &&= format(new Date(args.minValue), "yyyy-MM-dd"); - args.maxValue &&= format(new Date(args.maxValue), "yyyy-MM-dd"); + args.minValue &&= format(new Date(args.minValue), "YYYY-MM-DD"); + args.maxValue &&= format(new Date(args.maxValue), "YYYY-MM-DD"); const [argProps, updateArgs] = useArgs(); @@ -69,8 +69,8 @@ const Base: Story = args => { value={{ start: argProps["start"], end: argProps["nd"] }} onChange={date => { updateArgs({ - start: format(new Date(date.start), "yyyy-MM-dd"), - end: format(new Date(date.end), "yyyy-MM-dd"), + start: format(new Date(date.start), "YYYY-MM-DD"), + end: format(new Date(date.end), "YYYY-MM-DD"), }); }} {...args} @@ -121,10 +121,10 @@ ControlledStory.args = { export const ControlledInput = () => { const [start, setStart] = React.useState( - format(subDays(new Date(), 1), "yyyy-MM-dd"), + format(subDays(new Date(), 1), "YYYY-MM-DD"), ); const [end, setEnd] = React.useState( - format(addDays(new Date(), 1), "yyyy-MM-dd"), + format(addDays(new Date(), 1), "YYYY-MM-DD"), ); return ( diff --git a/src/datepicker/__tests__/DatePicker.test.tsx b/src/datepicker/__tests__/DatePicker.test.tsx index f0402a083..3053e78d6 100644 --- a/src/datepicker/__tests__/DatePicker.test.tsx +++ b/src/datepicker/__tests__/DatePicker.test.tsx @@ -227,9 +227,9 @@ describe("DatePicker", () => { it("should be invalid on out of range value", () => { render( , ); diff --git a/src/datepicker/stories/DatePickerBase.stories.tsx b/src/datepicker/stories/DatePickerBase.stories.tsx index cff274241..824343f23 100644 --- a/src/datepicker/stories/DatePickerBase.stories.tsx +++ b/src/datepicker/stories/DatePickerBase.stories.tsx @@ -41,10 +41,10 @@ export default { } as Meta; const Base: Story = args => { - args.value &&= format(new Date(args.value), "yyyy-MM-dd"); - args.defaultValue &&= format(new Date(args.defaultValue), "yyyy-MM-dd"); - args.minValue &&= format(new Date(args.minValue), "yyyy-MM-dd"); - args.maxValue &&= format(new Date(args.maxValue), "yyyy-MM-dd"); + args.value &&= format(new Date(args.value), "YYYY-MM-DD"); + args.defaultValue &&= format(new Date(args.defaultValue), "YYYY-MM-DD"); + args.minValue &&= format(new Date(args.minValue), "YYYY-MM-DD"); + args.maxValue &&= format(new Date(args.maxValue), "YYYY-MM-DD"); const [{ value }, updateArgs] = useArgs(); @@ -52,7 +52,7 @@ const Base: Story = args => { - updateArgs({ value: format(new Date(date), "yyyy-MM-dd") }) + updateArgs({ value: format(new Date(date), "YYYY-MM-DD") }) } {...args} /> diff --git a/src/datepicker/stories/DatePickerRange.stories.tsx b/src/datepicker/stories/DatePickerRange.stories.tsx index 93493268f..9d7724141 100644 --- a/src/datepicker/stories/DatePickerRange.stories.tsx +++ b/src/datepicker/stories/DatePickerRange.stories.tsx @@ -51,16 +51,16 @@ export default { const Base: Story = args => { args.value = { - start: args.start && format(new Date(args.start), "yyyy-MM-dd"), - end: args.end && format(new Date(args.end), "yyyy-MM-dd"), + start: args.start && format(new Date(args.start), "YYYY-MM-DD"), + end: args.end && format(new Date(args.end), "YYYY-MM-DD"), }; args.defaultValue = { start: - args.defaultStart && format(new Date(args.defaultStart), "yyyy-MM-dd"), - end: args.defaultEnd && format(new Date(args.defaultEnd), "yyyy-MM-dd"), + args.defaultStart && format(new Date(args.defaultStart), "YYYY-MM-DD"), + end: args.defaultEnd && format(new Date(args.defaultEnd), "YYYY-MM-DD"), }; - args.minValue &&= format(new Date(args.minValue), "yyyy-MM-dd"); - args.maxValue &&= format(new Date(args.maxValue), "yyyy-MM-dd"); + args.minValue &&= format(new Date(args.minValue), "YYYY-MM-DD"); + args.maxValue &&= format(new Date(args.maxValue), "YYYY-MM-DD"); const [argProps, updateArgs] = useArgs(); @@ -69,8 +69,8 @@ const Base: Story = args => { value={{ start: argProps["start"], end: argProps["nd"] }} onChange={date => { updateArgs({ - start: format(new Date(date.start), "yyyy-MM-dd"), - end: format(new Date(date.end), "yyyy-MM-dd"), + start: format(new Date(date.start), "YYYY-MM-DD"), + end: format(new Date(date.end), "YYYY-MM-DD"), }); }} {...args} @@ -123,10 +123,10 @@ ControlledStory.args = { export const ControlledInput = () => { const [start, setStart] = React.useState( - format(subDays(new Date(), 1), "yyyy-MM-dd"), + format(subDays(new Date(), 1), "YYYY-MM-DD"), ); const [end, setEnd] = React.useState( - format(addDays(new Date(), 1), "yyyy-MM-dd"), + format(addDays(new Date(), 1), "YYYY-MM-DD"), ); return ( diff --git a/src/utils/date.ts b/src/utils/date.ts index 92f04d1ce..827319f2b 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -1,8 +1,11 @@ -import { parse, format } from "date-fns"; +import { parse } from "date-fns"; import dayjs from "dayjs"; +import advancedFormat from "dayjs/plugin/advancedFormat"; import { RangeValue } from "@react-types/shared"; +dayjs.extend(advancedFormat); + export function parseDate(dateValue: string | undefined) { if (dateValue == null) return; @@ -26,7 +29,7 @@ export const parseRangeDate = ( }; export function stringifyDate(date: Date) { - return format(date, "yyyy-MM-dd"); + return format(date, "YYYY-MM-DD"); } export function isInvalidDateRange( @@ -120,8 +123,8 @@ export const isWeekend = (date: Date) => { return day === 0 || day === 6; }; -// export const format = (date: Date, fmt: string) => { -// return dayjs(date).format(fmt); -// }; +export const format = (date: Date, fmt: string) => { + return dayjs(date).format(fmt); +}; -export { format, closestTo } from "date-fns"; +export { closestTo } from "date-fns"; From 5946e6b4059297a735a348bb76e5d9835c644784 Mon Sep 17 00:00:00 2001 From: Anurag Date: Thu, 12 Aug 2021 18:03:07 +0530 Subject: [PATCH 6/8] refactor: migrate parseDate (failing) --- src/utils/date.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/date.ts b/src/utils/date.ts index 827319f2b..8d05b044f 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -9,12 +9,12 @@ dayjs.extend(advancedFormat); export function parseDate(dateValue: string | undefined) { if (dateValue == null) return; - const parsedDate = parse(dateValue, "yyyyyy-MM-dd", new Date()); + const parsedDate = dayjs(dateValue, "YYYY-MM-DD", true); // Check for Invalid Date - if (isNaN(+parsedDate)) return; - parsedDate.setHours(new Date().getHours()); - return parsedDate; + if (!parsedDate.isValid()) return; + parsedDate.set("hour", new Date().getHours()); + return parsedDate.toDate(); } export const parseRangeDate = ( From 70d4a389c5ddeef2ca0c67a0fbf35b6a02f91f92 Mon Sep 17 00:00:00 2001 From: Anurag Date: Thu, 12 Aug 2021 18:04:57 +0530 Subject: [PATCH 7/8] refactor: migrate closestTo --- src/utils/date.ts | 49 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/src/utils/date.ts b/src/utils/date.ts index 8d05b044f..070a5daf0 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -1,4 +1,3 @@ -import { parse } from "date-fns"; import dayjs from "dayjs"; import advancedFormat from "dayjs/plugin/advancedFormat"; @@ -127,4 +126,50 @@ export const format = (date: Date, fmt: string) => { return dayjs(date).format(fmt); }; -export { closestTo } from "date-fns"; +export function closestTo( + dirtyDateToCompare: string, + dirtyDatesArray: string[], +) { + let dateToCompare = dayjs(dirtyDateToCompare); + + if (!dateToCompare.isValid()) { + return new Date(NaN); + } + + let timeToCompare = dateToCompare.toDate().getTime(); + + let datesArray; + // `dirtyDatesArray` is undefined or null + if (dirtyDatesArray == null) { + datesArray = []; + + // `dirtyDatesArray` is Array, Set or Map, or object with custom `forEach` method + } else if (typeof dirtyDatesArray.forEach === "function") { + datesArray = dirtyDatesArray; + + // If `dirtyDatesArray` is Array-like Object, convert to Array. Otherwise, make it empty Array + } else { + datesArray = Array.prototype.slice.call(dirtyDatesArray); + } + + let result: Date | null; + let minDistance: number; + datesArray.forEach(function (dirtyDate: any) { + let currentDate = dayjs(dirtyDate); + + if (!currentDate.isValid()) { + result = new Date(NaN); + minDistance = NaN; + return; + } + + let distance = Math.abs(timeToCompare - currentDate.toDate().getTime()); + if (result == null || distance < minDistance) { + result = currentDate.toDate(); + minDistance = distance; + } + }); + + // @ts-ignore + return result; +} From 078b1cdf9c656860a36165448754ac998dbac88b Mon Sep 17 00:00:00 2001 From: Anurag Date: Fri, 13 Aug 2021 11:55:14 +0530 Subject: [PATCH 8/8] refactor: revert parseDate and fix closestTo types --- src/utils/date.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/utils/date.ts b/src/utils/date.ts index 070a5daf0..0f02d03d2 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -1,4 +1,5 @@ import dayjs from "dayjs"; +import { parse } from "date-fns"; import advancedFormat from "dayjs/plugin/advancedFormat"; import { RangeValue } from "@react-types/shared"; @@ -8,12 +9,12 @@ dayjs.extend(advancedFormat); export function parseDate(dateValue: string | undefined) { if (dateValue == null) return; - const parsedDate = dayjs(dateValue, "YYYY-MM-DD", true); + const parsedDate = parse(dateValue, "yyyyyy-MM-dd", new Date()); // Check for Invalid Date - if (!parsedDate.isValid()) return; - parsedDate.set("hour", new Date().getHours()); - return parsedDate.toDate(); + if (isNaN(+parsedDate)) return; + parsedDate.setHours(new Date().getHours()); + return parsedDate; } export const parseRangeDate = ( @@ -127,9 +128,9 @@ export const format = (date: Date, fmt: string) => { }; export function closestTo( - dirtyDateToCompare: string, - dirtyDatesArray: string[], -) { + dirtyDateToCompare: Date | number, + dirtyDatesArray: (Date | number)[], +): Date { let dateToCompare = dayjs(dirtyDateToCompare); if (!dateToCompare.isValid()) {