让人理解有偏差的【最近一个月】和setMonth中的一个神坑

统一前后端最近一月数据获取
探讨了前端与后端在获取最近一个月数据时的差异及解决方案,分析了不同方法的优缺点,并最终采用moment.js实现了与后端一致的时间范围获取。

昨天在弄一个项目,我和同事分别负责不同的模块,但是我们有一个相似的功能,就是数据默认取最近一个月的数据。

虽然重复造轮子容易有坑,但是有时时间比较急的时候,这个也是比较难以避免的。

公共方法,此处可不细看,用于处理时间显示效果:

function formatDate (date, format) {
        if (!date) return;
        if (!format) format = "yyyy-MM-dd";
        switch (typeof date) {
            case "string":
                date = new Date(date.replace(/-/, "/"));
                break;
            case "number":
                date = new Date(date);
                break;
        }
        if (!date instanceof Date) return;
        var dict = {
            "yyyy": date.getFullYear(),
            "M": date.getMonth() + 1,
            "d": date.getDate(),
            "H": date.getHours(),
            "m": date.getMinutes(),
            "s": date.getSeconds(),
            "MM": ("" + (date.getMonth() + 101)).substr(1),
            "dd": ("" + (date.getDate() + 100)).substr(1),
            "HH": ("" + (date.getHours() + 100)).substr(1),
            "mm": ("" + (date.getMinutes() + 100)).substr(1),
            "ss": ("" + (date.getSeconds() + 100)).substr(1)
        };
        return format.replace(/(yyyy|MM?|dd?|HH?|ss?|mm?)/g, function () {
            return dict[arguments[0]];
        });
}

以下是我取的最近一个月数据的实现方法,主要是应用了setMonth和getMonth来实现:

let date = "2018-11-16";
let startDate = new Date(date);
startDate = startDate.setMonth(startDate.getMonth() - 1); 
var endDate = Date.parse(new Date(date));
var query = {
    firOnSellTimeBegin:Date.parse(formatDate(parseInt(startDate)) + ' 0:00:00'),
    firOnSellTimeEnd: Date.parse(formatDate(parseInt(endDate)) + ' 23:59:59')
}

 

而我的同事,则默认取了最近30天当作最近一个月,代码如下:

let d = new Data('2018-11-16');
let endDate = d.getTime();
let startDate = endDate - (30 * 24 * 60 * 60 * 1000);
this.query = Object.assign(this.query, {
    firOnSellTimeBegin: Date.parse(ctrlFunc.formatDate(parseInt(startDate)) + ' 0:00:00'),
    firOnSellTimeEnd: Date.parse(ctrlFunc.formatDate(parseInt(endDate)) + ' 23:59:59')
});

 

 

分析:

取最近30天肯定是有问题的,因为最近30天是最近一个月,那最近三个月呢?是最近90天?

当然不是这样理解,所以同事的代码被ko掉了,我的代码就对了?那最近一个月究竟要怎么取? 

我们前端组得出一个结论,不管怎么取,前后端至少要统一。

然后我们又去找后端看看他们的最近一个月是怎么取的,

假设2018-11-16,后端取最近一个月,结果起始为2018-11-16

假设2018-10-31,后端取最近一个月,结果起始为2018-09-30

假设2018-03-31,后端取最近一个月,结果起始为2018-02-28

得出结论,后端最近一个月的结果为:月份减1,日期不变,若上个月没有该天,则取该月最后一天

 

神坑:

重新检查我的代码,然后发现一个神坑,看如下图便可一下发现问题:

 

 

通过getMonth()setMonth()方法,2018年3月31号的最近一个月既然是2018年3月3号?

原来该方法取最近一个月效果是:3月有31天,然后2月只有28天,则31减28等于3,然后日期自动往后推了3天,即结果为3月3日,这可和后端的结果相差可远呢。

 

解决办法:

由于我们当前开发的项目已引入monent.js, 估方法如下:

let moment = require('moment');

let date = ctrlFunc.formatDate(new Date(), 'yyyy-MM-dd');
let d = new Date(date);
let endDate = d.getTime();
let query =  {
   firOnSellTimeBegin: Date.parse(moment(date).subtract(1, 'month').format('YYYY-MM-DD HH:mm:ss')),
   firOnSellTimeEnd: Date.parse(ctrlFunc.formatDate(parseInt(endDate)) + ' 23:59:59'),
};

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值