简体   繁体   English

如何计算仅给定月份、该月内的周数和星期几的日期

[英]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:我正在调用一个返回以下对象的 api,告诉我夏令时从 3 月 11 日开始,适用于给定的时区:

{
  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.在这种情况下,week:2 代表三月的第二周。

How do I create March 11th from this?我如何从中创建 3 月 11 日? I have the following function which works fine for March, but realized this would fail for April if say the api returned the following:我有以下功能在 3 月份运行良好,但意识到如果说 api 返回以下内容,这将在 4 月份失败:

{
  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如果您只想要一个月中某个特定日期的第 n 次出现,您可以获取该月的第 1 次,移至该特定日期的第一次出现,然后添加(n-1) * 7天以获得第 n 次出现,例如

 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;
},

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

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