最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • date函数setMonth()方法 项目中遇到的坑

    正文概述 掘金(Forbear)   2021-01-12   616

    问题回顾

    点击月份,可以切换月份,查询对应订单,

    12月31日,近6个月的月份变成如下所示

    date函数setMonth()方法 项目中遇到的坑

    排查问题

    月份计算通过取当前时间,调用addMonths方法获得,addMonths通过计算months,调用setMonth方法实现,在addMonths中打印setMonth的值。

    index.vue片段:

    monthOption: [
            {
              name: new Date().getMonth() + 1 + '月',
              color: '#1989fa',
              timeStr: new Date().format('yyyy-MM')
            },
            {
              name: new Date().addMonths(-1).getMonth() + 1 + '月',
              timeStr: new Date().addMonths(-1).format('yyyy-MM')
            },
            {
              name: new Date().addMonths(-2).getMonth() + 1 + '月',
              timeStr: new Date().addMonths(-2).format('yyyy-MM')
            },
            {
              name: new Date().addMonths(-3).getMonth() + 1 + '月',
              timeStr: new Date().addMonths(-3).format('yyyy-MM')
            },
            {
              name: new Date().addMonths(-4).getMonth() + 1 + '月',
              timeStr: new Date().addMonths(-4).format('yyyy-MM')
            },
            {
              name: new Date().addMonths(-5).getMonth() + 1 + '月',
              timeStr: new Date().addMonths(-5).format('yyyy-MM')
            }
          ]
    

    prototype.js片段:

    Object.defineProperty(Date.prototype, 'addMonths', {
      value: function(months) {
        if (months === undefined || months === '') {
          months = 1
        }
        console.log(this.getMonth(),months)
        this.setMonth(this.getMonth() + months)
        return this
      }
    })
    

    打印结果

    new Date(new Date('2020-12-31').addMonths(-1)).format('yyyy-MM-dd') //  11 -1 "2020-12-01"
    new Date(new Date('2020-12-31').addMonths(-2)).format('yyyy-MM-dd') //  11 -2 "2020-10-31"
    new Date(new Date('2020-12-31').addMonths(-3)).format('yyyy-MM-dd') //  11 -3 "2020-10-01"
    new Date(new Date('2020-12-31').addMonths(-4)).format('yyyy-MM-dd') // 11 -4 "2020-08-31"
    new Date(new Date('2020-12-31').addMonths(-5)).format('yyyy-MM-dd') // 11 -5 "2020-07-31"
    new Date(new Date('2020-12-31').addMonths(-6)).format('yyyy-MM-dd') // 11 -6 "2020-07-01"
    new Date(new Date('2020-12-31').addMonths(-7)).format('yyyy-MM-dd') // 11 -7 "2020-05-31"
    new Date(new Date('2020-12-31').addMonths(-8)).format('yyyy-MM-dd') // 11 -8 "2020-05-01"
    new Date(new Date('2020-12-31').addMonths(-9)).format('yyyy-MM-dd') // 11 -9 "2020-03-31"
    new Date(new Date('2020-12-31').addMonths(-10)).format('yyyy-MM-dd') // 11 -10 "2020-03-02"
    new Date(new Date('2020-12-31').addMonths(-11)).format('yyyy-MM-dd') // 11 -11 "2020-01-31"
    new Date(new Date('2020-12-31').addMonths(-12)).format('yyyy-MM-dd') // 11 -12 "2019-12-31"
    new Date(new Date('2020-12-31').addMonths(-10)).format('yyyy-MM-dd') // 11 -10 "2020-03-02"
    

    通过上图的打印结果,可以发现,this.getMonths()和传入的计算months输出无误,那么问题发生在setMonth的时候。上网查阅mdn资料,发现如下描述:

    点击快速跳转 Date.prototype.setMonth()方法

    If a parameter you specify is outside of the expected range, setMonth() attempts to update the date information in the Date object accordingly. For example, if you use 15 for monthValue, the year will be incremented by 1, and 3 will be used for month.

    The current day of month will have an impact on the behavior of this method. Conceptually it will add the number of days given by the current day of the month to the 1st day of the new month specified as the parameter, to return the new date. For example, if the current value is 31st August 2016, calling setMonth with a value of 1 will return 2nd March 2016. This is because in 2016 February had 29 days.

    如果指定的参数超出预期范围,setMonth()会尝试相应地更新date对象中的日期信息。例如,如果monthValue使用15,year将增加1,month将使用3。

    每月的当前日期将对该方法的行为产生影响。从概念上讲,它将在指定为参数的新月份的第一天添加当前日期所给出的天数,以返回新的日期。例如,如果当前值是2016年8月31日,用值1调用setMonth将返回2016年3月2日。这是因为2016年2月有29天。

    推理到我们项目中。在12月31日当天。调用addMonths(-1),相当于调用setMonth(10,31)方法。由于11月只有30天,11月添加31天,天数溢出后。结果就会推后一天,到12月1日。

    项目上线方案:

    该方案,未使用setMonth()方法,通过直接计算年月日,来返回对应的日期字符。业务场景不需要具体日期,只需要精确到月份。

    function addMonth(date, months) {
      var y = date.getFullYear()
      var m = date.getMonth()
      var d = date.getDate()
    
      y += Math.floor((m + months) / 12) //计算年
      m = Math.floor((m + months) % 12) + 1 //计算月
      if (m <= 0) {
        m += 12
      }
      var d_max = new Date(y , m  ,'0').getDate() //获取计算后的月的最大天数
      if (d > d_max) {
        d = d_max
      }
      return y + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d)
    }
    addMonth(new Date('2020-12-31'),2)
    

    后期,查阅优秀插件setMonth()源码,找到针对setMonth方法的上述特性,moment里面的解决方案:

    get(mom, 'Month') + months * isAdding)
    function mod(n, x) {
         return ((n % x) + x) % x;
    }
    function daysInMonth(year, month) {
        if (isNaN(year) || isNaN(month)) {return NaN;}
        var modMonth = mod(month, 12);year += (month - modMonth) / 12;
            return modMonth === 1
            ? isLeapYear(year)
            ? 29
            : 28
            : 31 - ((modMonth % 7) % 2);
    }
    dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
    mom._d['setMonth'](value, dayOfMonth);
    

    建议大家在后期的开发中,避免自己定义日期函数的方法。尽量使用一些优秀的插件。比如moment,dayjs等。


    起源地下载网 » date函数setMonth()方法 项目中遇到的坑

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元