简体   繁体   中英

How to calculate a Date given only month, week number within that month, and day of week

I am calling an api that returns the following object to tell me that daylight savings time begins on March 11th for a given timezone:

{
  dayOfWeek: "Sunday",
  month: 3,
  timeOfDay: "0001-01-01T02:00:00.000Z",
  week: 2
}

where week:2 reprsents the 2nd week of March in this case.

How do I create March 11th from this? I have the following function which works fine for March, but realized this would fail for April if say the api returned the following:

{
  dayOfWeek: "Saturday",
  month: 4,
  timeOfDay: "0001-01-01T02:00:00.000Z",
  week: 2
}

Code:

/**
 * Given the year, month, week day, week number of the month, and time, calculate a date
    - set the date to the first day of the month
    - then adjust the date backwards to the proper weekday
    - then move it forward by 7 * week number to get it to the proper date
 */
calcDateFromDaylightSavingRulesAPI: function(year, month, time, dayOfWeek, weekNum) {
    const weekDays = {
        Sunday: 0,
        Monday: 1,
        Tuesday: 2,
        Wednesday: 3,
        Thursday: 4,
        Friday: 5,
        Saturday: 6
    };

    const date = new Date(year, month, 1, time);
    date.setDate(date.getDate() + weekDays[dayOfWeek] - date.getDay());
    date.setDate(date.getDate() + (weekNum * constants.DAYS_PER_WEEK));

    return date;

If you just want the nth occurrence of a particular day in a month, you can get the 1st of the month, move to the first occurrence of the particular day, then add (n-1) * 7 days to get to the nth occurrence, eg

 function getNthDay(year, month, dayName, n) { var weekDays = { Sunday: 0, Monday: 1, Tuesday: 2, Wednesday: 3, Thursday: 4, Friday: 5, Saturday: 6 }; // validate input values here, throw errors if required, eg // dayName must be in weekdays, 0 < n < 6 // Create date for first day of required month var d = new Date(year, month - 1, 1); // Set to first instance of particular day d.setDate((8 - (d.getDay() - weekDays[dayName]))%7); // Add (n-1)*7 days d.setDate(d.getDate() + (n-1) * 7); // Check final date is still in required month return d.getMonth() == month - 1? d : 'fail'; } // Second Sunday in March, 2018 console.log(getNthDay(2018,3,'Sunday',2).toString())

If you want the Sunday of the second week, that is a little harder to calculate since some places start weeks on Sunday, and some on Monday. Also, the algorithm for the week of the month may change from place to place (as does week in year).

I think this is working correctly now. Thanks for your help everyone!

/**
 * Given an object which contains month, time, week day, and week number in a month, calculate a date
    - set the date to the first day of the month
    - then adjust the date backwards to the proper weekday
    - then move it forward by 7 * week number to get it to the proper date
 */
calcDateFromDaylightSavingRulesAPI: function(ruleSet) {
    const today = new Date();
    const year = today.getFullYear();
    const month = ruleSet.month - 1;
    const time = new Date(ruleSet.timeOfDay).getUTCHours();
    const dayOfWeek = ruleSet.dayOfWeek;
    const weekNum = ruleSet.week;

    const weekDays = {
        Sunday: 0,
        Monday: 1,
        Tuesday: 2,
        Wednesday: 3,
        Thursday: 4,
        Friday: 5,
        Saturday: 6
    };

    const date = new Date(year, month, 1, time);
    const diff = weekDays[dayOfWeek] - date.getDay();
    date.setDate(date.getDate() + (diff >= 0 ? diff - 7 : diff));
    date.setDate(date.getDate() + (weekNum * constants.DAYS_PER_WEEK));

    return date;
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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