简体   繁体   中英

Set Date by day of week, week & year

I'm building a calendar. I have events on the calendar that repeat yearly on the same day of week.

For example:

  • eventOne, Sunday (0), Week 3

  • eventTwo, Tuesday (2), week 12

EventOne should have a date object that is always the Sunday for week 3 of the current year.

EventTwo should have a date object that is always the Tuesday of week 12 of the current year.

 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 } const date = getDateOfISOWeek(3, 2020) console.log(date)

The above function will give me the first day of the week I'm requesting but no implementation for the day of week and I've struggled to find a Date function todo this.

I'm happy to use moment or date-fns if there are any convenience functions to help out, but would prefer if I could get to a native javascript solution.

i'm not sure, but if i understand correctly you could make this simply using date-fns:

var startOfYear = require('date-fns/start_of_year')
var getDay = require('date-fns/get_day')
var addDays = require('date-fns/add_days')
var addWeeks = require('date-fns/add_weeks')    

let getDateOfISOWeek = (w, y, d) => {
  let startDayOfYear = startOfYear(new Date(y,0,1));
  let diff = d - getDay(startDayOfYear);
  let firstAppearanceOfYear = addDays(startDayOfYear, diff < 0 ? 7 + diff : diff);
  return addWeeks(firstAppearanceOfYear, w - 1);
}

let result = getDateOfISOWeek(3, 2020, 0); //Sun Jan 19 2020
let result2 = getDateOfISOWeek(3, 2021, 0); // Sun Jan 17 2021

first two arguments - week & year, third - index of day you are looking for(0 - Sunday, 6 - Saturday)

The getDateOfISOWeek works fine, though it's a little clunky. You just need to add the required number of days to get the particular day you want.

ISO weeks start on Monday, so it's just a matter of getting the start of the week and adding the day number less 1. Sunday can be 0 or 7 so either ECMAScript or ISO numbering is OK.

 /* Return date for start of ISO week in given year ** @param {number|string} week: required ISO week number ** @param {number|string} year: required year ** @returns {Date} date of Monday at start of week */ function getDateOfISOWeek(week, year) { // Get date for 1 Jan in given year let d = new Date(year, 0, 1); let dow = d.getDay(); // Shift to start of ISO week 1 d.setDate((dow <= 4? 2 : 9) - d.getDay()); // Add required number of weeks d.setDate(d.getDate() + (week - 1)*7); return d; } /* Return date for a day in given ISO week in given year ** @param {number|string} day: day number, Mon=1, Tue=2, ... Sun=0 or 7 ** @param {number|string} week: required ISO week number ** @param {number|string} year: required year ** @returns {Date} date of required day */ function getDayOfISOWeek(day, week, year) { let d = getDateOfISOWeek(week, year); d.setDate(d.getDate() + (+day || 7) - 1); return d; } // Options for formatting dates let opts = {weekday:'short', day:'numeric', month:'short', year:'numeric'}; // Examples [[1, 3,2020], // Mon, week 3, 2020 [0, 1,2020], // Sun, week 1, 2020 [7, 1,2020], // Sun, week 1, 2020 [5,10,2020], // Fri, week 10, 2020 [6,27,2022], // Sat, week 27, 2022 [2,12,2020], // Tue, week 12, 2020 [2,12,2021], // Tue, week 12, 2021 [2,12,2022] // Tue, week 12, 2022 ].forEach(args => console.log( args + ': ' + getDayOfISOWeek(...args).toLocaleString(void 0, opts) ));

PS. You really should include braces for blocks and semicolons to terminate statements, otherwise you can get some really difficult to find bugs.

You can simply implement a such function, by subtracting the offset from weeks times 7; and calculating the offset based on 4th January (because that's the day which is always in the 1st week )

Notes:

  • If you consider Sunday as the first day of the week, pass 0 as weekDay , while if you consider Sunday as the last day of the week, you should pass 7.
  • The week is one-based, passing 1 may result in a Date with the value of the previous year (eg createDate(2020, 1, 1) will return 30 December 2019.

 function createDate(year, week, weekDay){ const date = new Date(year, 0, 4) const offset = (date.getDay() || 7) - weekDay date.setDate(week * 7 - offset - 3) return date } console.log(createDate(2020,3,7).toDateString()) console.log(createDate(2021,3,7).toDateString()) console.log(createDate(2020,12,4).toDateString()) console.log(createDate(2021,12,4).toDateString()) console.log(createDate(2015,1,4).toDateString())

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