How do I print out a calendar month in console? - java

I have an assignment for a class I'm taking in which I have to make a Java console application, and it involves asking the user for a date, parsing that date, and working out what day of the month that date starts on. I have to then print out a calendar to look like this:
Calendar for September 2016
Su Mo Tu We Th Fr Sa
- - - - 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 -
I have the date, I have the number of the day that the date starts on, (eg. Day= 1 (Monday), Day= 2(Tuesday), etc.)
Now, I can use a very messy looking switch statement with nested if statements that says, depending on the value of Day, and the number of days in that month, print out this pre-made calendar, and I can just pre-make a calendar for every eventual combination of Day and number of days in that month. But I don't want to do that, and I can't figure out an easier way of doing it. Has anybody got any ideas of a tidier, more succinct way of doing it? Would it be something involving 2d arrays?
PS. I'm not allowed to use any date-based library classes available in Java.

well you can use this if you change your mind
public static void main(String args [])
{
// type MM yyyy
Scanner in = new Scanner(System.in);
System.out.print("Enter month and year: MM yyyy ");
int month = in.nextInt();
int year = in.nextInt();
in.close();
// checks valid month
try {
if (month < 1 || month > 12)
throw new Exception("Invalid index for month: " + month);
printCalendarMonthYear(month, year);}
catch (Exception e) {
System.err.println(e.getMessage());
}
}
private static void printCalendarMonthYear(int month, int year) {
Calendar cal = new GregorianCalendar();
cal.clear();
cal.set(year, month - 1, 1); // setting the calendar to the month and year provided as parameters
System.out.println("Calendar for "+ cal.getDisplayName(Calendar.MONTH, Calendar.LONG,
Locale.US) + " " + cal.get(Calendar.YEAR));//to print Calendar for month and year
int firstWeekdayOfMonth = cal.get(Calendar.DAY_OF_WEEK);//which weekday was the first in month
int numberOfMonthDays = cal.getActualMaximum(Calendar.DAY_OF_MONTH); //lengh of days in a month
printCalendar(numberOfMonthDays, firstWeekdayOfMonth);
}
private static void printCalendar(int numberOfMonthDays, int firstWeekdayOfMonth) {
int weekdayIndex = 0;
System.out.println("Su MO Tu We Th Fr Sa"); // The order of days depends on your calendar
for (int day = 1; day < firstWeekdayOfMonth; day++) {
System.out.print(" "); //this loop to print the first day in his correct place
weekdayIndex++;
}
for (int day = 1; day <= numberOfMonthDays; day++) {
if (day<10) // this is just for better visialising because unit number take less space of course than 2
System.out.print(day+" ");
else System.out.print(day);
weekdayIndex++;
if (weekdayIndex == 7) {
weekdayIndex = 0;
System.out.println();
} else {
System.out.print(" ");
}}}

Related

Java finding the next leap year

How do I find the next leap year if the given input isn't a leap year?
A year is considered a leap year when it is either:
divisible by 4, but not 100 or
divisible by both 4, 100, and 400 at the same time
Input:
A single line containing a number that represents a year, here 1702.
Output:
The next soonest leap year if the input is not a leap year. Otherwise, output "Leap year".
The next leap year is 1704
Heres my code:
When I input 1702 nothing shows but if it's 1700 it works. If ever you can help pls only use if else or while since these two are the only allowed for it to run.
import java.util.Scanner;
class Main {
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
int year = input.nextInt();
int leap = 0;
if (year % 400 == 0) {
System.out.print("Leap year");
} else if (year % 100 == 0) {
leap += 4;
year += leap;
System.out.print("The next leap year is ");
System.out.print(year);
} else if (year % 4 == 0) {
System.out.print("Leap year");
}
input.close();
}
}
tl;dr short solution with java.time:
Java 8+ provide the package java.time which has a class Year which provides a method to determine if that very year was/is/will be a leap year, that is Year.isLeap().
You could use it to get your desired result, maybe like in the following example:
public static void main(String[] args) {
// hard-coded example number
int numericalYear = 1702;
// create the year from the number given
Year year = Year.of(numericalYear);
// check if that year is leap
if (year.isLeap()) {
System.out.println("Leap Year");
} else {
// of find the next one by adding 1 year and checking again
while (!year.isLeap()) year = year.plusYears(1);
// print the next one
System.out.println("Next leap year is " + year);
}
}
This example has an output of
Next leap year is 1704
The major part of the main() is an if-statement with three branches. I think the most difficulties you have is you mixed the part to determine a leap year, and the part to control the workflow.
The workflow of your program is:
Take an user input
Check if this is a leap year
Print the response according to step 2
The logic to determine a leap year is:
divisible by 4, but not 100 or
divisible by both 4, 100, and 400 at the same time
You could try to isolate these two area with two different piece of code. Take one step at a time. Then things will become less complex. You can simplify your if from three to two branches. Since the year is either a leap or not, no other possibility. If it is leap year, print the year. Else, print next leap year. Only two cases.
In order to check whether a year leap year or not, obviously you need an algorithms. You can decouple the algorithms into a separate function. This way you can isolate the leap year logic with your workflow.
Example
import java.util.Scanner;
public class Main{
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
int year = input.nextInt();
// base cycle is 4 year
final int leapCycle = 4;
if (isLeapYear(year)) {
System.out.print("Leap year");
} else {
// complete the year with next cycle
year += leapCycle - (year % leapCycle);
// the next maybe not a leap year e.g. 1800, 1900
if (!isLeapYear(year)) {
// then advance it with one more cycle
year += leapCycle;
}
System.out.print("The next leap year is ");
System.out.print(year);
}
input.close();
}
private static boolean isLeapYear(int year) {
if (year % 4 == 0) {
if (year % 100 == 0) {
return year % 400 == 0;
} else {
return true;
}
}
return false;
}
}
Test cases
1700
The next leap year is 1704
1702
The next leap year is 1704
1799
The next leap year is 1804
1800
The next leap year is 1804
1999
The next leap year is 2000
2000
Leap year
2001
The next leap year is 2004

How to get last three months first date and last date based on current date including current date in java?

I want to categorize values based on months so to filter those values required 1st & last date of last three months based on current month including current month values. Here how many last months is parameter. I wanted list of all months 1st date and last date. Any logic for the same will be helpful.
for example:-
// parameters
int lastMonths = 3;
date currentDate= 26-04-2019;
//expected output
current month is 04-2019 ,1st date is 1-04-2019 and last date is 30-04-2019
previous month is 03-2019, 1st date is 01-03-2019 and last date is 31-03-2019
previous month is 02-2019, 1st date is 01-02-2019 and last date is 28-02-2019
Use java.util.Calendar for addition and subraction in date
and
java.text.DateFormat to format date
DateFormat format = new SimpleDateFormat("dd-MM-yyyy", Locale.US);
DateFormat monthFormat = new SimpleDateFormat("MM-yyyy", Locale.US);
Calendar cal = Calendar.getInstance();
cal.setTime(format.parse("26-04-2019"));
for (int i = 0; i < 3; i++){
System.out.println("currentDate: " + monthFormat.format(cal.getTime())); // print current month
cal.set(Calendar.DAY_OF_MONTH, 1);
System.out.println("first date: " + format.format(cal.getTime())); // print first date
cal.add(Calendar.MONTH, 1);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.add(Calendar.DATE, -1);
System.out.println("last date: " + format.format(cal.getTime())); // print last date
cal.add(Calendar.MONTH, -1);
}
Important to say - there are tons of libraries who will give you this specific need, but I would like relying on one that does the work and was actually designed for (some of yours...) those use cases -
Java.time.LocalDate library (already built into Java 8)
import java.time.LocalDate;
LocalDate now = LocalDate.now(); // 2019-04-26
In order to get first and last days of month, you can use:
LocalDate start = YearMonth.now().atDay(1);
(now can be some other month, of course)
LocalDate end = YearMonth.now().atEndOfMonth();
You can use it specifically on one / two months, or with some for loop. Examples below:
1. Specific call:
LocalDate earlierOneMonth = now.minusMonths(1); // 2019-03-26
earlierOneMonth.getDay(); // 26
2. For Loop: (so you'll need something like an array / list to store those values...)
for(int i=0; i < lastMonths - 1; i++){
arr(i) = now.minusMonths(i + 1);
}
Also, in order to get the name of the month, you can use ->
earlierOneMonth.getMonth(); // APRIL
earlierOneMonth.getMonth.getValue(); // 04
Lastly, in order to get the year, you can use ->
earlier.getYear(); // 2019
Once you have all of your desired values, you can print them out as you requested, with that expected output:
"current month is" + nowMonth + "-" + nowYear + " ,1st date is" + nowDay + "-" + nowMonth + "-" + nowYear + " and last date is ...
Let me know if it's clear enough :)
tl;dr
YearMonth.now().minusMonths( 3 ).atDay( 1 ) // Get the first day of the month of three months ago. Returns `LocalDate` object.
YearMonth.now().minusMonths( 3 ).atEndOfMonth() // Get the last day of the month of three months ago. Returns `LocalDate` object.
YearMonth
You really care about the months. The dates are secondary. So focus on the months. Java has a class for that!
The YearMonth class represents a particular month of a particular year.
ZoneId z = ZoneId.of( "America/Edmonton" ) ;
YearMonth currentYm = YearMonth.now( z ) ;
Collect your months of interest.
List< YearMonth > yms = new ArrayList<>() ;
int limit = 3 ; // We want current month plus three previous months.
for( int i = 0 ; i <= limit ; i ++ ) {
YearMonth ym = currentYm.minusMonths( i ) ;
yms.add( ym ) ;
}
When you need dates, loop the list. Let YearMonth determine the first and last days of the month.
for( YearMonth ym : yms ) {
System.out.println( "YearMonth: " + ym + " starts: " + ym.atDay( 1 ) + " ends: " + ym.atEndOfMonth() ) ;
}
See this code run live at IdeOne.com.
YearMonth: 2019-04 starts: 2019-04-01 ends: 2019-04-30
YearMonth: 2019-03 starts: 2019-03-01 ends: 2019-03-31
YearMonth: 2019-02 starts: 2019-02-01 ends: 2019-02-28
YearMonth: 2019-01 starts: 2019-01-01 ends: 2019-01-31
If you need a Date object then the following will do just fine
Date date = getDate(targetDate);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MONTH, -3);
calendar.set(Calendar.DAY_OF_MONTH, 1);
// calendar.getTime()
// The line above returns Date object
If you need a plain String then you can format it any way you want by simply using DateTimeFormatter from org.joda.time library and just use it's print() method on calendar.getTimeInMillis().
LocalDate currentDate = LocalDate.of(2019, 4, 26);//current date
System.out.println(currentDate);
int lastMonths = 3;//number of months
LocalDate prevDate = null;
LocalDate start = null;
LocalDate end = null;
for(int i = 0; i < lastMonths; i++) {
if(prevDate == null) {
start = currentDate.withDayOfMonth(1);//First day of current month
end = currentDate.withDayOfMonth(currentDate.lengthOfMonth());//Last day of current month
prevDate = currentDate.minusMonths(1);//subtracting one month from current month
} else {
start = prevDate.withDayOfMonth(1);//First day of previous month
end = prevDate.withDayOfMonth(prevDate.lengthOfMonth());//Last day of previous month
prevDate = prevDate.minusMonths(1);//subtracting one month from previous month
}
System.out.println(start + " " + end);
}
Output:
2019-04-26
2019-04-01 2019-04-30
2019-03-01 2019-03-31
2019-02-01 2019-02-28
Reference:
Get first and last day of month using threeten, LocalDate
int lastMonths = 3;
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
DateFormat monthYearFormat = new SimpleDateFormat("MM-yyyy");
for (int i = 0; i < lastMonths; i++) {
int monthOfYear = month - i;
// if month is january, reset couter and month
if(monthOfYear == 0) {
month = 13;
year -= 1;
i = 0;
continue;
}
// get last day of month (month length)
YearMonth yearMonth = YearMonth.of(year, monthOfYear);
int firstDay = 1;
int lastDay = yearMonth.lengthOfMonth();
// create date with given year, month and day
Date date = new GregorianCalendar(year, monthOfYear - 1, firstDay).getTime();
String monthAndYear = monthYearFormat.format(date);
String currentOrPrevious;
if (i == 0) {
currentOrPrevious = "current";
} else {
currentOrPrevious = "previous";
}
String output = String.format("%s month is %s, 1st date is %02d-%s and last date is %d-%s", currentOrPrevious, monthAndYear, firstDay, monthAndYear, lastDay, monthAndYear);
System.out.println(output);
}
Output:
current month is 04-2019, 1st date is 01-04-2019 and last date is 30-04-2019
previous month is 03-2019, 1st date is 01-03-2019 and last date is 31-03-2019
previous month is 02-2019, 1st date is 01-02-2019 and last date is 28-02-2019

Gregorian Calendar Adding Days and Printing

I'm trying to create a simple calendar app. In general, I want to print the calendar in month view. I am able to find the day and position of the first day of the month. After that, I want to add a day to the calendar and print the next day until I have printed all the days of that month. However, when I add one to the calendar, I don't get 2 (first day is 1), I get 9. Could someone please let me know why it's doing that. Here's what I have so far:
import java.util.Calendar;
import java.util.GregorianCalendar;
enum MONTHS
{
January, February, March, April, May, June, July, August, September, October, November, December;
}
enum DAYS
{
Su, Mo, Tu, We, Th, Fr, Sa;
}
public class MyCalendarTester {
static GregorianCalendar cal = new GregorianCalendar(); // capture today
public static void main(String[] args) {
// TODO Auto-generated method stub
MONTHS[] arrayOfMonths = MONTHS.values();
DAYS[] arrayOfDays = DAYS.values();
System.out.println(" " + arrayOfMonths[cal.get(Calendar.MONTH) - 1] + " " + cal.get(Calendar.YEAR)); //prints the month and year
for(int i = 0; i < arrayOfDays.length; i++){
if(i == 0){
System.out.print(arrayOfDays[i]);
}
else{
System.out.print(" " + arrayOfDays[i]);
}
}//print days of week
System.out.println();
for(int i = 0; i < arrayOfDays.length; i++){
if(!arrayOfDays[i].equals(arrayOfDays[cal.get(Calendar.DAY_OF_WEEK) - 1])){
System.out.println(" ");
}
else{
System.out.print(" " + Calendar.getInstance().getActualMinimum(Calendar.DAY_OF_MONTH));
break;
}
}
cal.add(Calendar.DAY_OF_MONTH, 1);
System.out.println(" " + cal.get(Calendar.DATE));
System.out.println("I think we're done here!");
}
}
The GregorianCalendar() constructor without any arguments constructs an instance of the GregorianCalendar class for todays date. In your code you use this constructor:
static GregorianCalendar cal = new GregorianCalendar(); // capture today
The day of the month, at the time of posting in 8. 8+1=9
To create a GregorianCalendar with the day of the month initialized to 1 you need to use GregorianCalendar(int year,int month,int dayOfMonth). As stated in the javadocs, this constructor
Constructs a GregorianCalendar with the given date set in the default time zone with the default locale.
static GregorianCalendar cal = new GregorianCalendar(2015,5,1);
The calendar object you're adding one to is static GregorianCalendar cal = new GregorianCalendar(); - that's why it said 9 (it is March, 9th)

How to have int input correlate to a substring?

I am trying to write a program that takes input from a user. The enter a number 1-12 and it returns the month January-December. I have to have all the months in one long string and then use a substring to return the corresponding month.
I am very confused as to how to get an int to correlate to a substring. I would appreciate some general guidelines for doing this. I'm not looking to have the whole program done for me.
Don't use substring(). If you have a csv of month names, use split() to turn the string into an array:
String months = "January,February,etc";
int choice; // 1-12
String monthName = months.split(",")[choice - 1];
Note that java arrays are zero-based, so you must subtract 1 from a 1-12 ranged number when used as an index.
Easier to read would be:
static String[] monthNames = "January,February,etc".split("");
then in your method:
String monthName = monthNames[choice - 1];
When you get the values of the month using your substring, store it in your array of String. And then get the 1 - 12 value by their indexes + 1.
Beside using Split you can use StringTokenizer to parse your string as well.
My Code:
int i = 1;
int month = 0;
while (i == 1) {
System.out.println("Enter your number ");
Scanner input = new Scanner(System.in);
month = input.nextInt();
if (month > 13 || month < 0) {
System.out.println("your number has to be between 1 and 12");
} else {
i = 2;
}
}
List<String> monthList = new ArrayList<>();
StringTokenizer st = new StringTokenizer("January February March April"
+ " May June July August September October November December");
while (st.hasMoreTokens()) {
monthList.add(st.nextToken(" "));
}
System.out.println("the month is " + monthList.get(month - 1));
My Output:
Enter your number
333
your number has to be between 1 and 12
Enter your number
3
the month is March

Java code to determine number of days elapsed does not return correct answer

The problem with this code is that it does calculate the days alive only for some birth dates. I tried using different birth dates and testing it with an online calculator and it seems not all are correct. I think the problem is because of Leapyears, more and less than 30 days in a month.
public class DaysAlive {
public static void main (String [] args){
Scanner userInput = new Scanner(System.in);
int TodayYear, TodayMonth, TodayDay;
int YearBorn, MonthBorn, DayBorn;
int DaysAlive;
System.out.println("Enter today's date");
System.out.print ("Year: ");
TodayYear = userInput.nextInt ();
System.out.print ("Month: ");
TodayMonth = userInput.nextInt ();
System.out.print ("Day: ");
TodayDay = userInput.nextInt ();
System.out.println("Enter date of birth");
System.out.print ("Year: ");
YearBorn = userInput.nextInt ();
System.out.print ("Month: ");
MonthBorn = userInput.nextInt ();
System.out.print ("Day: ");
DayBorn = userInput.nextInt ();
//I think this line is the problem
DaysAlive = (TodayYear - YearBorn) *365 + (TodayMonth - MonthBorn) *30 +(TodayDay - DayBorn);
System.out.println("DaysAlive: " + DaysAlive);
}
}
How about using Calendar? It will do all of that for you... or joda time library
check it out here:
Getting the number of days between two dates in java
If I understand what you want, you should be able to use something like this -
public static void main(String[] args) {
Scanner userInput = new Scanner(System.in);
System.out.println("Enter today's date");
System.out.print("Year: ");
int todayYear = userInput.nextInt();
System.out.print("Month: ");
int todayMonth = userInput.nextInt();
System.out.print("Day: ");
int todayDay = userInput.nextInt();
// Java has January as month 0. Let's not require that the user know.
Calendar today = new GregorianCalendar(todayYear, todayMonth - 1,
todayDay);
System.out.println("Enter date of birth");
System.out.print("Year: ");
int yearBorn = userInput.nextInt();
System.out.print("Month: ");
int monthBorn = userInput.nextInt();
System.out.print("Day: ");
int dayBorn = userInput.nextInt();
Calendar born = new GregorianCalendar(yearBorn, monthBorn - 1, dayBorn);
double diff = today.getTimeInMillis() - born.getTimeInMillis();
diff = diff / (24 * 60 * 60 * 1000); // hours in a day, minutes in a hour,
// seconds in a minute, millis in a
// second.
System.out.println(Math.round(diff));
}
With output
Enter today's date
Year: 2014
Month: 03
Day: 14
Enter date of birth
Year: 2014
Month: 03
Day: 13
1
You are right, the problem is that not all months have 30 days in them. A simple solution would to be use if statements and make another integer variable called something like monthMultiplier. As other people pointed out you can also use the Calendar
if(TodayMonth == 9 || TodayMonth == 11 || TodayMonth == 4 || TodayMonth == 6) {
monthMultiplier = 30;//30 days in these months
}
if(TodayMonth == 2){
monthMultiplier = 28;//WELL 28.25 accounting for leap years
}
else {
monthMultiplier = 31;
}
DaysAlive = (TodayYear - YearBorn) *365 + (TodayMonth - MonthBorn) * monthMultiplier +(TodayDay - DayBorn);
Joda-Time
The Joda-Time library makes easy work of this problem. Just one line of code, basically. Joda-Time handles time zones, leap days, and other issues.
Hand-coding such date-time work is risky, error-prone, and frankly silly given the excellent libraries available (Joda-Time and the new java.time package in Java 8).
Example Code
Here’s some example code in Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime start = new DateTime(2008, 4, 26, 0, 0, 0, timeZone);
DateTime stop = new DateTime(2008, 5, 26, 0, 0, 0, timeZone);
int daysBetween = Days.daysBetween( start, stop ).getDays();
Dump to console…
System.out.println( "start: " + start );
System.out.println( "stop: " + stop );
System.out.println( "daysBetween: " + daysBetween );
When executed…
start: 2008-04-26T00:00:00.000+02:00
stop: 2008-05-26T00:00:00.000+02:00
daysBetween: 30

Categories