I am writing a JavaScript program that takes in a date typed by the user and determines what day of the week the given date falls on. I am able to get the program to take in the date. I have used debug statements to print the values of the day, the month, the year, and the century to make sure the program is getting the values correctly, which they are so far.
I also have a debug variable called totalNumDays
which stores the number of days for each month since that value differs. (January has 31 days, April has 30 days, February has either 28 or 29 days). The problem I am having is getting the number to be correct for the month February.
What I did was create an array of all the months with 31 days:
//1 = January, 3 = March, 5 = May,..., etc.
var monthNumsWith31 = [1, 3, 5, 7, 8, 10, 12];
Then later on I use a for loop to iterate through to determine the number of days. I tried a couple different things here. The one I thought made the most sense was:
for(var i = 0; i < monthNumsWith31.length; i++)
{
if(month == monthNumsWith31[i])
{
totalNumDays = 31;
}
else
{
if(month == 2 && isLeapYear() == true)
{
totalNumDays = 29;
}
else if(month == 2 && isLeapYear() == false)
{
totalNumDays = 28;
}
else
{
totalNumDays = 30;
}
}
I tried a whole bunch of different things and can't seem to get it to store the correct number of days for February. I even tried creating a second array of monthNumsWith30
and use two different for loops to iterate through both of those and set the appropriate number of days for months with 30 and 31 days. I think the problem might be in my isLeapYear()
function. Here is the code for isLeapYear()
. Note that year
is global so the function does have access to it.
function isLeapYear() {
if(year % 4 == 0)
{
if(year % 100 == 0)
{
if(year % 400 == 0)
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
else
{
return false;
}
}
I tried to follow the formula for determining whether a year is a leap year or not. The formula can be seem here:
Does anyone know why my function is not doing what it is supposed to be doing? Thanks.
UPDATE I got it working correctly now for figuring the correct number of days for each month. I am having another issue however.
To find out which day of the week a given date occurs on, I am using Zeller's Congruence. The particular formula I am using is ((26M - 2) / 10 + D + Y + Y/4 + C/4 + 5C) MOD 7
where M
, D
, Y
are exactly what they seem and C
is the century (first two digits of the year). There is a part of the algorithm that states
IF Month < 3 THEN
Year = Year - 1
Month = Month + 10
ELSE
Month = Month - 2
END IF
I got all that working seemingly correctly. I put in many debug statements to make sure it gets the correct values which it is, but for some reason the puter is evaluating the expression incorrectly.
This algorithm will give a number between 0 and 6. 0 being Sunday, 1 being Monday, etc. For example, taken the date 2/15/16. This date occurred on a Monday. Monday, February 15, 2016.
In my program I have the following code
var weekdayIndex = (Math.floor((26 * monthVal) - 2 / 10) + dayVal +
yearVal + Math.floor(yearVal / 4) + Math.floor(centuryVal / 4) +
(5 * centuryVal)) % 7;
When this expression runs, it should equal 1
, but for some reason it equals 0
. I did the math by hand and evaluated each individual expression over and over again and kept getting 1
. Doing this by hand I got the numbers to be (31 + 15 + 15 + 3 + 5 + 20) % 7
. When I put this expression into the puter directly (without all the variable names and Math.floor expressions, just numbers) it correctly gets the value. I don't know why it is incorrect when I use the variable names and expressions rather. Any ideas?
I am writing a JavaScript program that takes in a date typed by the user and determines what day of the week the given date falls on. I am able to get the program to take in the date. I have used debug statements to print the values of the day, the month, the year, and the century to make sure the program is getting the values correctly, which they are so far.
I also have a debug variable called totalNumDays
which stores the number of days for each month since that value differs. (January has 31 days, April has 30 days, February has either 28 or 29 days). The problem I am having is getting the number to be correct for the month February.
What I did was create an array of all the months with 31 days:
//1 = January, 3 = March, 5 = May,..., etc.
var monthNumsWith31 = [1, 3, 5, 7, 8, 10, 12];
Then later on I use a for loop to iterate through to determine the number of days. I tried a couple different things here. The one I thought made the most sense was:
for(var i = 0; i < monthNumsWith31.length; i++)
{
if(month == monthNumsWith31[i])
{
totalNumDays = 31;
}
else
{
if(month == 2 && isLeapYear() == true)
{
totalNumDays = 29;
}
else if(month == 2 && isLeapYear() == false)
{
totalNumDays = 28;
}
else
{
totalNumDays = 30;
}
}
I tried a whole bunch of different things and can't seem to get it to store the correct number of days for February. I even tried creating a second array of monthNumsWith30
and use two different for loops to iterate through both of those and set the appropriate number of days for months with 30 and 31 days. I think the problem might be in my isLeapYear()
function. Here is the code for isLeapYear()
. Note that year
is global so the function does have access to it.
function isLeapYear() {
if(year % 4 == 0)
{
if(year % 100 == 0)
{
if(year % 400 == 0)
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
else
{
return false;
}
}
I tried to follow the formula for determining whether a year is a leap year or not. The formula can be seem here: https://gyazo./9e4b7fb92014d1e27315807c188fd5e0
Does anyone know why my function is not doing what it is supposed to be doing? Thanks.
UPDATE I got it working correctly now for figuring the correct number of days for each month. I am having another issue however.
To find out which day of the week a given date occurs on, I am using Zeller's Congruence. The particular formula I am using is ((26M - 2) / 10 + D + Y + Y/4 + C/4 + 5C) MOD 7
where M
, D
, Y
are exactly what they seem and C
is the century (first two digits of the year). There is a part of the algorithm that states
IF Month < 3 THEN
Year = Year - 1
Month = Month + 10
ELSE
Month = Month - 2
END IF
I got all that working seemingly correctly. I put in many debug statements to make sure it gets the correct values which it is, but for some reason the puter is evaluating the expression incorrectly.
This algorithm will give a number between 0 and 6. 0 being Sunday, 1 being Monday, etc. For example, taken the date 2/15/16. This date occurred on a Monday. Monday, February 15, 2016.
In my program I have the following code
var weekdayIndex = (Math.floor((26 * monthVal) - 2 / 10) + dayVal +
yearVal + Math.floor(yearVal / 4) + Math.floor(centuryVal / 4) +
(5 * centuryVal)) % 7;
When this expression runs, it should equal 1
, but for some reason it equals 0
. I did the math by hand and evaluated each individual expression over and over again and kept getting 1
. Doing this by hand I got the numbers to be (31 + 15 + 15 + 3 + 5 + 20) % 7
. When I put this expression into the puter directly (without all the variable names and Math.floor expressions, just numbers) it correctly gets the value. I don't know why it is incorrect when I use the variable names and expressions rather. Any ideas?
- if your problem is just calculating the day of the week of a given date why aren't you using the Date api? – Mauricio Poppe Commented Mar 17, 2016 at 23:14
- We were told that we are not allowed to use that. – GenericUser01 Commented Mar 17, 2016 at 23:20
6 Answers
Reset to default 3Your function is ok, except for a simple thing: you are missing the year parameter!
function isLeapYear(year) {
return year % 4 == 0 &&
(year % 100 !== 0 || year % 400 === 0);
}
But, with your extended syntax is ok too:
function isLeapYear(year) {
if(year % 4 == 0)
{
if(year % 100 == 0)
{
if(year % 400 == 0)
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
else
{
return false;
}
}
isLeapYear(1900)
yields false
, as expected, 2000 true
, 1996 true
, 1997 false
.
Seems legit to me.
I think that your logic is rather suspect. I use the following function to determine whether a given year is a leap year:
CsiLgrDate.leap_year = function (year)
{ return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); };
Your function is correct, the error is because javascript Array
for month
's is zero-indexed.
Change this line:
var monthNumsWith31 = [1, 3, 5, 7, 8, 10, 12];
To this:
var monthNumsWith31 = [0, 2, 4, 6, 7, 9, 11];
And subtract one from all your month references (february is Array index 1)
You can test it by typing (new Date()).getMonth()
on the console: you will see that march == 2
.
Hope it helps.
Here give this a shot. I assume you're just starting. We can avoid a lot of the nested if statements. Also, you'll want to start to get into the habit of using triple equals (===) as it does type checking and won't do weird things with "truthy" values.
First thing, looking at your isLeapYear
function. When you do a check for an if statement and use the equal operator to pare them, it's going to return a true or false, so if we aren't doing weird things were we expect true to be false (though there are easy ways to do that too) we can actually just return the expression to get true or false, instead of needing to return true or false if your expression is true or false.
It also might be worth wild to pass in the year as an argument instead of getting it from the parent's scope. But in this case it doesn't actually matter, I'm sure.
The &&
will check if a statement is true, then it will execute the next expression. And you can chain it if you are expecting everything to be true, because if one thing is false, then everything is false. So no need to write nested if statements.
function checkLeapYear(yearToCheck) {
return yearToCheck%4 === 0 && yearToCheck%100 === 0 && yearToCheck%400 === 0;
}
So looping through an array is kind of expensive. You might learn that if you start to loop through arrays within arrays. But luckily we don't even need that for this example.
This is a switch statement. It's very handy if you have values you need to equal the same thing. But you might hear from a lot of people the way I wrote mine is wrong and that you should never let a case fall through. I disagree with those people, because I think this is a great example of when you'd want to do just that.
This switch will take a variable, the month in this case. Compare it with the value in the cases, then execute the code for the case. It will fall through into the next case without a break;
Because we want 1, 3, 5, 7, 8, 10, 12
to all make totalNumDays = 31
we set that for the lowest case and have the rest fall into.
But when if month
equals 2, we want it totalNumDays
to be 29 on leap years or 28 otherwise. Ternary Operator It basically works like a shorthand if statement. You give it an expression, in this case the checkLeapYear
function, then a ?
to start the ternary operator. Then the value for when it's true, this case we want it to equal 29. Then for false values use :
then put want you want the false value to be, in this case 28.
In the switch statement, default just means do this if there are no matches. Which is making totalNumDays
equal 30. Which this could be a bit dangerous as if we make month equal to 13 or 'A' it will still make totalNumDays
equal 30. But preparing for every possibility isn't something I'm too concerned around right now.
switch(month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
totalNumDays = 31;
break;
case 2:
totalNumDays = checkLeapYear(year) ? 29 : 28;
break;
default:
totalNumDays = 30;
break;
}
Anyway, I hope that helps and wasn't too much to take in. As for why your code isn't working. I think it might be because your loop starts on month 0. Which is going to be a 30 day month.
The code actually works if the year parameter is used in the isLeapYear call and in the function declaration.
Here is the code exactly as posted (well, I added a missing closing }
that I assume was a posting omission):
// Set some test values
var monthNumsWith31 = [1, 3, 5, 7, 8, 10, 12];
var month = 2;
var year = 2000
for(var i = 0; i < monthNumsWith31.length; i++)
{
if(month == monthNumsWith31[i])
{
totalNumDays = 31;
}
else
{
if(month == 2 && isLeapYear(year) == true)
{
totalNumDays = 29;
}
else if(month == 2 && isLeapYear(year) == false)
{
totalNumDays = 28;
}
else
{
totalNumDays = 30;
}
}
}
function isLeapYear(year) {
if(year % 4 == 0)
{
if(year % 100 == 0)
{
if(year % 400 == 0)
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
else
{
return false;
}
}
document.write(totalNumDays);
https://codepen.io/pen?template=QWmqeqj
Steps:
1). If the year is evenly divisible by 100, then If the year is evenly divisible by 400.
*The year is a leap year.*
2). If the year is not evenly divisible by 100, then If the year is evenly divisible by 4.
*The year is a leap year.*
3). If the year is not evenly divisible by 100 and year is not evenly divisible by 400 or year is not evenly divisible by 4.
*The year is not a leap year.*