Calendar.set not changing Calendar variables - java

I've been working on a program for my Computer Programming class and I'm having a little trouble. Truthfully, I'm on the verge of insanity...
Its a calendar program and the part I'm having trouble with is the Calendar object in java. Here is my code for one of methods:
public static void calendarGet(){
String md = getInput("What date would you like to look at?(mm/dd)");
int slash = md.indexOf('/');
MDFromDate(md);
cal.set(cal.MONTH, MONTH - 1);
cal.set(cal.DATE, DAY);
TARGET_DAY = DAY;
MAX_DAY = cal.getActualMaximum(cal.DAY_OF_MONTH);
WEEKS_IN_MONTH = MAX_DAY / 7;
System.out.println(cal.MONTH + 1);
System.out.println(cal.DAY_OF_MONTH);
System.out.println(cal.getTime());
drawMonth(cal.MONTH);
}
And the output for this is:
What date would you like to look at?(mm/dd)12/12
3
5
Wed Dec 12 22:47:32 PST 2018
As you can see, if I use getTime(); it returns the right month and day but cal.MONTH and cal.DAY_OF_MONTH do not.
Also, when I use the debugger and look in cal, none of the variables had changed.
I'm incredibly confused, I would appreciate some help! :D
EDIT:
public static String getInput(String prompt){
System.out.print(prompt);
Scanner inScan = new Scanner(System.in);
return inScan.nextLine();
}
public static void MDFromDate(String md){
Scanner getMD = new Scanner(md).useDelimiter("/");
MONTH = getMD.nextInt();
DAY = getMD.nextInt();
}

So...
System.out.println(cal.MONTH + 1);
System.out.println(cal.DAY_OF_MONTH);
is printing the constant values assigned to Calendar.MONTH and Calendar.DAY_OF_MONTH, this are not the values contained within the Calendar instance, they are simply values you can use to set/get values of the Calendar
So, if instead we use Calendar#get, for example...
Calendar cal = Calendar.getInstance();
int month = 12;
int day = 12;
cal.set(cal.MONTH, month - 1);
cal.set(cal.DATE, day);
System.out.println(cal.get(Calendar.MONTH));
System.out.println(cal.get(Calendar.DATE));
It will print...
11
12
But wait, why 11, because the months are zero indexed (ie January is 0)
Part of the confusion is down to the fact that you're not using the standard coding conventions for the Java Language, which states variable names which all all uppercase (MONTH/DAY) are constants, which they aren't in your code
And, yes, as I'm sure some is bound to point out, you shouldn't be using Calendar but instead the newer java.time API, but if your teacher wants you to use it, who are we to contradict them :/

In a very well-explained answer MadProgrammer asks:
And, yes, as I'm sure some is bound to point out, you shouldn't be
using Calendar but instead the newer java.time API, but if your
teacher wants you to use it, who are we to contradict them :/
I am taking the chance. If only for other readers that are not under the same restrictions. Teachers are different. When I was teaching, I certainly appreciated whenever students found a different solution from what I had imagined. You know your teacher better, so I hope you know what is right in your situation, I certainly don’t.
private static final DateTimeFormatter monthDayFormatter
= DateTimeFormatter.ofPattern("M/d");
public static void calendarGet(){
String md = getInput("What date would you like to look at?(mm/dd)");
LocalDate date = MonthDay.parse(md, monthDayFormatter)
.atYear(Year.now(ZoneId.of("America/Los_Angeles")).getValue());
int targetDay = date.getDayOfMonth();
int maxDay = date.lengthOfMonth();
System.out.println(date.getMonth());
System.out.println(date.getDayOfMonth());
}
When I entered 04/05, this printed
APRIL
5
IMHO the code using java.time is clearer to read and what should be taught in schools.

Related

Java: How can I create method that works on my date class

I have a date class and it has the following
public class Date {
public int month;
public int day;
public int year;
public Date(int m, int d, int y)
{
month = m;
day = d;
year = y;
}
public Date increase(int numberOfDays)
{
day += numberOfDays;
return this;
}
My question is what is the easiest way to do increasing of number of days to that given instance of Date? Like for example I have a created an instance of new Date(4,20,2016).increase(30); which would increase the given date addition 30 days. That would be sometime in May 19 I think. The method above should work if it's less than the max day of the month. But I haven't figure out how to do the calculation including the month and year. Like I added 365 days to that date would be 4/20/2017. Just an idea would be helpful. Thanks
use Java Calendar object instead. https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE, 30); // add 30 days
date = cal.getTime();
using jcalendar you can add the dates try this example
Implementing this yourself is a suprisingly tricky task. More so since you are storing your Date as a separate month, year and day. You would have to store information about the number of days in every month, along with information about leap years. In short, trying to re-implement Date is not easy.
One solution to storing a "day, month, year" date before Java 8 came along was to use Joda. Using Joda's LocalDate class, you can do:
LocalDate date = LocalDate.now();
date = date.plusDays(30);
This functionality is now available in Java 8's java.time package, using the same LocalDate class name. Take a look at the source code for either package to see how it's implemented.
In short, LocalDate.plusDays() first converts the "month, day, year" date to a single number of days since the "epoch", using an algorithm that's around twenty lines long. Then, it adds the requested number of days to that number. Finally, it converts that number back to a "day, month, year" using another algorithm that's even longer.

"is this date the third thursday of the month?" - Java Library?

I've got a few dozen backlog requests in the pipeline like
'I need this functionality to run on the third Thursday of every month, and the first Wednesday of every other month...'
I've already got a function that runs every day, i just need the: isThirdSundayOfMonth(date) bit to append onto then end.
The less time I spend considering the nuances of the Gregorian calendar and timezones, the better my life is.
Anyone know a Java library that simplifies this sort of calculation? No xml config or frameworks or anything. Just a .Jar and a documented, readable API would be perfect.
Any help would be much appreciated.
Complete overview:
In Java-8 (new standard):
LocalDate input = LocalDate.now(); // using system timezone
int ordinal = 3;
DayOfWeek weekday = DayOfWeek.SUNDAY;
LocalDate adjusted =
input.with(TemporalAdjusters.dayOfWeekInMonth(ordinal, weekday));
boolean isThirdSundayInMonth = input.equals(adjusted);
In Joda-Time (popular 3rd-party-library):
LocalDate input = new LocalDate(); // using system timezone
int ordinal = 3;
int weekday = DateTimeConstants.SUNDAY;
LocalDate start = new LocalDate(input.getYear(), input.getMonthOfYear(), 1);
LocalDate date = start.withDayOfWeek(weekday);
LocalDate adjusted = (
date.isBefore(start))
? date.plusWeeks(ordinal)
: date.plusWeeks(ordinal - 1);
boolean isThirdSundayInMonth = input.equals(adjusted);
Using java.util.GregorianCalendar (old standard):
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
GregorianCalendar input = new GregorianCalendar();
int ordinal = 3;
int weekday = Calendar.SUNDAY;
GregorianCalendar start =
new GregorianCalendar(input.get(Calendar.YEAR), input.get(Calendar.MONTH), 1);
int dow = start.get(Calendar.DAY_OF_WEEK); // Sun=1, Mon=2, ...
int delta = (weekday - dow);
if (delta < 0) {
delta += 7;
}
start.add(Calendar.DAY_OF_MONTH, delta + (ordinal - 1) * 7);
String comp1 = sdf.format(input.getTime());
String comp2 = sdf.format(start.getTime());
boolean isThirdSundayInMonth = comp1.equals(comp2);
Even with the ugliest library a solution is possible ;-) I have used a string comparison in order to get rid of any timezone effects or time-of-day-parts including milliseconds. A field-wise comparison based only on year, month and day-of-month is also a good idea.
Using Time4J (my own 3rd-party-library):
PlainDate input =
SystemClock.inLocalView().today(); // using system timezone
Weekday weekday = Weekday.SUNDAY;
PlainDate adjusted =
input.with(PlainDate.WEEKDAY_IN_MONTH.setToThird(weekday));
boolean isThirdSundayInMonth = input.equals(adjusted);
The canonical library for all things date and time related is Joda Time. Adopt that and purge all the standard java classes like Date, Calendar, etc.
It will make your life much better.
As for "How do I use joda-time to find the third Thursday of the month", there's a stackoverflow answer for that already. I'd suggest using the code that the question asker posted and then the question "is it now the third Thursday of the month" is answered by:
LocalDate today = new LocalDate();
if (today.equals(calcDayOfWeekOfMonth(DateTimeConstants.THURSDAY, 3, today))) {
// do special third-Thursday processing here
}

Java Calendar always shows the same time

Below is my code.
public class TestCalendar {
public static void main(String[] args){
int unique_id = Integer.parseInt("" + Calendar.HOUR + Calendar.MINUTE
+ Calendar.SECOND);
System.out.println(unique_id);
}
}
Calendar.HOUR is supposed to give me
public static final int HOUR Field number for get and set indicating the hour of the morning or
afternoon. HOUR is used for the 12-hour clock (0 - 11). Noon and midnight are represented by 0, not
by 12. E.g., at 10:04:15.250 PM the HOUR is 10.
It doesnt matter how many times I run this code, it always gives me the same unique_id. (101213) and my local time on my machine is 1:30pm. What am I doing wrong here?
Thanks.
Your code is just concatenating constants, that the Calendar defines to identify some of it's fields. To get values of these fields, call Calendar.get() and pass the constant identifier as an argument:
public class TestCalendar {
public static void main(String[] args){
Calendar c = Calendar.getInstance();
int unique_id = Integer.parseInt("" + c.get(Calendar.HOUR) + c.get(Calendar.MINUTE)
+ c.get(Calendar.SECOND));
System.out.println(unique_id);
}
}
The above would work, but the result will be far from unique ID.
To get an ID uniquely identifying a point in time (with the precision of milliseconds), consider Calendar.getTimeInMillis().
Calendar.HOUR, Calendar.MINUTE and Calendar.SECOND are public static int field of the Calendar class. Their value is
CALENDAR.HOUR: 10
CALENDAR.MINUTE: 12 and
CALENDAR.SECOND: 13.
Your String concatenation is just appending this values. To read from a Calendar you could so something similar to
calendar.get(Calendar.HOUR);
calendar.get(Calendar.MINUTE);
I am not sure what is requirement but if you want system time then may be you can use this "System.currentTimeMillis()"
Calendar.HOUR (or MINUTE, SECOND) is just an indicator that indicates which field we want to extract from the Calendar instance, not the value, i.e. we want to 'extract HOUR from the calendar object' like below:
Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY); // in 24-hours,
// or c.get(Calendar.HOUR) in 12-hours.
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
int weekday = c.get(Calendar.DAY_OF_WEEK);
int weekOfYear = c.get(Calendar.WEEK_OF_YEAR);
For those who are still having some problems with this, like I did, especially when you want to print multiple times you may need to to use new like follows:
System.out.println(""+new GregorianCalendar().get(Calendar.HOUR_OF_DAY)+":"+new GregorianCalendar().get(Calendar.MINUTE)+":"+new GregorianCalendar().get(Calendar.SECOND)+":"+new GregorianCalendar().get(Calendar.MILLISECOND));

How do I determine time passed between two Calendar Objects in Java?

What is the best way to count the amount of time between two Calendar dates in java. I am writing a method that determines the number of months that pass between two dates and returns a boolean based on a predefined term of months. This is my code(does not work correctly).
This code always returns false. Also this code does not take into account the number of days passed. This could be a problem if the start date is at the end of a month. Is there not a simple compareTo method?
private boolean hasMatured()
{
Calendar now = Calendar.getInstance();
Calendar start = (Calendar) super.dateOpened.clone();
int nowYear = now.get(Calendar.YEAR);
int nowMonth = now.get(Calendar.MONTH);
int startYear = start.get(Calendar.YEAR);
int startMonth = start.get(Calendar.MONTH);
int monthsElapsed = (nowYear - startYear) * 12 + (nowMonth - startMonth);
return monthsElapsed>PERIOD_IN_MONTHS;
}
int nowYear = now.get(Calendar.YEAR);
int nowMonth = now.get(Calendar.MONTH);
int startYear = now.get(Calendar.YEAR);
int startMonth = now.get(Calendar.MONTH);
int monthsElapsed = (nowYear - startYear) * 12 + (nowMonth - startMonth);
I would strongly recommend Joda Time for all date-related stuff in Java. It has a much cleaner and more intuitive API, togather with the concepts of intervals between dates etc.
The code looks fine expect from one major caveat: Calendar is mutable.
So, instead of
Calendar start = super.dateOpened;
you should have done
Calendar start = (Calendar) super.dateOpened.clone();
otherwise the changes get reflected in dataOpened which may cause unexpected side-effects.
Am I missing something? There is a compareTo() in Calendar, as well as other useful stuff...
How about:
Calendar now = Calendar.getInstance();
now.add(Calendar.MONTH, -PERIOD_IN_MONTHS);
return super.dateOpened.before(now);
Subtract X months from today, and see if the start date is still before that date. If it is, then X months must have passed.

Stuck on testing a method

I am doing some table testing in word, all of the JUnits are done but i am having trouble testing a method - as i am the tester in this project and not the coder i am struggling to understand what is actually correct or not
public GregorianCalendar calcDeparture(String date, String time) {
String[] calDate = new String[3];
String[] calTime = new String[2];
calDate[0] = (date.substring(0, 2)); //Dat
calDate[1] = date.substring(2, 5); //Month
calDate[2] = "20" + date.substring(5, 7); //Year
calTime = time.split(":");
//Adds the year, month and day and hour and minute from the above splited arrays
int year = Integer.parseInt(calDate[2]);
int month = monthToInt(calDate[1]);
int day = Integer.parseInt(calDate[0]);
int hour = Integer.parseInt(calTime[0]);
int minute = Integer.parseInt(calTime[1]);
GregorianCalendar newDeparture = new GregorianCalendar(year, month, day, hour, minute, 0);
return newDeparture;
}
This is the method I am testing. If i pass it the values of "01AUG07 "14:40" i get a gregorian calander back but i don't know if the values inside of it are correct so i can't tick the passed or failed box. What i get back in the BlueJ object inspector is a load of really long numbers :D
can i get some help please
thanks
I suggest to check all the relevant values of the calendar at the same time using a SimpleDateFormat() like so:
SimpleDateFormat f = new SimpleDateFormat ("yyyy-MM-dd HH:mm");
String s = f.format (calcDeparture(yourDate, yourTime));
assertEquals ("2007-08-01 14:40", s);
Now call your method with odd dates (like 31.12.2999, August 45th, February 29th 2001, etc) to see what you get and how you should handle errors.
BlueJ? Consider using an IDE, not an educational software
The method is terribly written - working with dates using a strictly-formatted String is wrong.
Calendar (which is the supertype of GregorianCalendar) has the get method, which you can use like:
Calendar calendar = calcDeparture(yourDate, yourTime);
int day = calendar.get(Calendar.DAY_OF_YEAR);
int moth = calendar.get(Calendar.MONTH); //this is 0 based;
and so on
Why can you just not use the standard getters to check the individual fields, along the lines of:
Calendar cal = calcDeparture("01AUG07", "14:40");
if (cal.get(Calendar.YEAR) != 2007) { ... }

Categories