javascript 中最常见的工作日问题

most-frequent-weekdays problem in javascript

尽最大努力,我无法在 JavaScript 中找到答案, 但我发现这个解决方案在 python

中完美运行
import datetime
def most_frequent_days(year):
    days = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')
    most = sorted(list(set([datetime.date(year, 1, 1).weekday() ,datetime.date(year, 12, 31).weekday()])))
    return [days[i] for i in most]

print(most_frequent_days(212))

现在想把它转换成JavaScript,你需要知道python(我知道如何处理python)我想出的最好的办法

const mostFrequentDays = year => {
  function getDayOfWeek(date) {
    const dayOfWeek = new Date(date).getDay();    
    return isNaN(dayOfWeek) ? null : 
      ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][dayOfWeek];
  }
  //let days = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ]
  let most = [getDayOfWeek(`${year}-1-1`), getDayOfWeek(`${year}-12-31`)].sort()
  let mySet = [...new Set(most)]
  //let sorted = mySet;
  let i = 0;
  let data = [];
  while (i < mySet.length) {
      data = [ ...data, mySet[i] ]
    i++;
  }
  return data;
};

现在这在 JS 中有效,但是当我尝试使用我构建的函数时 mostFrequentDays(212) 我没有得到预期的输出

**给你一个整数年。 Return 那一年中一周中出现频率最高的一天。生成的天数列表应按从星期一开始的一周中的天数排序(例如 ['Monday'、'Tuesday'])。 **

Tests

it("should handle basic tests", () => {
    assert.deepEqual(mostFrequentDays(2427), ["Friday"]);
    assert.deepEqual(mostFrequentDays(2185), ["Saturday"]);
    assert.deepEqual(mostFrequentDays(1084), ["Tuesday", "Wednesday"]);
    assert.deepEqual(mostFrequentDays(1167), ["Sunday"]);
    assert.deepEqual(mostFrequentDays(1216), ["Friday", "Saturday"]);
    assert.deepEqual(mostFrequentDays(1492), ["Friday", "Saturday"]);
    assert.deepEqual(mostFrequentDays(1770), ["Monday"]);
    assert.deepEqual(mostFrequentDays(1785), ["Saturday"]);
    assert.deepEqual(mostFrequentDays(212), ["Wednesday", "Thursday"]);
});

当我将 python 代码转换为 JS 时,除了最后一个代码,它们中的很多都有效,因为 JS 日期在 212 年 [=16 时不起作用=]

请帮我做一个可以通过所有测试的函数,有很多 python 版本的解决方案,但我使用的是简单的,在 python 中,该代码有效,因为 python 中的 DateTime 在 212 这样的日期工作。 或者如果你知道一个更好的版本不是最初来自 python,你将如何实现 JS

的解决方案

谢谢, 最好的问候。

您需要定义“不起作用”。

平年有 365 天,也就是 52 周加一天。因此,无论哪一天是一年中的第一天,都会出现 53 次,其他所有天都会出现 52 次。所以最频繁的只是 1 月 1 日这个工作日。

对于闰年,第一天和第二天将出现 53 次,其他日期为 52 次。例如2018 年 1 月 1 日是星期一,12 月 31 日也是,所以有 53 个星期一和 52 个其他星期一。 2020 年 1 月 1 日是星期三,闰年,12 月 31 日是星期四,所以 53 个星期三和星期四,其余 52 个。

当然,随机范围的日期会让生活变得更加困难。

实现上述的一个函数是:

function mostFrequentDaysOfYear(year = new Date().getFullYear()) {
  // 1 Jan
  let d = new Date(year, 0);
  // Weekday name for 1 Jan
  let mostFrequent = [d.toLocaleString('en',{weekday:'long'})];
  let isLeap = new Date(year, 1, 29).getDate() == 29;
  // If leap year, add next day's name too
  if (isLeap) {
    d.setDate(d.getDate() + 1);
    mostFrequent.push(d.toLocaleString('en',{weekday:'long'}))
  }

  return mostFrequent;
}

// Examples
[2018, 2020, 2022, 212].forEach(year => console.log(
  `${year}: ${mostFrequentDaysOfYear(year)}`
));

另一种算法(PHP 代码所做的)是检查 1 月 1 日和 12 月 31 日是否是同一天。如果是,那一天 return。如果没有,return 这两天。

唯一需要的排序是闰年从星期日开始。默认 return 是 [Sunday, Monday] 但在这种情况下要求是 [Monday, Sunday]。

因此,如果 1 月 1 日是星期日(第 0 天),则反转日期列表,例如

function mostFrequentDaysOfYear(year = new Date().getFullYear()) {
  let dayName = d => d.toLocaleString('en',{weekday:'long'});
  // 1 Jan
  let d = new Date(year, 0, 1);
  let d0 = dayName(d);
  // 31 Dec
  let d1 = dayName(new Date(year, 11, 31));
  let result = d0 == d1? [d0] : [d0, d1];
  // If d0 is Sunday, reverse result
  return d.getDay()? result : result.reverse();
}

[2427, // Friday
 2185, // Saturday
 1084, // Tuesday, Wednesday
 1167, // Sunday
 1216, // Friday, Saturday
 1492, // Friday, Saturday
 1770, // Monday
 1785, // Saturday
 2040, // Monday, Sunday - leap year starting on Sun
 212   // Wednesday, Thursday
].forEach(year => console.log(
  `${year}: ${mostFrequentDaysOfYear(year)}`
));