【问题标题】:Calculate if last X day of month then increment month计算一个月的最后 X 天,然后增加月份
【发布时间】:2019-08-03 08:26:03
【问题描述】:

我正在尝试解决 Vue JS 申请表的支付频率<select> 的问题。为了稍微解释一下我所拥有的,我将在此处添加一些上下文。

有一个申请表,带有一个<select> 框,其中包含一些选项供用户选择下一次付款的时间,例如:每月最后一个工作日、每周、每两周、每月最后一个星期一,每个月的最后一个星期二等,我将在下面列出可用的选项。

用户选择适当的<option> 并自动计算他们的下一个和下一个付款日期,例如:下一个付款:30/08/2019,下一个付款:27/09/2019。如果愿意,用户可以选择编辑这些字段。

下一个付款日期有 3 个输入字段,下一个付款日期有 3 个输入字段,(DD/MM/YYYY) 字段。

我遇到的问题与每个月的最后周的支付频率选项有关,例如:每月的最后一个星期一,每月的最后一个星期二,一直到到星期五。问题是,例如,如果我在本月的最后一个星期四,假设日期是 29/08/2019,然后我选择选项本月的最后一个星期一,而不是自动将 1 个月添加到月份字段,它停留在当前月份,这是不正确的,因为您不能有过去的下一个付款日期。

我正在使用 Moment JS,版本 2.24.0,并使用 Vue JS 版本 2.6.10,还有包 vee-validate 用于已设置的验证。

我有一些方法可以确定用户的下一个和下一个支付日期,下面列出的payFrequencyChange 方法计算用户可以从中选择的每个可用支付频率选项。我试过检查代码,它似乎应该根据日期正确计算 month 字段,但不是。

这是有问题的代码:


    new Vue({
      el: '#application-form',
      data: {
        frequency: [{ value: 0, name: 'Last working day of month' }, { value: 1, name: 'Weekly' }, { value: 2, name: 'Four weekly' }, { value: 10, name: 'Specific Date' }, { value: 3, name: 'Bi-Weekly' }, { value: 9, name: 'Last Friday of month' }, { value: 5, name: 'Last Monday of month' }, { value: 6, name: 'Last Tuesday of month' }, { value: 7, name: 'Last Wednesday of month' }, { value: 8, name: 'Last Thursday of month' }],
        NextPaydateError: false,
        FollowingPaydateError: false,
        formData: {
          EmpPayFrequency: '',
          NextPaydate: '',
          FollowingPaydate: '',
          NextPaydateDay: '',
          NextPaydateMonth: '',
          NextPaydateYear: '',
          FollowingPaydateDay: '',
          FollowingPaydateMonth: '',
          FollowingPaydateYear: ''
        }
      },
      methods: {

        /**
         * Switch fields
         */
        switchToField(fieldSwitchName, fieldValue, fieldLength) {
          if (String(fieldValue).length >= fieldLength) {
            this.$refs[fieldSwitchName].focus();
          }
        },

        /**
         * Leading Zero
         * @param {int} input
         * @param {bool} years
         */
        leadingZeros: function leadingZeros(input, years = false) {
          if (!years) {
            if (String(input).length === 1) return '0' + input
          } else {
            if (String(input).length === 2) {
              if (parseInt(input) > 50 && parseInt(input) < 100) {
                return '19' + input
              }
            }
          }
          return input
        },

        /**
         * Next Pay Date Change
         */
        nextPayDateChange: function nextPayDateChange() {
          string = this.formData.NextPaydateYear + '-' + this.formData.NextPaydateMonth + '-' + this.formData.NextPaydateDay
          date = moment(string).format('DD/MM/YYYY')
          if (this.formData.NextPaydateYear === '') return
          this.NextPaydateError = (date === 'Invalid date') ? true : false
          this.formData.NextPaydate = date
        },

        /**
         * Following Pay Date Change
         */
        followingPayDateChange: function followingPayDateChange() {
          nextDate = this.formData.NextPaydateYear + '-' + this.formData.NextPaydateMonth + '-' + this.formData.NextPaydateDay
          followingDate = this.formData.FollowingPaydateYear + '-' + this.formData.FollowingPaydateMonth + '-' + this.formData.FollowingPaydateDay
          if (!moment(followingDate).isAfter(moment(nextDate))) {
            this.FollowingPaydateError = true
            return
          }
          date = moment(followingDate).format('DD/MM/YYYY')
          if (this.formData.FollowingPaydateYear === '') return
          this.FollowingPaydateError = (date === 'Invalid date') ? true : false
          this.formData.FollowingPaydate = date
        },

        /**
         * Find Last Working Day
         * @param {bool} nextMonth
         */
        lastBusinessDay: function lastBusinessDay(nextMonth) {
          dateOffset = {
            'Saturday': 1,
            'Sunday': 2
          }
          currentDate = new Date()
          date = new Date(currentDate.getFullYear(), currentDate.getMonth() + (nextMonth ? 2 : 1), 0)
          lastDay = date.toLocaleString('en-GB', {
            day: 'numeric'
          })
          lastWeekday = date.toLocaleString('en-GB', {
            weekday: 'long',
          })
          return dateOffset[lastWeekday] ? lastDay - dateOffset[lastWeekday] : lastDay
        },

        /**
         * Find Last Weekday
         * @param {object} monthMoment
         * @param {int} dayInt
         */
        lastWeekdayOfMonth: function weekly(monthMoment, dayInt) {
          var lastDay = monthMoment.endOf('month').startOf('day')
          for (let i = 0; i <= 10; i++) {
            if (lastDay.day() === dayInt) {
              return lastDay
            } else {
              lastDay.subtract(1, 'days')
            }
          }
        },

        /**
         * Weekly Workouts
         */
        weekly: function weekly(year, month, date, day) {
            date = new Date()
            offset = 4
            result = null
            if ('undefined' === typeof day || null === day) {
                day = 5
            }
            if ('undefined' === typeof year || null === year) {
                year = date.getFullYear()
            }
            if ('undefined' === typeof month || null === month) {
                month = date.getMonth()
            }
            do {
                result = new Date(year, month, date.getDate() + offset)
                offset++
            } while (result.getDay() !== day)
            return result
        },

        /**
         * Pay Frequency Change
         * @param {int} value
         */
        payFrequencyChange: function payFrequencyChange(value) {
          var elems = document.querySelectorAll('.dobbox.is-invalid')
          if (typeof elems === 'object') {
            elems.forEach.call(elems, function(el) {
              el.classList.remove('is-invalid')
            });
          }
          currentDate = new Date()
          switch (parseInt(value)) {
            case 0: // last working day
              next = {
                day: this.lastBusinessDay(false),
                month: currentDate.getMonth() + 1,
                year: currentDate.getFullYear()
              }
              following = {
                day: this.lastBusinessDay(true),
                month: ((currentDate.getMonth() + 2) === 13) ? 1 : currentDate.getMonth() + 2,
                year: ((currentDate.getMonth() + 2) === 13) ? currentDate.getFullYear() + 1 : currentDate.getFullYear()
              }
              break
            case 1: // weekly
              next = this.weekly(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), 5)
              follow = new Date(this.weekly(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), 5))
              following = follow.setDate(follow.getDate() + 7)
              next = {
                day: moment(next).format('DD'),
                month: moment(next).format('MM'),
                year: moment(next).format('YYYY')
              }
              following = {
                day: moment(following).format('DD'),
                month: moment(following).format('MM'),
                year: moment(following).format('YYYY')
              }
              break
            case 2: // four weekly
              next = this.weekly(currentDate.getFullYear(),currentDate.getMonth(), currentDate.getDate() + 4)
              d = new Date(this.weekly(currentDate.getFullYear(),currentDate.getMonth(), currentDate.getDate() + 4))
              d.setDate(d.getDate() + 28)
              following = d
              next = {
                day: moment(next).format('DD'),
                month: moment(next).format('MM'),
                year: moment(next).format('YYYY')
              }
              following = {
                day: moment(following).format('DD'),
                month: moment(following).format('MM'),
                year: moment(following).format('YYYY')
              }
              break
            case 10: // specific date
              next = { day: '', month: '', year: '' }
              following = { day: '', month: '', year: '' }
              break
            case 3: // bi-weekly
              next = { day: '', month: '', year: '' }
              following = { day: '', month: '', year: '' }
              break
            case 9: // last friday
              next = this.lastWeekdayOfMonth(moment(), 5)
              following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 5)
              next = {
                day: moment(next).format('DD'),
                month: moment(next).format('MM'),
                year: moment(next).format('YYYY')
              }
              following = {
                day: moment(following).format('DD'),
                month: moment(following).format('MM'),
                year: moment(following).format('YYYY')
              }
              break
            case 8: // last thursday
              next = this.lastWeekdayOfMonth(moment(), 4)
              following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 4)
              next = {
                day: moment(next).format('DD'),
                month: moment(next).format('MM'),
                year: moment(next).format('YYYY')
              }
              following = {
                day: moment(following).format('DD'),
                month: moment(following).format('MM'),
                year: moment(following).format('YYYY')
              }
              break
            case 7: // last wednesday
              next = this.lastWeekdayOfMonth(moment(), 3)
              following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 3)
              next = {
                day: moment(next).format('DD'),
                month: moment(next).format('MM'),
                year: moment(next).format('YYYY')
              }
              following = {
                day: moment(following).format('DD'),
                month: moment(following).format('MM'),
                year: moment(following).format('YYYY')
              }
              break
            case 6: // last tuesday
              next = this.lastWeekdayOfMonth(moment(), 2)
              following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 2)
              next = {
                day: moment(next).format('DD'),
                month: moment(next).format('MM'),
                year: moment(next).format('YYYY')
              }
              following = {
                day: moment(following).format('DD'),
                month: moment(following).format('MM'),
                year: moment(following).format('YYYY')
              }
              break
            case 5: // last monday
              next = this.lastWeekdayOfMonth(moment(), 1)
              following = this.lastWeekdayOfMonth(moment().add(1, 'months'), 1)
              next = {
                day: moment(next).format('DD'),
                month: moment(next).format('MM'),
                year: moment(next).format('YYYY')
              }
              following = {
                day: moment(following).format('DD'),
                month: moment(following).format('MM'),
                year: moment(following).format('YYYY')
              }
              break
          }
          // Populate new dates
          this.formData.NextPaydateDay = this.leadingZeros(next.day)
          this.formData.NextPaydateYear = next.year
          this.formData.NextPaydateMonth = this.leadingZeros(next.month)
          this.formData.FollowingPaydateDay = this.leadingZeros(following.day)
          this.formData.FollowingPaydateYear = following.year
          this.formData.FollowingPaydateMonth = this.leadingZeros(following.month)
          setTimeout(function () { // Prevent validation errors
            this.NextPaydateError = this.FollowingPaydateError = false
          }.bind(this), 10)
        }

      },
      watch: {
        'formData.NextPaydateYear': function formDataNextPaydateYear() {
          this.nextPayDateChange()
        },
        'formData.FollowingPaydateYear': function formDataFollowingPaydateYear() {
          this.followingPayDateChange()
        }
      }
    })

因此,有了上述内容,一切都会很好,因为它是月初,它应该增量下个月,然后递增一个月的字段,但在上周五选择时,它应该留在当月,除非它在月底前3天,那么它也应该增加。

我知道这需要接受很多,因此另外准备了一支代码笔:

https://codepen.io/sts-ryan-holton/pen/rXGzox

这里将不胜感激,这不是我写的东西,所以不能完全 100% 确定如何修复/添加这一关键功能。

【问题讨论】:

    标签: javascript datetime vue.js vuejs2 momentjs


    【解决方案1】:

    您可以通过更改 lastWeekdayOfMonth 函数中的一些内容来获得所需的功能,如下所示

    lastWeekdayOfMonth: function weekly(monthMoment, dayInt) {
        var lastDay = moment(monthMoment).endOf('month').startOf('day')
        var result = this.__lastWeekdayOfMonth(lastDay, dayInt)
        if( result.isBefore(monthMoment) ) {
            lastDay = moment(lastDay).add(1, 'month')
            result = this.__lastWeekdayOfMonth(lastDay, dayInt)
        }
        return result
    },
    __lastWeekdayOfMonth: function __weekly(lastDay, dayInt) {
        for (let i = 0; i <= 10; i++) {
            if (lastDay.day() === dayInt) {
                return lastDay
            } else {
                lastDay.subtract(1, 'days')
            }
        }
    },
    

    在这里,我对代码进行了一些模块化,并添加了另一个可以完成特定工作的函数。

    我只是在检查结果是否在给定日期之前去检查下个月。

    【讨论】:

      猜你喜欢
      • 2010-09-18
      • 2012-03-12
      • 1970-01-01
      • 2016-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      • 1970-01-01
      相关资源
      最近更新 更多