简体   繁体   English

使用Moment.js获取指定日期之后的特定工作日的日期

[英]Get date of specific weekday after a specified date with Moment.js

I am trying to get the date for the next instance of a weekday after a given date. 我正在尝试获取给定日期后一个工作日的下一个实例的日期。 The weekday may be any day from Monday through Sunday. 工作日可能是星期一至星期日的任何一天。 I am using the Moment.js library but there doesn't seem to be a simple way to achieve what I am after. 我正在使用Moment.js库,但是似乎没有一种简单的方法可以实现我所追求的目标。

This is what I have so far but it's not returning the date I want: 这是到目前为止,我没有得到想要的日期:

// competition.startDate = 2016-02-10 (Wednesday)
var startDate = moment(competition.startDate);

...

for (m = 0; m < matchesPerRound; m++) {
    var date;

    ...

    // matchTime[m].day = 3 (Wednesday)
    date = startDate.startOf('week').add(7, 'days').subtract(matchTime[m].day, 'days');

    console.log(date.format('YYYY-MM-DD'));
    // Actual Output = 2016-02-11
    // Expected Output = 2016-02-10
    ...

}

With the example above, I need it returning 2016-02-15 as this is the next Monday after 2016-02-10 . 在上面的示例中,我需要它返回2016-02-15因为这是2016-02-10之后的下一个星期一。 This is no problem, and I can get that date. 没问题,我可以得到那个日期。 My problem is that I need something more dynamic, as matchTime[m].day could be any weekday number. 我的问题是我需要更动态的东西,因为matchTime[m].day可以是任何工作日数字。 For example, if matchTime[m].day = 3 // Wednesday , it should just return the same startDate 2016-02-10 as this is a Wednesday. 例如,如果matchTime[m].day = 3 // Wednesday ,它应该只返回相同的startDate 2016-02-10因为这是星期三。

I'm trying to avoid conditional statements if possible, but I am wondering if Moment.js has the functionality out of the box to produce these results. 我试图尽可能避免使用条件语句,但是我想知道Moment.js是否具有开箱即用的功能来产生这些结果。

UPDATE UPDATE

I've come up with a solution, and it's working with my requirements, but I feel it's very messy. 我想出了一个解决方案,它可以满足我的要求,但是我感到这很麻烦。 Does someone else have a cleaner, more concise solution? 别人有更清洁,更简洁的解决方案吗?

var date;
var startDate = moment(competition.startDate);
var proposedDate = moment(startDate).startOf('isoweek').add(matchTimes[0].day - 1, 'd');
if ( startDate.isAfter(proposedDate) ) {
    date = startDate.startOf('isoweek').add(7 + Number(matchTimes[0].day) - 1, 'd');
} else {
    date = startDate.startOf('isoweek').add(matchTimes[0].day - 1, 'd');
}

This is a pure JS version: 这是一个纯JS版本:

Logic 逻辑

  1. Find current day. 查找当前日期。
  2. Find days to add to get to start of next week. 查找要添加的天数,以开始下周的工作。
  3. Get day number for the day to find date. 获取当天的日期编号以查找日期。
  4. Compute date with this date. 用此日期计算日期。

JSFiddle . JSFiddle

 function claculateNextDate() { var date = new Date(); var nextDay = document.getElementById("dayOfWeek").value; var day = date.getDay(); var noOfDaysToAdd = (7 - day) + parseInt(nextDay); date.setDate(date.getDate() + noOfDaysToAdd); document.getElementById("result").innerHTML = date.toDateString(); } 
 <select id="dayOfWeek"> <option value="0">Sunday</option> <option value="1">Monday</option> <option value="2">Tuesday</option> <option value="3">Wednesday</option> <option value="4">Thursday</option> <option value="5">Friday</option> <option value="6">Saturday</option> </select> <button onclick="claculateNextDate()">Calculate Next Date</button> <p id="result"></p> 

I don't know about moment.js, but it seems rather complex for something rather simple. 我不知道moment.js,但是对于一些简单的事情来说似乎很复杂。

function firstMatchingDayOfWeek(day, date) {
    var delta = date.getDay() - day,
        result = new Date(date);

    if (delta) {
        result.setDate(result.getDate() + ((7 - delta) % 7));
    }

    return result;
}

I think the code is rather self-explanatory (don't we all ;-) ), but in order to clarify the steps: 我认为代码是不言自明的(不是所有人;-)),但是为了澄清步骤:

  • firstMatchingDayOfWeek(day, date) > call the function specifying the day of week (0-6) and a date object firstMatchingDayOfWeek(day, date) >调用指定星期几(0-6)和日期对象的函数
  • delta = date.getDay() - day > calculate how many days the date needs to shift in order to reach the same day of week delta = date.getDay() - day >计算日期需要移动多少天才能到达一周的同一天
  • result = new Date(date) > create a new Date instance based on the input (so you get to preserve the original date) result = new Date(date) >根据输入创建一个新的Date实例(这样您就可以保留原始日期)
  • result.setDate(result.getDate() + ((7 - delta) % 7)) > set the date part (day of month) to a week minus the delta, modulo a week (as delta can be negative and you want the first occurrence of the same day) result.setDate(result.getDate() + ((7 - delta) % 7)) >将date部分(每月的某天)设置为减去delta的一周,以一周为模(因为delta可以为负,并且您希望当天的第一次出现)

 function firstMatchingDayOfWeek(day, date) { var delta = date.getDay() - day, result = new Date(date); if (delta) { result.setDate(result.getDate() + ((7 - delta) % 7)); } return result; } // tests for (var i = 1; i < 28; ++i){ var check = new Date('2016-02-' + ('00' + i).substr(-2)), output = document.querySelector('#out') .appendChild(document.createElement('pre')), log = []; log.push('input: ' + check); for (var day = 0; day <= 6; ++day) { var next = firstMatchingDayOfWeek(day, check); log.push(day + ' > ' + next); } output.innerText = log.join('\\n'); } 
 pre { border: 1px solid gold; } 
 <div id="out"></div> 

Here's a possible answer too using momentjs (assumes match days will be 0 (sunday) - 6): 这也是使用momentjs的可能答案(假设比赛日将为0(星期日)-6):

var startDate = moment(competition.startDate);
var matchDay = Number(matchTimes[0].day);
var daysToAdd = Math.ceil((startDate.day() - matchDay) / 7) * 7 + matchDay;
var proposedDate = moment(startDate).startOf('week').add(daysToAdd, 'd');

My solution 我的解决方案

var weekDayToFind = moment().day('Monday').weekday() //change monday to searched day name
var givenDate = moment('2016-02-10') // pass the given date

var searchDate = moment(givenDate)
while (searchDate.weekday() !== weekDayToFind){ 
  searchDate.add(1, 'day'); 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM