Doing the best research, I couldn't find the answer in JavaScript, But I found this solution that works perfectly in 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))
Now trying to convert this into JavaScript, you need to know python (I know how to deal with python) the best thing I come up with
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;
};
Now this works in JS, however when I try to use the function I built
mostFrequentDays(212)
I don't get the expected output
**You are given a year as an integer. Return the most frequent day(s) of the week in that year. The resulting list of days should be sorted by the order of days in week starting from Monday (e. g. ['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"]);
});
A lot of them works when I convert the python code to JS except the last one because the JS Date doesn't work on year 212
Please help me make a function that can pass all the tests, there are a lot of python versions of the solution but the one I used is the easy one, and in python, that code works because the DateTime in python work on a date like 212. Or maybe if you know a better version that's not originally from python, how would you implement a solution for JS
Thank you, Best regards.
CodePudding user response:
You need to define "doesn't work".
A non–leap year has 365 days, which is 52 weeks plus one day. So whichever day is the first day of the year will have 53 occurrences and all the others will have 52. So the most frequent is just the weekday of 1 January.
For a leap year, the first and second day will have 53 occurrences and the others 52. e.g. 1 Jan 2018 was Monday, as was 31 December, so there were 53 Mondays and 52 of the others. 1 Jan 2020 was Wednesday and a leap year, 31 Dec was Thursday so 53 Wednesdays and Thursdays and 52 of the rest.
Of course a random range of dates will make life a little more difficult.
A function to implement the above is:
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)}`
));
Another algorithm (which is what the PHP code is doing) is to check if 1 Jan and 31 Dec are the same day. If they are, return that day. If not, return both days.
The only sorting that's required is where a leap year starts on Sunday. The default return is [Sunday, Monday] but the requirement is for [Monday, Sunday] in that particular case.
So if 1 Jan is a Sunday (day 0) reverse the day list, e.g.
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)}`
));