I am creating a Discord bot with node.js and discord.js, and there's a feature that allows users to vote thanks to a command, but I'd like them to vote only once a week.
The issue is that, on this Discord, weeks start on Friday and end on Thursday, therefore I can't simply write :
var weekNow = moment().week();
var weekLastVote = moment(dateLastVote).week();
if (weekNow == weekLastVote){
//Prevent from voting again
} else {
//Let the user vote
}
Therefore, I have written some code that seems to work, but I'd like your opinion on it as it seems very sloppy and I'm not sure if I have taken into account all of the possibilities (I don't know if I need to use my month variables for example):
module.exports = {
isSameWeek: function (dateLastVote) {
// moments for today's date
var dayNow = moment().weekday();
var weekNow = moment().week();
var monthNow = moment().month();
var yearNow = moment().year();
var dateNow = moment().format('MMDDYYYY'); // moment without hours/minutes/seconds
// moments for last vote's date
var dayLastVote = moment(dateLastVote).weekday();
var weekLastVote = moment(dateLastVote).week();
var monthLastVote = moment(dateLastVote).month();
var yearLastVote = moment(dateLastVote).year();
var dateLastVote = moment(dateLastVote).format('MMDDYYYY'); // moment without hours/minutes/seconds
if ((yearNow === yearLastVote && weekNow === weekLastVote && dayLastVote < 5) || // 5 = Friday, starting day of the week (a week = Friday to thursday)
(yearNow === yearLastVote && weekNow - 1 === weekLastVote && dayLastVote >= 5 && dayNow < 5) ||
(dateNow === dateLastVote)
){
return true;
} else {
return false;
}
}
};
As I said, this seems do to the trick but I would like someone else's opinion on it to be sure there isn't a simpler way or, if there isn't, if I haven't forgotten anything.
Thank you for reading :)
I do not know how our approaches compare to each other in matter of performance, but I still wanna show my approach on the problem:
function isSameWeek(firstDay, secondDay, offset) {
var firstMoment = moment(firstDay);
var secondMoment = moment(secondDay);
var startOfWeek = function (_moment, _offset) {
return _moment.add("days", _moment.weekday() * -1 + (_moment.weekday() >= 7 + _offset ? 7 + _offset : _offset));
}
return startOfWeek(firstMoment, offset).isSame(startOfWeek(secondMoment, offset), "day");
}
What the solution does is calculating the start of the week of each of the given dates in respect to the offset (for values >= -7 and <= 0) and returning whether both have the same start of the week. Same start of the week = same week.
All you have to do is call the function passing two date objects (or moment objects) and an offset between -7 and 0, depending on how the week is shifted in relation to a "regular" week.
I think that the best way to do want you need is to tell moment that your week starts on Friday. You can simply use updateLocale
method customizing dow
(day of week) key of the week
object and then use your first code snippet. See Customize section of the docs to get more info about locale customization.
Here a live example of setting a custom day as first day of the week and then using your code to check if a given day is in the current week:
moment.updateLocale('en', {
week: {
dow : 5, // Friday is the first day of the week.
}
});
function checkWeek(dateLastVote){
var weekNow = moment().week();
var weekLastVote = moment(dateLastVote).week();
if (weekNow == weekLastVote){
//Prevent from voting again
console.log(moment(dateLastVote).format('YYYY-MM-DD') + ' is in the current week')
} else {
//Let the user vote
console.log(moment(dateLastVote).format('YYYY-MM-DD') + ' is NOT in the current week')
}
}
checkWeek('2017-05-30'); // same week mon-sun, but previous week fri-thu
checkWeek('2017-06-01'); // same week mon-sun, but previous week fri-thu
checkWeek('2017-06-08'); // next week mon-sun, but current week fri-thu
// First day of the current week
console.log(moment().startOf('week').format('YYYY-MM-DD'));
// Last day of the current week
console.log(moment().endOf('week').format('YYYY-MM-DD'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
EDIT An improved solution is to use moment isSame
passing 'week'
as second parameter. As the docs states:
Check if a moment is the same as another moment.
If you want to limit the granularity to a unit other than milliseconds, pass it as the second parameter.
Here a live sample:
moment.updateLocale('en', {
week: {
dow : 5, // Friday is the first day of the week.
}
});
function isSameWeek(dateLastVote){
var now = moment();
var lastVote = moment(dateLastVote);
if (now.isSame(lastVote, 'week')){
//Prevent from voting again
console.log(moment(dateLastVote).format('YYYY-MM-DD') + ' is in the current week')
} else {
//Let the user vote
console.log(moment(dateLastVote).format('YYYY-MM-DD') + ' is NOT in the current week')
}
}
isSameWeek('2017-06-10'); // same week mon-sun, but next week fri-thu
isSameWeek('2017-06-03'); // previous week mon-sun, but current week fri-thu
isSameWeek('2017-06-06'); // current week both mon-sun and fri-thu
// First day of the current week
console.log(moment().startOf('week').format('YYYY-MM-DD'));
// Last day of the current week
console.log(moment().endOf('week').format('YYYY-MM-DD'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With