How to Properly print Month Calendar on Terminal

放肆的年华 提交于 2021-02-08 06:38:00

问题


Hello and thanks in advance for the assistance. I have a program that is supposed to print the current month calendar based on the user inputs of month and year. The program mostly work but i am having issues with formatting and the first day of the month is not starting under the proper date.

Example output:

    October 2020
------------------------------
 Sun Mon Tue Wed Thu Fri Sat
      1   2   3   4   5
   6   7   8   9  10   11   12 
  13   14   15   16   17   18   19 
  20   21   22   23   24   25   26 
  27   28   29   30   31 

October 2020 will begin on a Thursday, but 1 is printed under Mon. October 4th is a Sunday, so that is where the new line should begin.

Please see attached my code. Thanks again

import java.util.*;

public class CalendarMonthDisplay {

        public static void main(String[] args) {
            Scanner input = new Scanner(System.in); //Scan for user input
            System.out.print("Please enter a month between 1 and 12 (e.g. 5): "); //Prompt user to enter month
            int m = input.nextInt();

            System.out.print("Please enter a full year (e.g. 2018): "); //Prompt user to enter year
            int y = input.nextInt();

             //Print calendar for the month of the year
            if ( m < 1 || m > 12)
                System.out.print("Wrong input! Please try again.");
            else
                printMonthCalendar(m, y);
        }

        static void printMonthCalendar (int m, int y) { //Display calendar in format above
            int startDay = getStartDay(m, y);
            int numDaysInMonths = getNumDaysInMonth(m, y);

            printMonthHeader(m, y);
            printMonthBody(startDay, numDaysInMonths);
        }

        static void printMonthBody (int startDay, int numDaysInMonths) { //Display the days in the calendar

            int i;

            for (i = 0; i <= startDay; i++)
                System.out.print(" ");

            for (i = 1; i <= numDaysInMonths; i++) {
                if ( i < 10 )
                    System.out.print("   " + i );
                else
                    System.out.print("  " + i + " ");

                if ((startDay + i) % 7 == 0)
                    System.out.println();
            }
            System.out.println();
        }

        static void printMonthHeader (int m, int y) { //Display the header information
            System.out.println("\t" + getMonthName(m) + " " + y);
            System.out.println("------------------------------");
            System.out.println(" Sun Mon Tue Wed Thu Fri Sat");
        }

        static  String getMonthName (int m) {
            String monthName = null;
            switch (m) {
                case 1: monthName = "January";
                break;
                case 2: monthName = "February";
                break;
                case 3: monthName = "March";
                break;
                case 4: monthName = "April";
                break;
                case 5: monthName = "May";
                break;
                case 6: monthName = "June";
                break;
                case 7: monthName = "July";
                break;
                case 8: monthName = "August";
                break;
                case 9: monthName = "September";
                break;
                case 10: monthName = "October";
                break;
                case 11: monthName = "November";
                break;
                case 12: monthName = "December";
            }
            return monthName;
        }


        static int getNumDaysInMonth (int m, int y) {
            int numDaysInMonths= 0;
            switch (m) {
                case 1: case 3: case 5: case 7: case 8: case 10: case 12:
                    numDaysInMonths= 31;
                    break;
                case 4: case 6: case 9: case 11:
                    numDaysInMonths = 30;
                    break;
                case 2:
                    if (isLeapYear(y))
                        numDaysInMonths = 29;
                    else
                        numDaysInMonths = 28;
                    break;
            }
            return numDaysInMonths;
        }

        static boolean isLeapYear (int y) {
            return  (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
//                return  true;
//            return false;
        }

        static int getStartDay (int m, int y) {
            // Adjust month number & year to fit Zeller's numbering system
            if (m < 3)
                m = m + 12;
                y = y - 1;

            int d = 1; //Set day parameter to 1
            int k = y % 100;      // Calculate year within century
            int j = y / 100;      // Calculate century term
            int h = 0;            // Day number of first day in month 'm'

            h = ( d + ( 13 * ( m + 1 ) / 5 ) + k + ( k / 4 ) + ( j / 4 ) + ( 5 * j ) ) % 7;

            // Convert Zeller's value to ISO value (1 = Mon, ... , 7 = Sun )
            int dayNum = ( ( h + 5 ) % 7 ) + 1;
            return dayNum;
        }


}

回答1:


I recommend you do it using the modern date-time API. Learn more about the modern date-time API from Trail: Date Time.

import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in); // Scan for user input
        System.out.print("Please enter a month between 1 and 12 (e.g. 5): "); // Prompt user to enter month
        int m = input.nextInt();

        System.out.print("Please enter a full year (e.g. 2018): "); // Prompt user to enter year
        int y = input.nextInt();
        printMonth(y, m);
    }

    static void printMonth(int year, int month) {
        YearMonth ym = YearMonth.of(year, month);
        System.out.println("Sun Mon Tue Wed Thu Fri Sat");
        int counter = 1;

        // Get day of week of 1st date of the month and print space for as many days as
        // distant from SUN
        int dayValue = LocalDate.of(year, month, 1).getDayOfWeek().getValue();
        for (int i = 0; i < dayValue; i++, counter++) {
            System.out.printf("%-4s", "");
        }

        for (int i = 1; i <= ym.getMonth().length(ym.isLeapYear()); i++, counter++) {
            System.out.printf("%-4d", i);

            // Break the line if the value of the counter is multiple of 7
            if (counter % 7 == 0) {
                System.out.println();
            }
        }
    }
}

A sample run:

Please enter a month between 1 and 12 (e.g. 5): 9
Please enter a full year (e.g. 2018): 2020
Sun Mon Tue Wed Thu Fri Sat
        1   2   3   4   5   
6   7   8   9   10  11  12  
13  14  15  16  17  18  19  
20  21  22  23  24  25  26  
27  28  29  30  

Note: Learn about formatted printing at Formatter.




回答2:


I don’t think your getStartDay method returns the day of week number that you expect. It seems to be returning 1 for Wednesday through 7 for Tuesday. Examples:

Month           Start day of week  getStartDay()
------------------------------------------------
July 2020       Wednesday          1
August 2020     Saturday           4
September 2020  Tuesday            7
October 2020    Thursday           2

There is probably one or two more problems in your code, but I think you should fix this fundamental one first.

It’s a fine exercise, you’re surely learning. For production code one would never implement Zeller’s algorithm or any other algorithm for finding lengths of months and days of week. This is done much more reliably by the standard library as shown in the answer by Arvind Kumar Avinash.



来源:https://stackoverflow.com/questions/64054639/how-to-properly-print-month-calendar-on-terminal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!