I'm trying to find the day of the year after you enter a date. I have a way that works but it is not the best way it seems.
I ask for the date using a Scanner object then send it through to a method where it checks what day of the year it is.
public static int theDay(int month, int day, int year)
{
int numDay = day;
/* Code here to check for leap year */
for(int i = 1; i < month; i++)
{
switch(i)
{
case 1:
numDay += 31;
break;
case 2:
numDay += 28;
break;
case 3:
numDay += 31;
break;
...
... //goes until case 12
...
}
}
return numDay;
}
I cannot use Calendar, LocalDate, arrays, and anything my teacher hasn't taught us yet. So just loops would be OK, I believe. As mentioned, this works and I get the correct day. But what would be a better way of doing this? Any help would be appreciated. Thanks!
Depending on what you're using:
Standard Java libraries, before Java 8
Calendar calendar = new GregorianCalendar();
// Just to avoid corner cases
calendar.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
calendar.set(year, month - 1, day);
int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
Joda Time
LocalDate date = new LocalDate(year, month, day);
int dayOfYear = date.getDayOfYear();
Java 8, using java.time
LocalDate date = LocalDate.of(year, month, day);
int dayOfYear = date.getDayOfYear();
Coding it yourself
(Now that we know that's what you need to do.)
Your current approach is okay, if you really need to do this yourself. You can do it without a loop though:
int daysInFebruary = ...; // Leap year calculation
switch (month)
{
case 1:
break; // Nothing to do
case 2:
numDay += 31; // Just add January
break;
case 3:
numDay += 31 + daysInFebruary; // Add January and February
break;
case 4:
numDay += 31 + daysInFebruary + 31; // Add January to March
break;
case 5:
numDay += 31 + daysInFebruary + 31 + 30; // Add January to April
break;
// etc
default:
throw new IllegalArgumentException("Invalid month: " + month);
}
That's more efficient, but I'd consider it less readable than the code you've already got.
It would be much cleaner to do this with an array, mind you - you could have one array with the lengths of each month, and another with the cumulative lengths of each month (0, 31, 59 etc). Add a special case for leap years, and Bob's your uncle. But if you're not allowed to use arrays...
Related
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;
}
}
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.
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.
I've been stuck on this issue for the past 4 hours trying different strategies which haven't prevailed much at all having checked countless posts on here and Google. Basically what I am trying to do is print out only the business working days within a week mon-fri. I have tried incrementing the day of the year each time the weekend days come up but of course this messes up the order of the days after. For example instead of having:
Iteration: 0, 1, 2, 3, 4, 5, 6, 7, 8....
Day: (0)Friday, (1)Saturday, (2)Sunday, (3)Monday, (4)Tuesday, (5)Wednesday, (6)Thursday, (7)Friday, (8)Saturday....etc
I require:
Day: (0)Friday, (1)Monday, (2)Tuesday (3)Wednesday, (4)Thursday, (5)Friday, (6)Monday, (7)Tuesday, (8)Wednesday....etc
Here's the code:
public static void date(int day) {
now = Calendar.getInstance();
//SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");//version 1
SimpleDateFormat format = new SimpleDateFormat("EEEE d MMMM yyyy"); //version 2
String[] days = new String[maxDayCount]; //limits the number of days to print out(ordinarily h)
now.add(Calendar.DAY_OF_YEAR, day + 1); //Increments from test count + 1 due to count starting at 0 (would be today). Increments the date to get from today.
int DayOfWeek = now.get(Calendar.DAY_OF_WEEK);
boolean WorkingDayCheck = ((DayOfWeek >= Calendar.MONDAY) && (DayOfWeek <= Calendar.FRIDAY));
if(WorkingDayCheck) {
days[day] = format.format(now.getTime());
} else {
//
}
now.add(Calendar.DAY_OF_MONTH, 1);
System.out.println("-----------Day " + day + ": " + String.valueOf(days[day])); //v2: print out each line
}//END OF METHOD: date
The idea is that I have an iteration elsewhere which passes the day number to this method in order for this to use that number to then print out the date. I am now back to what I was with originally before trying a load of things which at the moment with the check I am doing with the WorkingDayCheck boolean the print out is of course returning null when the weekend days come about.
Any ideas chaps?
Thanks for your time.
I think this will solve your problem.
First, why do you define the array days each time you enter the method then you populate only one value in it?
Your String[] days = new String[maxDayCount]; should be a member variable not a local variable. So initialize this array outside this method.
Also initialize another int that represent the last empty location in your array. (defaults to 0)
public class Foo {
int maxDayCount = 365;
String[] days = new String[maxDayCount];
int finalIndex = 0;
public static void date(int day) {
now = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("EEEE d MMMM yyyy");
String[] days = new String[maxDayCount]; //limits the number of days to print out(ordinarily h)
now.add(Calendar.DAY_OF_YEAR, day + 1); //Increments from test count + 1 due to count starting at 0 (would be today). Increments the date to get from today.
int DayOfWeek = now.get(Calendar.DAY_OF_WEEK);
boolean WorkingDayCheck = ((DayOfWeek >= Calendar.MONDAY) && (DayOfWeek <= Calendar.FRIDAY));
if(WorkingDayCheck) {
days[finalIndex++] = format.format(now.getTime());
System.out.print("(" + (finalIndex - 1) + ")" + String.valueOf(days[finalIndex - 1]))
} else {
//
}
}
public static void main(String[]args) {
int day = 0;
while(finalIndex != maxDaysCount) {
date(day++);
}
}
}
Now your days array will be populated with working days only in their respective indices. For example in days[0] will be Friday then days[1] will be Saturday and so on since you have a pointer finalIndex that is independent of the value of day that is input to your method from the iteration.
If I get your problem correctly you want to do somewhat like following,
Working Day #1 = 0 Week + 1 Day = 1st Day
..
Working Day #5 = 0 Week + 5 Days = 5th Day
Working Day #6 = 1 Week + 1 Day = 8th Day
..
Working Day #10 = 1 Week + 5 Days = 12th Day
And then print the 1st,2nd,3rd calendar day of the year.
If that is the case you can try finding the calendar day from working day like something,
int div = day/5;
int rem = day%5;
int calendarDay = 0;
if(day>5){
if(rem == 0)
calendarDay = (div-1)*7 + 5;
else
calendarDay = div*7 + rem;
}else
calendarDay = day;
And then find the Calendar day for that date like
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.DAY_OF_YEAR, day);
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.ENGLISH);
formatter.format("%tD", calendar);
System.out.println(sb);
The code is not a solution, but I guess it points to where you want to go.
Having played around with the code I have achieved what I was after now with:
public static String getDate4(int day) {
now = Calendar.getInstance();
//SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");//version 1
SimpleDateFormat format = new SimpleDateFormat("EEEE d MMMM yyyy"); //version 2
now.add(Calendar.DAY_OF_YEAR, day + 1); //Increments from test count + 1 due to count starting at 0 (would be today). Increments the date to get from today.
int DayOfWeek = now.get(Calendar.DAY_OF_WEEK);
boolean WorkingDayCheck = ((DayOfWeek >= Calendar.MONDAY) && (DayOfWeek <= Calendar.FRIDAY));
if(WorkingDayCheck) {
days[finalIndex++] = format.format(now.getTime());
return "\n(" + (finalIndex - 1) + ") " + String.valueOf(days[finalIndex - 1]);
} else {
now.add(Calendar.DATE, 2); //advance dates by two
dayCount = dayCount + 2; //Increase the day count by 2 to ensure that later dates are also incremented to avoid duplication i.e. Monday(Sat), Tuesday(Sun), Monday, Tuesday, Wed...
days[finalIndex++] = format.format(now.getTime());
return "\n(" + (finalIndex - 1) + ") " + String.valueOf(days[finalIndex - 1]);
}//END OF if else
}//END OF getDate4 method
I had to add and use an external dayCount (similar to the day int #Mohammed Osama used) separate from the count used in the mains methods iteration which I used previously to feed into this method and then when a weekend came up I incremented the date by 2 which is something I had experimented with before however the problem came when the weekend ended and it was back onto non weekend dates which ended up with:
Friday
Monday (previously Saturday)
Tuesday (previously Sunday)
Monday (weekend over, now back onto Monday) <--- Issue here and onwards
Tuesday
This is where the new dayCount came in which is now fed into this method simply as:
//Main method
//Iteration code start
getDate4(dayCount++);
//Iteration end
Incrementing this by 2 each time a weekend was encountered pushed the later dates to their appropriate position therefore now I am getting what I was always after being:
Friday
Monday (previously Saturday) <-Pushed ahead by 2 dates to Monday
Tuesday (previously Sunday) <-Pushed ahead by 2 dates to Tuesday
Wednesday (previously Monday) <-Pushed ahead 2 dates to Wednesday due to weekends incrementing the dayCount by 2
Thursday <--- etc. etc.
Thanks a lot for the help folks, can move on now finally :>
I need to create a method for a program that accepts the date and if valid will add all the days from 01/01/xx to the date in the that year, eg 10/1/1999 will display "day 274 in 1999". I have the following code below, but its not adding the correct values. Not sure what I am doing wrong.
public static int dayNumber(int day, int month, int year){
int daysInMonth = 0;
int days = 0;
boolean leapYear = isLeapYear(year);
for(int i = 1; i <= month; i++){
switch(month){
case 1: daysInMonth += 31;
case 2: if(leapYear)
daysInMonth += 29;
else
daysInMonth += 28;
case 3: daysInMonth += 31;
case 4: daysInMonth += 30;
case 5: daysInMonth += 31;
case 6: daysInMonth += 30;
case 7: daysInMonth += 31;
case 8: daysInMonth += 31;
case 9: daysInMonth += 30;
case 10: daysInMonth += 31;
case 11: daysInMonth += 30;
case 12: daysInMonth += 31;
break;
default:
break;
}
while(month <= 12){
days += daysInMonth + day;
month++;
}
}
return days;
}
You need to terminate each case with a break:
case 1: daysInMonth += 31;
break;
case 2: if(leapYear)
daysInMonth += 29;
else
daysInMonth += 28;
break;
case 3: daysInMonth += 31;
break;
and so on.
Without this, statements in a switch fall through.
Additionally, your loop variable is i and you switch on month (but then modify month in another, nested, loop).
There is really no need for a loop here... This should do the trick:
days = day
days += (month-1)*30;
days += (month)/2; // every odd month until July has 31 days
days += (month >= 8 && month % 2 == 1) ? 1 : 0; // so if we have august or later and in an even month, add 1 day
if (month > 2) {
days -= (isLeapYear(year)) ? 1 : 2;
}
Just read your comment about this being exercise for school, so I'll better explain my code a little bit more.
First, we assume every month just has 30 days.
This, of course, is incorrect - every second month, starting with January, has 31. SO we're calculating how many month with 31 days we had so far. As it's the odd month (at least until August) that have the 31 days, we're dividing the month by two (remember - integer division, we'll get floor(month/2)) to get the number of month that have passed and had 31 days.
This is still incorrect, as starting with August, we have another day to add - our previous calculation yields one month with 31 days less than we really had. So we just add that one day if an even number of month has passed (we can tell this by dividing month by two and looking at the leftover, this is called "modulo division" and written "month % 2").
Finally, we're going for February. If February has passed (=we are in march or later) we just subtract two days - or one if it's a leap year. I used a so called "ternary statement" here (the ... ? ... : ... thing). Basically it's short for if (isLeapYear(year)) { days -= 1; } else { days -= 2; }
This question already has answers here:
Excluding Dates from Print Loop
(2 answers)
Closed 10 years ago.
I have almost completed my code; however, instead of eliminating solely the dates which fall on Friday and also happen to be the 13th day of the month, it has eliminated every 13th submission. I thought that:
int friday = ((startingDayOfWeek+dayOfYear) % 7);
if (dayOfYear != 13 && friday != 5)
System.out.println(month + "/" + dayOfYear);
dayOfYear++;
Would work, but it is eliminating them all. I understand that there are easier ways to accomplish this; however, I am required to do it in this manner. Here is the full code:
public class LoopDate {
public static void main(String[] args) {
//Denotes that Tuesday is the first day of 2013
int startingDayOfWeek = 2;
int year = 2013;
int numDays = 0;
for (int month = 1; month <= 12; month++) {
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if (((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0))
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
int dayOfYear = 1;
while (dayOfYear <= numDays)
{
int friday = ((startingDayOfWeek+dayOfYear) % 7);
if (dayOfYear != 13 && friday != 5)
System.out.println(month + "/" + dayOfYear);
dayOfYear++;
}
}
}
}
Your boolean logic is wrong.
if (dayOfYear != 13 && friday != 5)
Should be:
if (dayOfYear != 13 || friday != 5)
You are doing the negative check of "is it friday the 13th". When converting a positive check into a negative check, you need to NOT the conditions (done), and flip the operators (OR becomes AND, AND becomes OR).
Also, when dealing with boolean logic like that, I usually give the segments meaningful names. It 'costs' a variable, but can save you countless hours later on!
boolean isFridayThe13th = (dayOfYear == 13 && friday == 5);
if (!isFridayThe13th) ...
This question already has answers here:
How to subtract X days from a date using Java calendar?
(11 answers)
Closed 7 years ago.
I want to subtract n days from the current date in Java.
How do I do that?
You don't have to use Calendar. You can just play with timestamps :
Date d = initDate();//intialize your date to any date
Date dateBefore = new Date(d.getTime() - n * 24 * 3600 * 1000 l ); //Subtract n days
UPDATE
DO NOT FORGET TO ADD "l" for long by the end of 1000.
Please consider the below WARNING:
Adding 1000*60*60*24 milliseconds to a java date will once in a great while add zero days or two days to the original date in the circumstances of leap seconds, daylight savings time and the like. If you need to be 100% certain only one day is added, this solution is not the one to use.
this will subtract ten days of the current date (before Java 8):
int x = -10;
Calendar cal = GregorianCalendar.getInstance();
cal.add( Calendar.DAY_OF_YEAR, x);
Date tenDaysAgo = cal.getTime();
If you're using Java 8 you can make use of the new Date & Time API (http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html):
LocalDate tenDaysAgo = LocalDate.now().minusDays(10);
For converting the new to the old types and vice versa see: Converting between java.time.LocalDateTime and java.util.Date
I found this perfect solution and may useful, You can directly get in format as you want:
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -90); // I just want date before 90 days. you can give that you want.
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd"); // you can specify your format here...
Log.d("DATE","Date before 90 Days: " + s.format(new Date(cal.getTimeInMillis())));
Thanks.
for future use find day of the week ,deduct day and display the deducted day using date.
public static void main(String args[]) throws ParseException {
String[] days = { "Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday" };
SimpleDateFormat format1 = new SimpleDateFormat("dd/MM/yyyy");
Date dt1 = format1.parse("20/10/2013");
Calendar c = Calendar.getInstance();
c.setTime(dt1);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
long diff = Calendar.getInstance().getTime().getTime() ;
System.out.println(dayOfWeek);
switch (dayOfWeek) {
case 6:
System.out.println(days[dayOfWeek - 1]);
break;
case 5:
System.out.println(days[dayOfWeek - 1]);
break;
case 4:
System.out.println(days[dayOfWeek - 1]);
break;
case 3:
System.out.println(days[dayOfWeek - 1]);
break;
case 2:
System.out.println(days[dayOfWeek - 1]);
break;
case 1:
System.out.println(days[dayOfWeek - 1]);
diff = diff -(dt1.getTime()- 3 );
long valuebefore = dt1.getTime();
long valueafetr = dt1.getTime()-2;
System.out.println("DATE IS befor subtraction :"+valuebefore);
System.out.println("DATE IS after subtraction :"+valueafetr);
long x= dt1.getTime()-(2 * 24 * 3600 * 1000);
System.out.println("Deducted date to find firday is - 2 days form Sunday :"+new Date((dt1.getTime()-(2*24*3600*1000))));
System.out.println("DIffrence from now on is :"+diff);
if(diff > 0) {
diff = diff / (1000 * 60 * 60 * 24);
System.out.println("Diff"+diff);
System.out.println("Date is Expired!"+(dt1.getTime() -(long)2));
}
break;
}
}
As #Houcem Berrayana say
If you would like to use n>24 then you can use the code like:
Date dateBefore = new Date((d.getTime() - n * 24 * 3600 * 1000) - n * 24 * 3600 * 1000);
Suppose you want to find last 30 days date, then you'd use:
Date dateBefore = new Date((d.getTime() - 24 * 24 * 3600 * 1000) - 6 * 24 * 3600 * 1000);