【问题标题】:Calculate date from week number in JavaScript从 JavaScript 中的周数计算日期
【发布时间】:2013-05-11 12:39:18
【问题描述】:

在知道周数和年份的情况下,如何在 JavaScript 中计算日期?对于第 20 周和 2013 年,我想获得 2013-05-16。 我正在尝试这样:

Date.prototype.dayofYear = function () {
  var d = new Date(this.getFullYear(), 0, 0)
  return Math.floor((/* enter code here */ this - d) / 8.64e + 7)
}

【问题讨论】:

  • 你应该可以在这里找到答案:stackoverflow.com/questions/6117814/… - 刚刚谷歌搜索。
  • 我想要反向。知道周数,获取日期..
  • 下面的答案实际上满足了您对 Javascript 代码的要求,但是 FWIW,momentjs 库很好地处理了这个问题。对于 ISO 8601 周数,moment("2013W20") 给出:"2013-05-13T00:00:00-06:00"

标签: javascript math


【解决方案1】:
function getDateOfWeek(w, y) {
    var d = (1 + (w - 1) * 7); // 1st of January + 7 days for each week

    return new Date(y, 0, d);
}

这里使用simple week definition,表示 2013 年的第 20 周是 5 月 14 日。

计算给定ISO8601 week 的开始日期(始终是星期一)

function getDateOfISOWeek(w, y) {
    var simple = new Date(y, 0, 1 + (w - 1) * 7);
    var dow = simple.getDay();
    var ISOweekStart = simple;
    if (dow <= 4)
        ISOweekStart.setDate(simple.getDate() - simple.getDay() + 1);
    else
        ISOweekStart.setDate(simple.getDate() + 8 - simple.getDay());
    return ISOweekStart;
}

结果:2013年第20周是5月13日,可以确认here

【讨论】:

  • 这不适用于例如 2009 年的第一周。应该从 2008 年 12 月 29 日开始,您的方法将在 1 月 5 日返回
  • 我认为dow &lt; 4 应该是dow &lt;= 4,但我还没有彻底测试过。
  • 是的,ISO 周从该年的第一个星期四开始。所以如果道是 4 意味着周开始。
  • @Damodharan 2009 年第 15 周从 4 月 6 日星期一开始。
  • 在处理考虑夏令时的一年中的部分时间时,我得到的日期不正确,为了防止这种情况,我将简单变量的创建更改为使用 Date.UTC() 构造函数。 var simple = new Date(Date.UTC(y, 0, 1 + (w - 1) * 7));
【解决方案2】:

抱歉,这有点冗长,但此解决方案也会在计算周数后返回星期日。它结合了我从几个不同地方看到的答案:

function getSundayFromWeekNum(weekNum, year) {
    var sunday = new Date(year, 0, (1 + (weekNum - 1) * 7));
    while (sunday.getDay() !== 0) {
        sunday.setDate(sunday.getDate() - 1);
    }
    return sunday;
}

【讨论】:

    【解决方案3】:

    ISO 周

    function weekDateToDate (year, week, day) {
      const firstDayOfYear = new Date(year, 0, 1)
      const days = 2 + day + (week - 1) * 7 - firstDayOfYear.getDay()
      return new Date(year, 0, days)
    }
    

    【讨论】:

    • 这是错误的weekDateToDate(2016, 52, 7) 产生 2016-12-26 而不是 2017-01-01
    • 不遵循 ISO 8601 周。不确定您所说的 ISO 周。
    【解决方案4】:

    根据周数获取日期范围

    Date.prototype.getWeek = function () {
        var target  = new Date(this.valueOf());
        var dayNr   = (this.getDay() + 6) % 7;
        target.setDate(target.getDate() - dayNr + 3);
        var firstThursday = target.valueOf();
        target.setMonth(0, 1);
        if (target.getDay() != 4) {
            target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
        }
        return 1 + Math.ceil((firstThursday - target) / 604800000);
    }
    
    function getDateRangeOfWeek(weekNo){
        var d1 = new Date();
        numOfdaysPastSinceLastMonday = eval(d1.getDay()- 1);
        d1.setDate(d1.getDate() - numOfdaysPastSinceLastMonday);
        var weekNoToday = d1.getWeek();
        var weeksInTheFuture = eval( weekNo - weekNoToday );
        d1.setDate(d1.getDate() + eval( 7 * weeksInTheFuture ));
        var rangeIsFrom = eval(d1.getMonth()+1) +"/" + d1.getDate() + "/" + d1.getFullYear();
        d1.setDate(d1.getDate() + 6);
        var rangeIsTo = eval(d1.getMonth()+1) +"/" + d1.getDate() + "/" + d1.getFullYear() ;
        return rangeIsFrom + " to "+rangeIsTo;
    };
    
    getDateRangeOfWeek(10)
    "3/6/2017 to 3/12/2017"
    
    getDateRangeOfWeek(30)
    "7/24/2017 to 7/30/2017"
    

    【讨论】:

    • 在不让用户过年的情况下如何知道所需的年份? @Aathi
    • 我认为这更容易通过6 传递给这个接受的答案来完成这个周末:function addDays(date = new Date(), days) { var end = new Date(date); end.setDate(end.getDate() + days); return end; }
    【解决方案5】:

    2019 版(如果有人想计算一周的开始日期)

    Elle 的回答非常正确,但有一个例外: 如果您想获得一周的开始日期 - 这对您没有帮助,因为 Elle 的算法根本不介意星期的开始日期。

    原因如下:

    Elle的解决方案

    function getDateOfWeek(w, y) {
      var d = (1 + (w - 1) * 7); // 1st of January + 7 days for each week
    
      return new Date(y, 0, d);
    }
    

    这里您基本上只是计算从年初(1 月 1 日)算起的天数。这意味着您的一年从哪一天开始并不重要:星期一、星期日或星期五 - 不会有任何区别。

    要设置一周的开始日期(例如星期一),您只需:

    function getDateOfWeek(w, y) {
      let date = new Date(y, 0, (1 + (w - 1) * 7)); // Elle's method
      date.setDate(date.getDate() + (1 - date.getDay())); // 0 - Sunday, 1 - Monday etc
      return date
    }
    

    【讨论】:

      【解决方案6】:
      function getDateOfWeek(weekNumber,year){
          //Create a date object starting january first of chosen year, plus the number of days in a week multiplied by the week number to get the right date.
          return new Date(year, 0, 1+((weekNumber-1)*7));
      }
      var myDate = getDateOfWeek(20,2013);
      

      【讨论】:

      【解决方案7】:

      ISO 星期日期(例如 2017-W32-3)到正常日期:

      const getZeroBasedIsoWeekDay = date => (date.getDay() + 6) % 7
      const getIsoWeekDay = date => getZeroBasedIsoWeekDay(date) + 1
      
      function weekDateToDate(year, week, weekDay) {
        const zeroBasedWeek = week - 1
        const zeroBasedWeekDay = weekDay - 1
        let days = (zeroBasedWeek * 7) + zeroBasedWeekDay
      
        // Dates start at 2017-01-01 and not 2017-01-00
        days += 1
      
        const firstDayOfYear = new Date(year, 0, 1)
        const firstIsoWeekDay = getIsoWeekDay(firstDayOfYear)
        const zeroBasedFirstIsoWeekDay = getZeroBasedIsoWeekDay(firstDayOfYear)
      
        // If year begins with W52 or W53
        if (firstIsoWeekDay > 4) days += 8 - firstIsoWeekDay
        // Else begins with W01
        else days -= zeroBasedFirstIsoWeekDay
      
        return new Date(year, 0, days)
      }
      
      const expectedAndActual = [
        [new Date('2007-01-01'), weekDateToDate(2007,  1, 1)],
        [new Date('2015-11-24'), weekDateToDate(2015, 48, 2)],
        [new Date('2015-12-31'), weekDateToDate(2015, 53, 4)],
        [new Date('2016-01-03'), weekDateToDate(2015, 53, 7)],
        [new Date('2017-01-01'), weekDateToDate(2016, 52, 7)],
        [new Date('2017-01-02'), weekDateToDate(2017,  1, 1)],
        [new Date('2017-05-07'), weekDateToDate(2017, 18, 7)],
        [new Date('2018-12-31'), weekDateToDate(2019,  1, 1)],
      ]
      
      expectedAndActual
        .forEach(value => {
          const expected = value[0].toISOString()
          const actual = value[1].toISOString()
          const isEqual = actual === expected
          console.assert(isEqual, '%s !== %s', actual, expected)
          console.log(actual, '===', expected)
        })

      【讨论】:

      • 这个是最适合我的。奇怪的是它被否决了。我所做的唯一改变是 const zeroBasedWeekDay = weekDay;
      【解决方案8】:

      @adius 功能对我有用,但我为正在寻找简单复制粘贴解决方案的人做了一些改进:

      /**
       * get date by week number
       * @param  {Number} year 
       * @param  {Number} week 
       * @param  {Number} day of week (optional; default = 0 (Sunday)) 
       * @return {Date}      
       */
      
        function weekToDate(year, week, weekDay = 0) {
          const getZeroBasedIsoWeekDay = date => (date.getDay() + 6) % 7;
          const getIsoWeekDay = date => getZeroBasedIsoWeekDay(date) + 1;
          const zeroBasedWeek = week - 1;
          const zeroBasedWeekDay = weekDay - 1;
          let days = (zeroBasedWeek * 7) + zeroBasedWeekDay;
              // Dates start at 2017-01-01 and not 2017-01-00
              days += 1;
        
          const firstDayOfYear = new Date(year, 0, 1);
          const firstIsoWeekDay = getIsoWeekDay(firstDayOfYear);
          const zeroBasedFirstIsoWeekDay = getZeroBasedIsoWeekDay(firstDayOfYear);
        
          // If year begins with W52 or W53
          if (firstIsoWeekDay > 4) {
            days += 8 - firstIsoWeekDay; 
          // Else begins with W01
          } else {
            days -= zeroBasedFirstIsoWeekDay;
          }
          
          return new Date(year, 0, days);
        }
      
      
      // test: 
      const x = [
        {year: 2001, week: 10},
        {year: 2019, week: 7},
        {year: 2020, week: 5},
        {year: 2020, week: 1},
        {year: 2020, week: 12}, 
        {year: 2020, week: 2},
        {year: 2020, week: 40},
        {year: 2021, week: 4},
        {year: 2021, week: 3},
        {year: 2021, week: 2},
        {year: 2032, week: 1}
      ]
      
      for (let i = 0; i < x.length; i++) {
        let date = weekToDate(x[i].year, x[i].week, 0);
        let d = new Date(date).toLocaleDateString('en-US', { 
          year: 'numeric',
          month: 'long',
          day: 'numeric' 
        })
      
        console.log(d);
      }

      【讨论】:

        【解决方案9】:

        这是用于获取当年一周的第一个星期一(ISO 8601):

        function getFirstMondayOfWeek(weekNo) {
            var firstMonday = new Date(new Date().getFullYear(), 0, 4, 0, 0, 0, 0);
        
            while (firstMonday.getDay() != 1) {
                firstMonday.setDate(firstMonday.getDate() - 1);
            }
            if (1 <= weekNo && weekNo <= 52)
                return firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));
        
            firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));
            if (weekNo = 53 && firstMonday.getDate() >= 22 && firstMonday.getDate() <= 28)
                return firstMonday;
            return null;
        }
        

        【讨论】:

          【解决方案10】:

          我刚刚创建了这个:

          //Returns monday and saturday of the week
          function getWeekRange(weekNo,YearNo) {
              let firstDayofYear = new Date(yearNo, 0, 1);
          
              if (firstDayofYear.getDay() > 4)  {
                  let weekStart = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 8);
                  let weekEnd = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 8 + 5);
                  return { startDay: weekStart, endDay: weekEnd }
              }
              else {
                  let weekStart = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 1);
                  let weekEnd = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 1 + 5);
                  return { startDay: weekStart, endDay: weekEnd }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-10-17
            • 1970-01-01
            • 1970-01-01
            • 2015-04-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多