react-native-paper-dates
Version:
Performant Date Picker for React Native Paper
222 lines (213 loc) • 6.61 kB
JavaScript
;
import { useCallback, useMemo } from 'react';
import { useLatest } from '../shared/utils';
export function showWeekDay(dayIndex, disableWeekDays) {
return !(disableWeekDays && disableWeekDays.some(di => di === dayIndex));
}
export function dateToUnix(d) {
return Math.trunc(d.getTime() / 1000);
}
export function addMonths(date, count) {
let n = date.getDate();
let n2 = new Date(date.getTime());
n2.setDate(1);
n2.setMonth(n2.getMonth() + count);
n2.setDate(Math.min(n, getDaysInMonth({
year: n2.getFullYear(),
month: n2.getMonth()
})));
return n2;
}
// https://stackoverflow.com/a/1185068/2508481
// pass in any date as parameter anyDateInMonth based on dayjs
export function getDaysInMonth({
year,
month
}) {
return [31, isLeapYear({
year
}) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
}
export function getFirstDayOfMonth({
year,
month,
startWeekOnMonday
}) {
let dayOfWeek = new Date(year, month, 1).getDay();
if (startWeekOnMonday) {
// Map Sunday (0) to 6, Monday (1) to 0, etc.
dayOfWeek = (dayOfWeek + 6) % 7;
}
return dayOfWeek;
}
export function useRangeChecker(validRange) {
const validStart = validRange?.startDate;
const validEnd = validRange?.endDate;
const startUnix = validStart instanceof Date ? dateToUnix(getStartOfDay(validStart)) : undefined;
const endUnix = validEnd instanceof Date ? dateToUnix(getEndOfDay(validEnd)) : undefined;
const validDisabledDatesRef = useLatest(validRange?.disabledDates);
const isWithinValidRange = useCallback(day => {
return isDateWithinOptionalRange(day, {
startUnix: startUnix,
endUnix: endUnix
});
}, [startUnix, endUnix]);
const isDisabled = useCallback(day => {
return validDisabledDatesRef.current ? validDisabledDatesRef.current.some(disabledDate => areDatesOnSameDay(disabledDate, day)) : false;
}, [validDisabledDatesRef]);
return {
isDisabled,
isWithinValidRange,
validStart,
validEnd
};
}
export function areDatesOnSameDay(a, b) {
if (!b) {
return false;
}
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
}
export function isDateBetween(date, {
startDate,
endDate
}) {
if (!startDate || !endDate) {
return false;
}
return date <= endDate && date >= startDate;
}
/**
* Check if a date is within an optional range.
*
* If the range doesn't exist, it defaults to `true`.
*/
export function isDateWithinOptionalRange(date, {
startUnix,
endUnix
}) {
const dateUnix = dateToUnix(date);
// if startUnix is provided and date is before start
if (startUnix && dateUnix < startUnix) {
return false;
}
// if endUnix is provided and date is after end
if (endUnix && dateUnix > endUnix) {
return false;
}
return true;
}
export function isLeapYear({
year
}) {
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}
export const daySize = 46;
export const estimatedMonthHeight = 360;
export const defaultStartYear = 1800;
export const defaultEndYear = 2200;
// Dynamic calculation functions to replace fixed constants
export function getStartAtIndex(startYear, _endYear) {
const start = startYear || 1800;
const today = new Date();
const currentYear = today.getFullYear();
// Calculate months from start year to current year
const monthsFromStart = (currentYear - start) * 12 + today.getMonth();
// Ensure we have enough buffer for the range
return Math.max(monthsFromStart, 0);
}
export function getTotalMonths(startYear, endYear) {
const start = startYear || 1800;
const end = endYear || 2200;
return (end - start + 1) * 12;
}
export function getBeginOffset(startYear, endYear) {
return estimatedMonthHeight * getStartAtIndex(startYear, endYear);
}
// Keep the old constants for backward compatibility but make them dynamic
export const startAtIndex = 2800;
export const totalMonths = startAtIndex * 2;
export const beginOffset = estimatedMonthHeight * startAtIndex;
// Create a dynamic grid counts array
export function createGridCounts(count) {
return new Array(count);
}
export const gridCounts = new Array(totalMonths);
export function getGridCount(index, startWeekOnMonday, startYear, endYear) {
const dynamicGridCounts = createGridCounts(getTotalMonths(startYear, endYear));
const cHeight = dynamicGridCounts[index];
if (cHeight) {
return cHeight;
}
const monthDate = addMonths(new Date(), getRealIndex(index, startYear, endYear));
const h = getGridCountForDate(monthDate, startWeekOnMonday);
dynamicGridCounts[index] = h;
return h;
}
export function getGridCountForDate(date, startWeekOnMonday) {
const year = date.getFullYear();
const month = date.getMonth();
const daysInMonth = getDaysInMonth({
year,
month
});
const dayOfWeek = getFirstDayOfMonth({
year,
month,
startWeekOnMonday
});
return Math.ceil((daysInMonth + dayOfWeek) / 7);
}
export function getRealIndex(index, startYear, endYear) {
return index - getStartAtIndex(startYear, endYear);
}
export function getInitialIndex(date, startYear, endYear) {
const dynamicStartAtIndex = getStartAtIndex(startYear, endYear);
if (!date) {
return dynamicStartAtIndex;
}
const today = new Date();
const months = differenceInMonths(today, date);
return dynamicStartAtIndex + months;
}
export function useInputFormatter({
locale
}) {
return useMemo(() => {
return new Intl.DateTimeFormat(locale, {
month: '2-digit',
day: '2-digit',
year: 'numeric'
});
}, [locale]);
}
export function getStartOfDay(d) {
const startOfDay = new Date(d);
startOfDay.setUTCHours(0, 0, 0, 0);
return startOfDay;
}
export function getEndOfDay(d) {
const endOfDay = new Date(d);
endOfDay.setUTCHours(23, 59, 59, 999);
return endOfDay;
}
export function useInputFormat({
formatter,
locale
}) {
return useMemo(() => {
// TODO: something cleaner and more universal?
const inputDate = formatter.format(new Date(2020, 10 - 1, 1));
if (inputDate.includes('٢٠٢٠')) {
return inputDate.replace('٢٠٢٠', 'YYYY').replace('١٠', 'MM').replace('٠١', 'DD');
}
return inputDate.replace('2020', locale === 'pt' ? 'AAAA' : 'YYYY').replace('10', 'MM').replace('01', 'DD');
}, [formatter, locale]);
}
export function differenceInMonths(firstDate, secondDate) {
let diffMonths = (secondDate.getFullYear() - firstDate.getFullYear()) * 12;
diffMonths -= firstDate.getMonth();
diffMonths += secondDate.getMonth();
return diffMonths;
}
//# sourceMappingURL=dateUtils.js.map