0

I am currently in the process of making a webpage where, when a user enters a standard date in the Gregorian calendar, the program will return the day of the week it falls on. I have tried the longer, brutal approach of take a code number assigned to the day, month, year, and century (as well as leap year, which took a few nested if-else blocks). That one did end up working, but the day of the week was wrong and would shift dramatically as you went up or down a day.

My next method was this method by the University of Waterloo in Ontario, which had stated that this method was more efficient for computer programming. Here is my current code, which does not output anything

I am open to any comments, suggestions, or concerns and feel free to yell at me for my incompetence.

let innerHTMLText = "";

function calculateDay() {
  const day = document.getElementById("dayInput").value;
  let month = document.getElementById("monthInput").value;
  const year = document.getElementById("yearInput").value;

  let lastYearDigits = parseInt(year.substr(2, 2));
  const centuryCode = parseInt(year.substr(0, 2));
  if (month === "1" || month.toLowerCase() === "january" || month === "2" || month.toLowerCase() === "february") {
    lastYearDigits -= 1
  }

  switch (month.toLowerCase()) {
    case "january":
      month = 11;
      break;
    case "february":
      month = 12;
      break;
    case "march":
      month = 1;
      break;
    case "april":
      month = 2;
      break;
    case "may":
      month = 3;
      break;
    case "june":
      month = 4;
      break;
    case "july":
      month = 5;
      break;
    case "august":
      month = 6;
      break;
    case "september":
      month = 7;
      break;
    case "october":
      month = 8;
      break;
    case "november":
      month = 9;
      break;
    case "december":
      month = 10;
      break;
    default:
      if (Number.isInteger(parseInt(month))) {
        month = parseInt(month);
      } else {
        innerHTMLText = "buh please enter a valid month";
      }
  }

  const result = (day + Math.floor((2.6 * month) - 0.2) - (2 * centuryCode) + lastYearDigits + Math.floor(lastYearDigits / 4) + Math.floor(centuryCode / 4)) % 7;

  switch (result) {
    case 0:
      innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Sunday`;
      break;
    case 1:
      innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Monday`;
      break;
    case 2:
      innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Tuesday`;
      break;
    case 3:
      innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Wednesday`;
      break;
    case 4:
      innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Thursday`;
      break;
    case 5:
      innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Friday`;
      break;
    case 6:
      innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Saturday`;
      break;
    default:
      return;
  }
}

document.getElementById("buh").innerHTML = innerHTMLText;
<p><strong>Input any day from 1 Jan 1700 to 31 Dec 2999 below and figure out what day of the week it was, is, or will be on.</strong></p>
<form autocomplete="off" action="/DotW" onsubmit="calculateDay()">
  <label for="day">Day:</label><br />
  <input type="number" min="1" max="31" id="dayInput" name="day" required><br /><br />
  <label for="month">Month:</label><br />
  <input type="text" id="monthInput" name="month" required><br /><br />
  <label for="year">Year:</label><br />
  <input type="number" min="1700" max="2999" id="yearInput" name="year" required><br /><br />
  <input type="submit" class="fancy-button">
</form>
<br /><br />
<p id="buh"> - </p>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Archigan
  • 62
  • 11
  • I have also tried to define the innerHTMLText inside the function as a variable in the window scope. – Archigan Nov 16 '21 at 13:22
  • 1
    What's the problem with what you currently have? – DBS Nov 16 '21 at 13:26
  • Does this answer your question? [How to get the day of week and the month of the year?](https://stackoverflow.com/questions/4822852/how-to-get-the-day-of-week-and-the-month-of-the-year) – James Nov 16 '21 at 13:29
  • _"which does not output anything"_ - are you familiar with the browser console yet? First of all you should check if it shows any _errors_, that prevent your code from finishing its job. If that is not the case, then use `console.log` to check if the variables contain what you _think_ they should (or step through the code in the debugger) - if your `switch (result)` at the end there for example doesn't find any of the cases you are specifically looking for, then `innerHTMLText` will of course stay an empty string. – CBroe Nov 16 '21 at 13:30
  • @DBS currently, the edited paragraph tag on the web page does not change at all. – Archigan Nov 16 '21 at 13:31
  • @James No, unfortunately, I'm trying to output a day based on any given date between 1700 and 3000, not today's date. – Archigan Nov 16 '21 at 13:32
  • Right now, you are only calling that function when the form submits (which is submitting data and refreshing the page, so any changes to the DOM will be lost after the refresh) – DBS Nov 16 '21 at 13:32
  • why put a `switch case` for the months when the ` – Mister Jojo Nov 16 '21 at 13:43

4 Answers4

0

Several issues

  1. set the inner HTML inside the function
  2. Cancel the submit

Here I use eventListeners

The script could be shortened to a few lines though

window.addEventListener("load", function() {
  document.getElementById("calcForm").addEventListener("submit", function(e) {
    e.preventDefault(); // stop submission
    let innerHTMLText = "";


    const day = document.getElementById("dayInput").value;
    let month = document.getElementById("monthInput").value;
    const year = document.getElementById("yearInput").value;

    let lastYearDigits = parseInt(year.substr(2, 2));
    const centuryCode = parseInt(year.substr(0, 2));
    if (month === "1" || month.toLowerCase() === "january" || month === "2" || month.toLowerCase() === "february") {
      lastYearDigits -= 1
    }

    switch (month.toLowerCase()) {
      case "january":
        month = 11;
        break;
      case "february":
        month = 12;
        break;
      case "march":
        month = 1;
        break;
      case "april":
        month = 2;
        break;
      case "may":
        month = 3;
        break;
      case "june":
        month = 4;
        break;
      case "july":
        month = 5;
        break;
      case "august":
        month = 6;
        break;
      case "september":
        month = 7;
        break;
      case "october":
        month = 8;
        break;
      case "november":
        month = 9;
        break;
      case "december":
        month = 10;
        break;
      default:
        if (Number.isInteger(parseInt(month))) {
          month = parseInt(month);
        } else {
          innerHTMLText = "buh please enter a valid month";
        }
    }

    const result = (day + Math.floor((2.6 * month) - 0.2) - (2 * centuryCode) + lastYearDigits + Math.floor(lastYearDigits / 4) + Math.floor(centuryCode / 4)) % 7;

    switch (result) {
      case 0:
        innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Sunday`;
        break;
      case 1:
        innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Monday`;
        break;
      case 2:
        innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Tuesday`;
        break;
      case 3:
        innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Wednesday`;
        break;
      case 4:
        innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Thursday`;
        break;
      case 5:
        innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Friday`;
        break;
      case 6:
        innerHTMLText = `The day of the week that ${day}/${month}/${year} falls on is: Saturday`;
        break;
      default:
        return;
    }


    document.getElementById("buh").innerHTML = innerHTMLText;
  })
})
<p><strong>Input any day from 1 Jan 1700 to 31 Dec 2999 below and figure out what day of the week it was, is, or will be on.</strong></p>
<form autocomplete="off" action="/DotW" id="calcForm">
  <label for="day">Day:</label><br />
  <input type="number" min="1" max="31" id="dayInput" name="day" required><br /><br />
  <label for="month">Month:</label><br />
  <input type="text" id="monthInput" name="month" required><br /><br />
  <label for="year">Year:</label><br />
  <input type="number" min="1700" max="2999" id="yearInput" name="year" required><br /><br />
  <input type="submit" class="fancy-button">
</form>
<br /><br />
<p id="buh"> - </p>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

What's wrong with Date.getDay? And wouldn't a month selector be more appropriate?

It is generally not a good idea to use inline event handlers.

Here's an example using event delegation.

document.addEventListener(`click`, handle);
const days = `Sunday,Monday,Tuesday,Wednessday,Thursday,Friday,Saturday`.split(`,`);
const pad = nr => `${nr < 10 ? `0${nr}` : nr}`;
const formatDate = date => [
  date.getFullYear(), 
  pad(date.getMonth() + 1),
  pad(date.getDate())].join(`-`);

function handle(evt) {
  if (evt.target.id === `justABttn`) {
    const reslt = document.querySelector(`pre.result`);
    const values = [...document.querySelectorAll(`[type='number'], select`)]
      .reduce( (acc, v) => ( { ...acc, [v.id]: v.value } ), {} );
      
    if (Object.values(values).filter(v => v).length === 3) {
      const date = new Date(`${values.year}/${values.month}/${values.date}`);
      const dayOfWeek = date.getDay();
      return reslt.textContent = `${formatDate(date)} ${date > new Date() ? `will be` : `was`} on ${
        days[dayOfWeek]}\nNote: an impossible date (e.g. febr 31th or april 31th)\nmay be autoconverted to a later date`;
    }
    
    return reslt.textContent = `not enough values available`;
  }
}
body {
  margin: 1rem;
  font: 12px/15px verdana, arial;
}

h3 {
  margin-bottom: 0.3rem;
}

p, button {
  margin: 0.3rem 0;
}

pre.result {
  position: fixed;
  top: 5rem;
  left: 30vw;
}
<h3>Input a date from 1 Jan 1700 to 31 Dec 2999</h3>
<p>
  <label for="date">Date:</label><br>
  <input type="number" min="1" max="31" id="date" required value="3">
</p>
<p>
  <label for="month">Month:</label><br>
  <select id="month" required><br>
    <option value=1 selected>January</option>
    <option value=2>February</option>
    <option value=3>March</option>
    <option value=4>April</option>
    <option value=5>May</option>
    <option value=6>June</option>
    <option value=7>July</option>
    <option value=8>August</option>
    <option value=9>September</option>
    <option value=10>October</option>
    <option value=11>November</option>
    <option value=12>December</option>
  </select>
</p>
<p>
  <label for="year">Year:</label><br>
  <input type="number" min="1700" max="2999" id="year" required value="1783">
</p>
<button id="justABttn">Get me the day</button>
<pre class="result"></pre>
KooiInc
  • 119,216
  • 31
  • 141
  • 177
-1

You can use also.

document.getElementById("form").addEventListener("submit", (e) => {
  e.preventDefault();
  var dateString = document.getElementById('date').value;
  var date = new Date(dateString);
  
  var day = date.getDay();
  var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
  
  alert("The day is " + days[day]);
});
<form id="form">
<input id="date" placeholder="mm/dd/yyyy" />
<button type="submit">Submit</button>
</form>

Very efficient!

naxsi
  • 602
  • 3
  • 15
-1

Before inventing the wheel, I would give existing solutions a go. My personal favourite, when it comes to date-related javascript functions, is this: https://date-fns.org/

It has a built-in method to do exactly what you are trying to achieve: https://date-fns.org/v2.25.0/docs/getDay

Combining this with a regular date input field gives you a very solid and easy to maintain solution.

Trevor
  • 121
  • 1
  • 1
  • 6
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 16 '21 at 14:10