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) { ... }
Related
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.
This question already has answers here:
Calculating days between two dates with Java
(16 answers)
Closed 5 years ago.
I've got a list of dates in format "yyyy-MM-dd", I'd like to have a number of days between my today date "2017-04-15" and first date from list which is higher than mine today date.
I am assuming that your events are not sorted by date. I am assuming that you can use Java 8. This is one of the tasks that have become so much easier with the java.time classes introduced in Java 8 (and backported to Java 6 and 7).
Use LocalDate.now() to get today’s date.
Iterate through your events, all the time keeping track of the closest future event date. For each event use LocalDate.parse() to convert the event’s date to a LocalDate. The 1-arg parse method fits your format. Compare with today’s date and with the earliest future event date encountered so far; if between, store as the new closest date. Use isAfter() and/or isBefore for the comparisons.
After your loop, you will either know the date or you will know that there are no future events at all. In the former case, use ChronoUnit.DAYS.between() to get the number of days from the current date to the event date.
Solution 1
If you are using joda library, then it will be easy, you can use Days.daysBetween :
Date startDate = ...;
Date endDate = ...;
int nbrDays = Days.daysBetween(new LocalDate(startDate), new LocalDate(endDate)).getDays();
Solution 2
Date startDate = ...;
Date endDate = ...;
Calendar cal = Calendar.getInstance();
cal.setTime(startDate);
int day1 = cal.get(Calendar.DAY_OF_MONTH);
cal.setTime(endDate);
int day2 = cal.get(Calendar.DAY_OF_MONTH);
int nbrDays = day1 - day2;
System.out.println(nbrDays);
You have to import :
import java.util.Calendar;
import java.util.Date;
Solution 3
If your dates are in this format "yyyy-MM-dd" so you can have two dates like this :
String date1 = "1991-07-03";
String date2 = "2017-04-15";
What you should to do, split your dates with - :
String spl1[] = date1.split("-");
String spl2[] = date2.split("-");
Calculate the difference between the two dates :
int year1 = Integer.parseInt(spl1[0]);
int month1 = Integer.parseInt(spl1[1]);
int days1 = Integer.parseInt(spl1[2]);
int year2 = Integer.parseInt(spl2[0]);
int month2 = Integer.parseInt(spl2[1]);
int days2 = Integer.parseInt(spl2[2]);
//make some calculation and in the end you can get the diffidence, this work i will let it for you.
This should solve your problem.
SimpleDateFormat myDateFormat = new SimpleDateFormat("yyyy-MM-dd");
List<Date> dateList = new ArrayList<Date>();
try {
beforeDate = myDateFormat.parse("2016-01-13");
dateList.add(myDateFormat.parse("2016-01-10"));
dateList.add(myDateFormat.parse("2016-01-11"));
dateList.add(myDateFormat.parse("2016-01-12"));
dateList.add(myDateFormat.parse("2016-01-19"));
dateList.add(myDateFormat.parse("2016-01-20"));
dateList.add(myDateFormat.parse("2016-01-21"));
} catch (ParseException e) {
System.out.println(e.getMessage());
}
//add here
boolean check = true;
for(int i = 0; check && i < dateList.size();i++){
if(dateList.get(i).after(beforeDate)){
afterDate = dateList.get(i);
check = false;
}
}
System.out.println(beforeDate+" "+afterDate);
long days = ChronoUnit.DAYS.between(LocalDate.parse(myDateFormat.format(beforeDate)), LocalDate.parse(myDateFormat.format(afterDate)));
if(days>0){
System.out.println(days);
}else{
System.out.println(0-days);
}
if you want to sort dateList then want to get afterDate then use this code after addition of date elements in dateList
Collections.sort(dateList,new Comparator<Date>() {
#Override
public int compare(Date o1, Date o2) {
return o1.compareTo(o2);
}
});
This will allow you to sort dates in ascending order..
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
}
In my app I´m saving when I last updated some data from my server.
Therefore I used:
long time = Calendar.getInstance().getTimeInMillis();
Now I want that the data is updated twice a year at 03.03 and 08.08.
How can I check wheater one of these two date boarders were crossed since last update?
Change them to time in mseconds and compare:
Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, Calendar.MARCH);
c.set(Calendar.DAY_OF_MONTH, 3);
long time2= c.getTimeInMillis();
c.set(Calendar.MONTH, Calendar.AUGUST);
c.set(Calendar.DAY_OF_MONTH, 8);
long time3= c.getTimeInMillis();
if(time>time2){
//Logic
if(time>time3){
//Logic
}
}
There is something very important which took me a while to figure it out and can be very helpful to people out there, if you are looking for an answer to any of the following questions this is for you:
Why is my date not showing correctly?
Why even when I set the time manually it is not showing right?
Why is the month and the year showing one day less than the one that I set?
For some reason Java sorts the months values like an array, what I mean is that for Java January is 0 and DECEMBER is 11. Same happens for the year, if you set December as month 12 and year as 2012, and then try to do a "system.out.println" of the month and the year, it will show my month as January and the year as 2013!!
so what should you do?
Calendar cal = new GregorianCalendar();
cal.set(2012, 11, 26); // the date I want to input is 26/12/2012 (for Java, 11 is December!)
NOW WHAT IS THE CORRECT WAY TO GET THAT DATE TO SEE IT ON THE SCREEN?
if you try to "system.out.println of yourCalendar.DATE, yourCalendar.MONTH and yourCalendar.YEAR," THAT WILL NOT SHOW YOU THE RIGHT DATE!!!!
If you want to display the dates you need to do the following:
System.out.println (calact.get (calact.DATE));
// displays day
System.out.println (calact.get (calact.MONTH)+1);
//add 1 remember it saves values from 0-11
System.out.println (calact.get (calact.YEAR));
// displays year
NOW IF YOU ARE HANDLING STRINGS THAT REPRESENT DATES, OR....
IF YOU NEED TO COMPARE DATES BETWEEN RANGES , LET'S SAY YOU NEED TO KNOW IF DATE "A" WILL TAKE PLACE WITHIN THE NEXT 10 DAYS....THIS....IS.....FOR....YOU!!
In my case I was working with a string that had format "15/07/2012", I needed to know if that date would take place within the next 10 days, therefore I had to do the following:
1 get that string date and transform it into a calendar ( StringTokenizer was used here )
this is very simple
StringTokenizer tokens=new StringTokenizer(myDateAsString, "/");
do nextToken and before returning the day, parse it as integer and return it.
Remember for month before returning substract 1.
I will post the code for the first you create the other two:
public int getMeD(String fecha){
int miDia = 0;
String tmd = "0";
StringTokenizer tokens=new StringTokenizer(fecha, "/");
tmd = tokens.nextToken();
miDia = Integer.parseInt(tmd);
return miDia;
}
2 THEN YOU CREATE THE CALENDAR
Calendar cal = new GregorianCalendar(); // calendar
String myDateAsString= "15/07/2012"; // my Date As String
int MYcald = getMeD(myDateAsString); // returns integer
int MYcalm = getMeM(myDateAsString); // returns integer
int MYcaly = getMeY(myDateAsString); // returns integer
cal.set(MYcaly, MYcalm, MYcald);
3 get my current date (TODAY)
Calendar curr = new GregorianCalendar(); // current cal
calact.setTimeInMillis(System.currentTimeMillis());
4 create temporal calendar to go into the future 10 days
Calendar caltemp = new GregorianCalendar(); // temp cal
caltemp.setTimeInMillis(System.currentTimeMillis());
caltemp.add(calact.DAY_OF_MONTH, 10); // we move into the future
5 compare among all 3 calendars
here basically you ask if the date that I was given is for sure taking place in the future AND (&&) IF the given date is also less than the future date which had 10 days more, then please show me "EVENT WILL TAKE PLACE FOR SURE WITHIN THE NEXT 10 DAYS!!" OTHERWISE SHOW ME:
"EVENT WILL NOT TAKE PLACE WITHIN THE NEXT 10 DAYS".
if((cal.getTimeInMillis() > curr.getTimeInMillis()) && (cal.getTimeInMillis()< curr.getTimeInMillis()))
{ System.out.println ("EVENT WILL TAKE PLACE FOR SURE WITHIN THE NEXT 10 DAYS!!");}
else
{ System.out.println ("EVENT WILL *NOT* TAKE PLACE WITHIN THE NEXT 10 DAYS");}
ALRIGHT GUYS AND GIRLS I HOPE THAT HELPS. A BIG HUG FOR YOU ALL AND GOOD LUCK WITH YOUR PROJECTS!
PEACE.
YOAV.
If the comparison should involve only the year, month and day then you can use this method for check if c1 is before c2. Ugly, but works.
public static boolean before(Calendar c1, Calendar c2){
int c1Year = c1.get(Calendar.YEAR);
int c1Month = c1.get(Calendar.MONTH);
int c1Day = c1.get(Calendar.DAY_OF_MONTH);
int c2Year = c2.get(Calendar.YEAR);
int c2Month = c2.get(Calendar.MONTH);
int c2Day = c2.get(Calendar.DAY_OF_MONTH);
if(c1Year<c2Year){
return true;
}else if (c1Year>c2Year){
return false;
}else{
if(c1Month>c2Month){
return false;
}else if(c1Month<c2Month){
return true;
}else{
return c1Day<c2Day;
}
}
}
used compareTo method ..and this returns integer value .if returns -ve the days before in current date else return +ve the days after come current date
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.