settingsAccountsettings
Menusettings

Q: Monthly Calendar in JavaScript

+1 vote

Write a JavaScript function calendar ([day, month, year]) that returns a monthly calendar as HTML table (like in the examples below) by given day, month and year. Weeks start by “Sun” (Sunday) and end by “Sat” (Saturday).

The input comes as array of 3 numbers:

  • day (1 ≤ day ≤ 31)
  • month (1 ≤ month ≤ 12)
  • year (1900 ≤ year ≤ 2100)

The output should be an HTML table, holding the calendar rows and columns, like in the examples below. Display the weeks as table rows: <tr>…</tr>. Display the days as table cells: <td>…</td>. Display the days of the previous month with CSS class “prev-month”, the days of the next month with CSS class “next-month” and the current day with CSS class “today”. See the examples below.

Examples:

Input 1:
24
12
2012

Output 1:

<table>
  <tr><th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th></tr>
  <tr><td class="prev-month">25</td><td class="prev-month">26</td><td class="prev-month">27</td><td class="prev-month">28</td><td class="prev-month">29</td><td class="prev-month">30</td><td>1</td></tr>
  <tr><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td></tr>
  <tr><td>9</td><td>10</td><td>11</td><td>12</td><td>13</td><td>14</td><td>15</td></tr>
  <tr><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td><td>22</td></tr>
  <tr><td>23</td><td class="today">24</td><td>25</td><td>26</td><td>27</td><td>28</td><td>29</td></tr>
  <tr><td>30</td><td>31</td><td class="next-month">1</td><td class="next-month">2</td><td class="next-month">3</td><td class="next-month">4</td><td class="next-month">5</td></tr>
</table>

Preview 1:

preview 1 of the calendar


Input 2:
4
9
2016

Output 2:

<table>
  <tr><th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th></tr>
  <tr><td class="prev-month">28</td><td class="prev-month">29</td><td class="prev-month">30</td><td class="prev-month">31</td><td>1</td><td>2</td><td>3</td></tr>
  <tr><td class="today">4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td></tr>
  <tr><td>11</td><td>12</td><td>13</td><td>14</td><td>15</td><td>16</td><td>17</td></tr>
  <tr><td>18</td><td>19</td><td>20</td><td>21</td><td>22</td><td>23</td><td>24</td></tr>
  <tr><td>25</td><td>26</td><td>27</td><td>28</td><td>29</td><td>30</td><td class="next-month">1</td></tr>
</table>

Preview 2:

preview 2 of the monthly calendar

HTML Skeleton:
To simplify your work, use the below HTML code and write the missing code in the calendar() function:

<!DOCTYPE html>
<html>
<head>
    <title>Monthly Calendar</title>
    <style>
        .prev-month, .next-month { color: #CCC }
        .today { font-weight: bold; background: #DDD; }
        .title { background: #AAAAFF; margin: 10px 0; padding:5px }
        table { border: 1px solid #CCC;}
        td { text-align: center; }
        #calendarCode { width: 100%; }
    </style>
    <script>
        function calendar([day, month, year])
        {
            // TODO: return the HTML text holding the calendar table
        }
    </script>
</head>

<body>
    Day: <input id="day" type="number" value="4" />
    Month: <input id="month" type="number" value="9" />
    Year: <input id="year" type="number" value="2016" />
    <input type="button" value="Show"
        onclick="let calendarHTML =
            calendar([document.getElementById('day').value,
                document.getElementById('month').value,
                document.getElementById('year').value]);
            document.getElementById('calendar').innerHTML = calendarHTML;
            document.getElementById('calendarCode').innerText = calendarHTML" />
    <div class="title">Calendar:</div>
    <div id="calendar">Calendar will be shown here</div>
    <div class="title">HTML:</div>
    <textarea rows="12" id="calendarCode"></textarea>
</body>

</html>

Screenshot:

This is how your calendar should look in Web browser, when the calendar() function is implemented correctly:

monthly calendar look in javascript

asked in JavaScript category by user sam

1 Answer

0 votes

Here are some hints how to create the monthly calendar with JavaScript and HTML:

  • Play with the class Date in JavaScript and make some calculations.
  • Print the calendar table headings + days.
  • Print the days from the previous month (if any):
  • Find the day of week for the first day of the input date.
  • If it is not Sunday, days from the previous month exist.
  • Go back a few days in the previous month to find the closest Sunday (first week day).
  • Start from it and print the days until the end of the previous month.
  • Print the days from the current month.
  • Print the days, one after another.
  • Create a new table row after the last week day (Saturday).
  • Print the days from the next month (if any).
  • Stop when you reach Saturday (the last week day).

Here is the HTML code first:

<!DOCTYPE html>
<html>
<head>
    <title>Monthly Calendar</title>
    <style>
        .prev-month, .next-month {
            color: #CCC
        }

        .today {
            font-weight: bold;
            background: #DDD;
        }

        .title {
            background: #AAAAFF;
            margin: 10px 0;
            padding: 5px
        }

        table {
            border: 1px solid #CCC;
        }

        td {
            text-align: center;
        }

        #calendarCode {
            width: 100%;
        }
    </style>
</head>

<body>
Day: <input id="day" type="number" value="4"/>
Month: <input id="month" type="number" value="9"/>
Year: <input id="year" type="number" value="2016"/>
<input type="button" value="Show"
       onclick="let calendarHTML =
            calendar([document.getElementById('day').value,
                document.getElementById('month').value,
                document.getElementById('year').value]);
            document.getElementById('calendar').innerHTML = calendarHTML;
            document.getElementById('calendarCode').innerText = calendarHTML"/>

<div class="title">Calendar:</div>
<div id="calendar">Calendar will be shown here</div>
<div class="title">HTML:</div>
<textarea rows="12" id="calendarCode"></textarea>
<script src="yourjscode.js"></script>
</body>

</html>

The JavaScript code (the solution):

function calendar(arr) {
    let [day,month,year]=arr.map(Number);
    let html = "<table>\n";
    html += " <tr><th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th></tr>\n";
    let currentDate = new Date(year, month - 1, 1);
    let lastDayOfPreviousMonth = new Date(year, month - 1, 0).getDate();
    if (currentDate.getDay() !== 0) {
        currentDate = new Date(year, month - 2, lastDayOfPreviousMonth - currentDate.getDay() + 1);
    }

    let previousMonth = new Date(year, month - 2, 1).getMonth();
    let nextMonth = new Date(year, month, 1).getMonth();
    while (currentDate.getMonth() !== nextMonth ||
    currentDate.getDay() !== 0) {
        if (currentDate.getDay() === 0) {
            html += " <tr>";
        }
        if (currentDate.getMonth() === previousMonth) {
            html += `<td class="prev-month">${currentDate.getDate()}</td>`;
        } else if (currentDate.getMonth() === nextMonth) {
            html += `<td class="next-month">${currentDate.getDate()}</td>`;
        } else if (currentDate.getDate() === day) {
            html += `<td class="today">${currentDate.getDate()}</td>`;
        } else {
            html += `<td>${currentDate.getDate()}</td>`;
        }
        if (currentDate.getDay() === 6) {
            html += "</tr>\n";
        }

        currentDate.setDate(currentDate.getDate() + 1);

    }
    html += "</table>";
    return html;
}

console.log(calendar([24, 12, 2012]));

 

answered by user ak47seo
function calendar([day, month, year]) {
    day = Number(day);
    month = Number(month);
    year = Number(year);

    let date = new Date(year, month - 1, day);
    let nextMonthDays = [];
    let prevMonthDays = [];
    let currentMonthDays = [];

    // Current month
    let currentMonth = new Date(date);
    currentMonth.setDate(1);
    let temp = new Date(currentMonth);
    temp.setMonth(currentMonth.getMonth() + 1);
    temp.setDate(0);
    let stop = temp.getDate();
    while (true) {
        currentMonthDays.push(new Date(currentMonth));
        if ((currentMonth.getDate() == stop))
            break;
        currentMonth.setDate(currentMonth.getDate() + 1);
    }

    // Next month
    let nextMonth = new Date(date);
    nextMonth.setMonth(nextMonth.getMonth() + 1);
    nextMonth.setDate(1);
    while (true) {
        if (nextMonth.getDay() == 0)
            break;
        nextMonthDays.push(new Date(nextMonth));
        nextMonth.setDate(nextMonth.getDate() + 1);
    };

    // Previous month
    let prevMonth = new Date(date);
    prevMonth.setDate(0);
    while (true) {
        prevMonthDays.push(new Date(prevMonth));
        if (prevMonth.getDay() == 0)
            break;
        prevMonth.setDate(prevMonth.getDate() - 1);
    };
    prevMonthDays.reverse();

    // open table
    let html = "<table>\n";

    // Append headers
    html +=
        "<tr><th>Sun</th><th>Mon</th>" +
        "<th>Tue</th><th>Wed</th><th>Thu</th>" +
        "<th>Fri</th><th>Sat</th></tr>\n";
    // Flow helpers
    let counter = 0;
    let flow = -1;
    let currentMonthLen = currentMonthDays.length;
    let prevMonthLen = prevMonthDays.length;
    let nextMonthLen = nextMonthDays.length;
    let boundary = currentMonthDays[0].getDay() == 0
        ? (currentMonthLen + nextMonthLen) / 7
        : (currentMonthLen + prevMonthLen + nextMonthLen) / 7;

    // Append cells to table
    for (let row = 0; row < boundary; row++) {
        html += "  <tr>";

        for (let col = 0; col < 7; col++) {
            // Append previous month days
            if (counter < prevMonthLen && flow == -1) {
                // fix the flow if current month's starting day is Sat
                if (currentMonthDays[0].getDay() == 0) {
                    flow++;
                    counter = 0;
                    col--;
                    continue;
                }
                html += `<td class="prev-month">${prevMonthDays[counter].getDate()}</td>`;
            }
            // Control the flow
            if (counter == prevMonthLen && flow == -1 ||
                counter == currentMonthLen && flow == 0) {
                flow++;
                counter = 0;
            }
            // Append current month days
            if (counter < currentMonthLen && flow == 0) {
                if (currentMonthDays[counter].getDate() == day)
                    html += `<td class="today">${day}</td>`;
                else
                    html += `<td>${currentMonthDays[counter].getDate()}</td>`;
            }
            // Append next month days
            if (counter < nextMonthLen && flow == 1) {
                html += `<td class="next-month">${nextMonthDays[counter].getDate()}</td>`;
            }
            counter++;
        }

        html += "</tr>\n";
    }

    // close table
    html += "</table>";
    return html;
}
...