date-fns 的 isSameOrBefore 实现
isSameOrBefore implementation for date-fns
随着 moment 被弃用,我决定从我的整个项目中隐藏 moment 并考虑使用 datefns 作为替代品。在浏览代码文件时,我遇到了一行内容,
moment(date1).isSameOrBefore(date2, year);
我开始寻找与该函数所做的类似的东西,但不幸的是,date-fns 没有任何东西可以执行基于精度的比较(即:年、月或日期比较)?谁能建议一些 date-fns 的解决方法?
使用getYear
先获取两个日期的“年”部分,然后比较两个日期。
类似于:
const date1 = new Date(2021, 6, 20);
const date2 = new Date(2021, 7, 2);
const date3 = new Date(2020, 1, 15);
console.log(dateFns.getYear(date1) <= dateFns.getYear(date2));
console.log(dateFns.getYear(date1) <= dateFns.getYear(date3));
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"></script>
使用 startOfSOMETHING()
您可以使用分钟、小时、天、月 ecc 来比较它们来检查日期是否早于或相同。
const dateBefore = dateFns.startOfHour(new Date(1988, 9, 26, 05, 35));
const dateSame = dateFns.startOfHour(new Date(1988, 9, 26, 11, 55));
const dateAfter = dateFns.startOfHour(new Date(1988, 9, 26, 16, 50));
const limit = dateFns.startOfHour(new Date(1988, 9, 26, 11, 55));
// dateBefore < limit => is before
if (dateFns.isBefore(dateBefore, limit) || dateFns.isEqual(dateBefore, limit)) console.log(dateFns.format(dateBefore), 'is before');
else console.log('is not before');
// dateSame === limit => is same
if (dateFns.isBefore(dateSame, limit) || dateFns.isEqual(dateSame, limit)) console.log(dateFns.format(dateSame), 'is same');
else console.log('is not same');
// dateAfter > limit => is after
if (dateFns.isBefore(dateAfter, limit) || dateFns.isEqual(dateAfter, limit)) console.log('you mustnt see that message ');
else console.log(dateFns.format(dateAfter), 'is after');
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"></script>
在我看来这个库很糟糕,我更喜欢 day.js 与 moment.js 非常相似,或者用 Javascritp 的 new Date()
详细说明日期。
import { isBefore, isEqual } from 'date-fns';
isSameOrBefore(date1: Date, date2: Date, property?: string) {
switch (property) {
case 'full':
return isBefore(date1, date2) || isEqual(date1, date2);
case 'year':
return date1.getFullYear() <= date2.getFullYear();
case 'month':
return (
isBefore(date1.getFullYear(), date2.getFullYear()) ||
(isEqual(date1.getFullYear(), date2.getFullYear()) &&
date1.getMonth() <= date2.getMonth())
);
case 'date':
return (
isBefore(date1.getFullYear(), date2.getFullYear()) ||
(isEqual(date1.getFullYear(), date2.getFullYear()) &&
date1.getMonth() < date2.getMonth()) ||
(isEqual(date1.getFullYear(), date2.getFullYear()) &&
isEqual(date1.getMonth(), date2.getMonth()) &&
date1.getDate() <= date2.getDate())
);
default:
return compareDesc(date1, date2);
}
}
您可以为日期、时刻添加更多实现....
您可以使用 differenceInYears
:
const date1 = new Date(2021, 6, 20);;
const date2 = new Date(2021, 7, 2);
function isSameOrBefore(date1, date2) {
return dateFns.differenceInYears(date1, date2) <= 0;
}
console.log(isSameOrBefore(date1, date2));
console.log(isSameOrBefore(date1, new Date('2022-06-20')));
console.log(isSameOrBefore(date1, new Date('2019-06-20')));
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"></script>
只要您针对相关矩函数进行测试,您应该能够创建一个直接替换。
我们可以寻找相关的startOfXXX过程来比较指定unit
时的日期,如果缺少也会抛出错误:
function isSameOrBefore(date1, date2, unit = '') {
if (unit) {
const procName = `startOf${unit[0].toUpperCase()}${unit.slice(1)}`;
if (!dateFns[procName]) {
throw new Error(`isSameOrBefore: Unsupported unit: ${unit}`);
}
date1 = dateFns[procName](date1);
date2 = dateFns[procName](date2);
}
return dateFns.isBefore(date1, date2) || dateFns.isEqual(date1, date2);
}
// Test against various inputs
const dts = ['2010-10-20 01:00', '2010-10-20 00:00', '2010-10-20 00:59:00', '2010-10-01', '2010-09-01', '2009-09-01'];
let units = ['year', 'month', 'day', 'hour', 'minute'];
let dt1 = '2010-10-20 01:00'
let allTests = [];
for(let dt2 of dts) {
for(let unit of units) {
// Ensure we get the same answer as moment().isSameOrBefore
const testPassed = isSameOrBefore(dt1, dt2, unit) === moment(dt1).isSameOrBefore(dt2, unit)
allTests.push(testPassed);
console.log(`isSameOrBefore(${dt1}, ${dt2}, ${unit}):`, isSameOrBefore(dt1, dt2, unit));
console.log(`isSameOrBefore(${dt1}, ${dt2}, ${unit}): Test passed:`, testPassed ? "TRUE": "FALSE")
}
}
console.log("All tests passed:", allTests.every(res => res) ? "TRUE": "FALSE")
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js" integrity="sha512-F+u8eWHrfY8Xw9BLzZ8rG/0wIvs0y+JyRJrXjp3VjtFPylAEEGwKbua5Ip/oiVhaTDaDs4eU2Xtsxjs/9ag2bQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
也让我post回答一下。它不需要您导入整个 date-fns
import { endOfDay, endOfWeek, endOfMonth, endOfYear } from 'date-fns';
export function isSameOrBefore(date1, date2, unit) {
let method;
switch (unit) {
case 'day':
method = endOfDay;
break;
case 'week':
method = endOfWeek;
break;
case 'month':
method = endOfMonth;
break;
case 'year':
method = endOfYear;
break;
default:
break;
}
const startTimestamp = method ? method(date1): date1;
return dateFns.isBefore(startTimestamp, date2) || dateFns.isEqual(startTimestamp, date2);
}
随着 moment 被弃用,我决定从我的整个项目中隐藏 moment 并考虑使用 datefns 作为替代品。在浏览代码文件时,我遇到了一行内容,
moment(date1).isSameOrBefore(date2, year);
我开始寻找与该函数所做的类似的东西,但不幸的是,date-fns 没有任何东西可以执行基于精度的比较(即:年、月或日期比较)?谁能建议一些 date-fns 的解决方法?
使用getYear
先获取两个日期的“年”部分,然后比较两个日期。
类似于:
const date1 = new Date(2021, 6, 20);
const date2 = new Date(2021, 7, 2);
const date3 = new Date(2020, 1, 15);
console.log(dateFns.getYear(date1) <= dateFns.getYear(date2));
console.log(dateFns.getYear(date1) <= dateFns.getYear(date3));
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"></script>
使用 startOfSOMETHING()
您可以使用分钟、小时、天、月 ecc 来比较它们来检查日期是否早于或相同。
const dateBefore = dateFns.startOfHour(new Date(1988, 9, 26, 05, 35));
const dateSame = dateFns.startOfHour(new Date(1988, 9, 26, 11, 55));
const dateAfter = dateFns.startOfHour(new Date(1988, 9, 26, 16, 50));
const limit = dateFns.startOfHour(new Date(1988, 9, 26, 11, 55));
// dateBefore < limit => is before
if (dateFns.isBefore(dateBefore, limit) || dateFns.isEqual(dateBefore, limit)) console.log(dateFns.format(dateBefore), 'is before');
else console.log('is not before');
// dateSame === limit => is same
if (dateFns.isBefore(dateSame, limit) || dateFns.isEqual(dateSame, limit)) console.log(dateFns.format(dateSame), 'is same');
else console.log('is not same');
// dateAfter > limit => is after
if (dateFns.isBefore(dateAfter, limit) || dateFns.isEqual(dateAfter, limit)) console.log('you mustnt see that message ');
else console.log(dateFns.format(dateAfter), 'is after');
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"></script>
在我看来这个库很糟糕,我更喜欢 day.js 与 moment.js 非常相似,或者用 Javascritp 的 new Date()
详细说明日期。
import { isBefore, isEqual } from 'date-fns';
isSameOrBefore(date1: Date, date2: Date, property?: string) {
switch (property) {
case 'full':
return isBefore(date1, date2) || isEqual(date1, date2);
case 'year':
return date1.getFullYear() <= date2.getFullYear();
case 'month':
return (
isBefore(date1.getFullYear(), date2.getFullYear()) ||
(isEqual(date1.getFullYear(), date2.getFullYear()) &&
date1.getMonth() <= date2.getMonth())
);
case 'date':
return (
isBefore(date1.getFullYear(), date2.getFullYear()) ||
(isEqual(date1.getFullYear(), date2.getFullYear()) &&
date1.getMonth() < date2.getMonth()) ||
(isEqual(date1.getFullYear(), date2.getFullYear()) &&
isEqual(date1.getMonth(), date2.getMonth()) &&
date1.getDate() <= date2.getDate())
);
default:
return compareDesc(date1, date2);
}
}
您可以为日期、时刻添加更多实现....
您可以使用 differenceInYears
:
const date1 = new Date(2021, 6, 20);;
const date2 = new Date(2021, 7, 2);
function isSameOrBefore(date1, date2) {
return dateFns.differenceInYears(date1, date2) <= 0;
}
console.log(isSameOrBefore(date1, date2));
console.log(isSameOrBefore(date1, new Date('2022-06-20')));
console.log(isSameOrBefore(date1, new Date('2019-06-20')));
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"></script>
只要您针对相关矩函数进行测试,您应该能够创建一个直接替换。
我们可以寻找相关的startOfXXX过程来比较指定unit
时的日期,如果缺少也会抛出错误:
function isSameOrBefore(date1, date2, unit = '') {
if (unit) {
const procName = `startOf${unit[0].toUpperCase()}${unit.slice(1)}`;
if (!dateFns[procName]) {
throw new Error(`isSameOrBefore: Unsupported unit: ${unit}`);
}
date1 = dateFns[procName](date1);
date2 = dateFns[procName](date2);
}
return dateFns.isBefore(date1, date2) || dateFns.isEqual(date1, date2);
}
// Test against various inputs
const dts = ['2010-10-20 01:00', '2010-10-20 00:00', '2010-10-20 00:59:00', '2010-10-01', '2010-09-01', '2009-09-01'];
let units = ['year', 'month', 'day', 'hour', 'minute'];
let dt1 = '2010-10-20 01:00'
let allTests = [];
for(let dt2 of dts) {
for(let unit of units) {
// Ensure we get the same answer as moment().isSameOrBefore
const testPassed = isSameOrBefore(dt1, dt2, unit) === moment(dt1).isSameOrBefore(dt2, unit)
allTests.push(testPassed);
console.log(`isSameOrBefore(${dt1}, ${dt2}, ${unit}):`, isSameOrBefore(dt1, dt2, unit));
console.log(`isSameOrBefore(${dt1}, ${dt2}, ${unit}): Test passed:`, testPassed ? "TRUE": "FALSE")
}
}
console.log("All tests passed:", allTests.every(res => res) ? "TRUE": "FALSE")
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js" integrity="sha512-F+u8eWHrfY8Xw9BLzZ8rG/0wIvs0y+JyRJrXjp3VjtFPylAEEGwKbua5Ip/oiVhaTDaDs4eU2Xtsxjs/9ag2bQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
也让我post回答一下。它不需要您导入整个 date-fns
import { endOfDay, endOfWeek, endOfMonth, endOfYear } from 'date-fns';
export function isSameOrBefore(date1, date2, unit) {
let method;
switch (unit) {
case 'day':
method = endOfDay;
break;
case 'week':
method = endOfWeek;
break;
case 'month':
method = endOfMonth;
break;
case 'year':
method = endOfYear;
break;
default:
break;
}
const startTimestamp = method ? method(date1): date1;
return dateFns.isBefore(startTimestamp, date2) || dateFns.isEqual(startTimestamp, date2);
}