@uiw/react-native
Version:
UIW for React Native
287 lines (286 loc) • 9.69 kB
JavaScript
import { useMemo } from 'react';
import dayjs from 'dayjs';
export default function useDatePicker({ mode, labelUnit, format, value, minDate = '1970-01-01 00:00:00', maxDate = '2100-01-01 00:00:00', onChange, }) {
const minDayjs = useMemo(() => dayjs(minDate), [minDate]);
const maxDayjs = useMemo(() => dayjs(maxDate), [maxDate]);
const clipDate = (date) => {
if (mode === 'datetime') {
if (dayjs(date).isBefore(minDayjs)) {
return cloneDate(minDayjs);
}
if (dayjs(date).isAfter(maxDayjs)) {
return cloneDate(maxDayjs);
}
}
else if (mode === 'date' || mode === 'year' || mode === 'month') {
if (dayjs(date).add(1, 'day').isBefore(minDayjs)) {
return cloneDate(minDayjs);
}
if (dayjs(date).isAfter(maxDayjs.add(1, 'day'))) {
return cloneDate(maxDayjs);
}
}
else if (mode === 'time') {
const maxHour = maxDayjs.get('hour');
const maxMinutes = maxDayjs.get('minute');
const minHour = minDayjs.get('hour');
const minMinutes = minDayjs.get('minute');
const hour = dayjs(date).get('hour');
const minutes = dayjs(date).get('minute');
if (hour < minHour || (hour === minHour && minutes < minMinutes)) {
return cloneDate(minDayjs);
}
if (hour > maxHour || (hour === maxHour && minutes > maxMinutes)) {
return cloneDate(maxDayjs);
}
}
return dayjs(date);
};
const getDate = () => {
return clipDate(value);
};
const getMinYear = () => {
return minDayjs.get('year');
};
const getMaxYear = () => {
return maxDayjs.get('year');
};
const getMinMonth = () => {
return minDayjs.get('month');
};
const getMaxMonth = () => {
return maxDayjs.get('month');
};
const getMinDay = () => {
return minDayjs.get('date');
};
const getMaxDay = () => {
return maxDayjs.get('date');
};
const getMinHour = () => {
return minDayjs.get('hour');
};
const getMaxHour = () => {
return maxDayjs.get('hour');
};
const getMinMinute = () => {
return minDayjs.get('minute');
};
const getMaxMinute = () => {
return maxDayjs.get('minute');
};
const cloneDate = (date) => {
return dayjs(date);
};
const getDateData = () => {
const date = getDate();
const selYear = date.get('year');
const selMonth = date.get('month');
const minDateYear = getMinYear();
const maxDateYear = getMaxYear();
const minDateMonth = getMinMonth();
const maxDateMonth = getMaxMonth();
const minDateDay = getMinDay();
const maxDateDay = getMaxDay();
const years = [];
for (let i = minDateYear; i <= maxDateYear; i++) {
years.push({
value: i + '',
label: i + labelUnit.year,
});
}
if (mode === 'year') {
return [years];
}
const months = [];
let minMonth = 0;
let maxMonth = 11;
if (minDateYear === selYear) {
minMonth = minDateMonth;
}
if (maxDateYear === selYear) {
maxMonth = maxDateMonth;
}
for (let i = minMonth; i <= maxMonth; i++) {
months.push({
value: i + '',
label: i + 1 + labelUnit.month,
});
}
if (mode === 'month') {
return [years, months];
}
const days = [];
let minDay = 1;
let maxDay = getDaysInMonth(date.toDate());
if (minDateYear === selYear && minDateMonth === selMonth) {
minDay = minDateDay;
}
if (maxDateYear === selYear && maxDateMonth === selMonth) {
maxDay = maxDateDay;
}
for (let i = minDay; i <= maxDay; i++) {
days.push({
value: i + '',
label: i + labelUnit.day,
});
}
return [years, months, days];
};
const getTimeData = (date) => {
let minHour = 0;
let maxHour = 23;
let minMinute = 0;
let maxMinute = 59;
const minDateMinute = getMinMinute();
const maxDateMinute = getMaxMinute();
const minDateHour = getMinHour();
const maxDateHour = getMaxHour();
const hour = date.get('hour');
if (mode === 'datetime') {
const year = date.get('year');
const month = date.get('month');
const day = date.get('date');
const minDateYear = getMinYear();
const maxDateYear = getMaxYear();
const minDateMonth = getMinMonth();
const maxDateMonth = getMaxMonth();
const minDateDay = getMinDay();
const maxDateDay = getMaxDay();
if (minDateYear === year && minDateMonth === month && minDateDay === day) {
minHour = minDateHour;
if (minDateHour === hour) {
minMinute = minDateMinute;
}
}
if (maxDateYear === year && maxDateMonth === month && maxDateDay === day) {
maxHour = maxDateHour;
if (maxDateHour === hour) {
maxMinute = maxDateMinute;
}
}
}
else {
minHour = minDateHour;
if (minDateHour === hour) {
minMinute = minDateMinute;
}
maxHour = maxDateHour;
if (maxDateHour === hour) {
maxMinute = maxDateMinute;
}
}
const hours = [];
for (let i = minHour; i <= maxHour; i++) {
hours.push({
value: i + '',
label: labelUnit.hour ? i + labelUnit.hour + '' : pad(i),
});
}
const minutes = [];
const selMinute = date.get('minute');
for (let i = minMinute; i <= maxMinute; i += 1) {
minutes.push({
value: i + '',
label: labelUnit.minute ? i + labelUnit.minute + '' : pad(i),
});
if (selMinute > i && selMinute < i + 1) {
minutes.push({
value: selMinute + '',
label: labelUnit.minute ? selMinute + labelUnit.minute + '' : pad(selMinute),
});
}
}
const cols = [hours, minutes].concat([]);
return { cols, selMinute };
};
const getValueCols = () => {
const date = getDate();
let cols = [];
let values = [];
if (mode === 'year') {
return {
cols: getDateData(),
values: [date.get('year') + ''],
};
}
if (mode === 'month') {
return {
cols: getDateData(),
values: [date.get('year') + '', date.get('month') + ''],
};
}
if (mode === 'datetime' || mode === 'date') {
cols = getDateData();
values = [date.get('year') + '', date.get('month') + '', date.get('date') + ''];
}
if (mode === 'datetime' || mode === 'time') {
const time = getTimeData(date);
cols = cols.concat(time.cols);
const hour = date.get('hour');
const dtValue = [hour + '', time.selMinute + ''];
values = values.concat(dtValue);
}
return {
values,
cols,
};
};
const setMonth = (date, month) => {
date.setDate(Math.min(date.getDate(), getDaysInMonth(new Date(date.getFullYear(), month))));
date.setMonth(month);
return dayjs(date);
};
const getNewDate = (value, index) => {
const date = cloneDate(getDate());
let newValue = undefined;
if (mode === 'datetime' || mode === 'date' || mode === 'year' || mode === 'month') {
switch (index) {
case 0:
newValue = date.set('year', value);
break;
case 1:
newValue = setMonth(date.toDate(), value);
break;
case 2:
newValue = date.set('date', value);
break;
case 3:
newValue = date.set('hour', value);
break;
case 4:
newValue = date.set('minute', value);
break;
default:
break;
}
}
else if (mode === 'time') {
switch (index) {
case 0:
newValue = date.set('hour', value);
break;
case 1:
newValue = date.set('minute', value);
break;
default:
break;
}
}
return clipDate(newValue.toDate());
};
const onValueChange = (value, index) => {
const newDate = getNewDate(parseInt(value + '', 10), index);
onChange?.(newDate.toDate(), newDate.format(format));
};
return {
getValueCols: getValueCols,
onValueChange: onValueChange,
};
}
function pad(n) {
return n < 10 ? `0${n}` : n + '';
}
function getDaysInMonth(date) {
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
}