I am trying to set up part of a program that allows a person to view transactions of an account based on the date of the transaction. The user enters the month day and year to view transactions and that is compared to the date that is connected to a given transaction. I am having difficult writing the lines of code that determine if the date is equal
if(aBank.getAccounts().get(i).getTransaction().get(j).getTransDate().get(Calendar.MONTH).compareTo(month)==0){
if(aBank.getAccounts().get(i).getTransaction().get(j).getTransDate().get(Calendar.DAY_OF_MONTH).compareTo(day)==0){
if(aBank.getAccounts().get(i).getTransaction().get(j).getTransDate().get(Calendar.YEAR).compareTo(year)==0){
The error that I am receiving is "cannot invoke compareTo(int) on the primitive type int"
see full code below:
System.out.println("Enter the account number of the account that you want to view transactions for");
number=keyboard.nextLong();
System.out.println("Enter the month day and year of the date that the transactions were completed");
int month=keyboard.nextInt()-1;
int day=keyboard.nextInt();
int year=keyboard.nextInt();
found=false;
try{
for(int i=0;i<aBank.getAccounts().size();i++){
if (aBank.getAccounts().get(i).getAccountNumber().compareTo(number)==0){
found=true;
System.out.println("Below is a list of transactions completed on "+month+ "/" +day+ "/" +year);
for (int j=0;j<aBank.getAccounts().get(i).getTransaction().size();j++){
if(aBank.getAccounts().get(i).getTransaction().get(j).getTransDate().get(Calendar.MONTH).compareTo(month)==0){
if(aBank.getAccounts().get(i).getTransaction().get(j).getTransDate().get(Calendar.DAY_OF_MONTH).compareTo(day)==0){
if(aBank.getAccounts().get(i).getTransaction().get(j).getTransDate().get(Calendar.YEAR).compareTo(year)==0){
aBank.getAccounts().get(i).getTransaction().get(j).toString();
break;
}
}
}
}
For primitive values you can just use ==
aBank.getAccounts().get(i).getTransaction().get(j).getTransDate().get(Calendar.YEAR)==year
Just use:
aBank.getAccounts().get(i).getTransaction().get(j).getTransDate().get(Calendar.MONTH) == month
If all of the XYZ.getTransDate() returns Calendar, then
XYZ.getTransDate().get(SOMETHING) returns primitive int. Primitives do not have comapreTo method, just use ==
so instead of XYZ.getTransDate().get(MONTH).compareTo(month) == 0 use
XYZ.getTransDate().get(MONTH) == month
This should work:
Calendar transDate = aBank.getAccounts().get(i).getTransaction().get(j).getTransDate();
if (transDate.get(Calendar.YEAR) == year &&
transDate.get(Calendar.MONTH) == month &&
transDate.get(Calendar.DAY_OF_MONTH) == day) {
// do something
}
Even better if you use something like Apache Commons Lang:
if (DateUtils.isSameDay(aBank.getAccounts().get(i).getTransaction().get(j).getTransDate(),
Calendar.getInstance().set(year, month, day)) {
...
}
Related
I want to create a Java Program that takes a date as input (27,2,2019) and print out what day it was. I am just assuming the usage of Gregorian Calender only. The reference is 1,1,1 which is a Monday. I am unable to complete this. Can someone help me out please. I also took leap years to account. Also, in this project, I am not allowed to import any packages so I should do it normally.
public class sortday
{
public static void main (String [] args)
{
sortdayoftheyear(1,1,2019);
}
public static void sortdayoftheyear(int day, int month, int year)
{
final int [] months = {31,28,31,30,31,30,31,31,30,31,30,31};
{
final int monthnum = 12;
int totaldays=0;
int newmon = month-1; //find which month it is
int monthdays = months[newmon]; // find days of the month
for (int i = 1; i < year; i++)
{
if (i%100 != 0 && i%4 == 0 && i%400 == 0) //check for leap year
{
totaldays = i*366;
}
else
totaldays = i*365;
}
totaldays += (day) + (newmon*monthdays);
if (totaldays%7 == 4)
System.out.println("Sunday");
if (totaldays%7 == 5)
System.out.println("Monday");
if (totaldays%7 == 6)
System.out.println("Tuesday");
if (totaldays%7 == 0)
System.out.println("Wednesday");
if (totaldays%7 == 1)
System.out.println("Thursday");
if (totaldays%7 == 2)
System.out.println("Friday");
if (totaldays%7 == 3)
System.out.println("Saturday");
System.out.println("It had been " + totaldays + " since January 1,AD");
}
}
}
There seems to be more than one bug in your code. I have spotted:
Each time through your for loop you are assigning a new value to totaldays. In this way only the last time through the loop has any effect in the end. I believe you intended every iteration to contribute.
As yole said in a comment, newmon*monthdays is incorrect for the total number of days in the first newmon months of the year. I even think that for February 13 your are counting 13 + 1 * 28, which can’t be right. One suggestion is you loop through the months and add up their lengths.
If the entered year is a leap year, you are always counting 28 days in February. You want to count 29 sometimes. An auxiliary method to determine whether a year is a leap year would come in handy.
If your reference date of January 1, 1 is a Monday, I think you want to print this when the modulo operation in the end yields 1. You are printing Thursday in this case.
I can’t tell if there may be more.
Issues without functional consequences that you should nevertheless want to fix include:
You are not using the constant monthnum, so delete it.
You have a superfluous set of braces around the code piece from the mentioned constant down to System.out.println. Delete those too.
Get your indentation right so you and I can read your code.
When writing code for others to read (including Stack Overflow users), respect the naming conventions. Call the class SortDay or FindDayOfWeek. The method sortDayOfTheYear or printDayOfWeek.
public void askForDate(Scanner in) {
System.out.println("Please enter the date that the vehicle entered the car park in this format dd/mm/yyyy :");
String enteredDate = in.nextLine();
//This array will hold the 3 elements of which the date is made up of, day, month and year, and this method returns it.
String[] dateEnteredSplit = enteredDate.split("/");
//I am using the split method to seperate each number, which returns an array, so I am assigning that array to the dateEnteredSplit array.
//dateEnteredSplit = enteredDate.split("/");
//So now the first element holds the day, second the month, and the third element holds the year.
//System.out.println(Arrays.toString(dateEnteredSplit));
//Assigning each element and converting them to integers.
int day = Integer.parseInt(dateEnteredSplit[0]);
int month = Integer.parseInt(dateEnteredSplit[1]);
int year = Integer.parseInt(dateEnteredSplit[2]);
**System.out.println("day: " + day + " month: " + month + " year: " + year);**
//The loop will be entered if any of the values are wrong. which will use recursion to call this method again for a chance to enter the date again.
while (!(day >= 1 && day <= 31) || !(month >= 1 && month <= 12) || !(year > 1000 && year < 5000)) {
**System.out.println("day: " + day + " month: " + month + " year: " + year);**
//Im calling these methods to inform which one specifially was wrong so they know what they need to change.
this.setDay(day);
this.setMonth(month);
this.setYear(year);
dateEnteredSplit[0] = "0";
askForDate(in);
}
//I then assign any correct value into the object attribute because the while loop is either finished or not entered at all.
//No need to use setDay etc. here because the checks have been done above in the while loop.
this.day = day;
this.month = month;
this.year = year;
}
Ok that is a method in a class. It asks for input in the format dd/mm/yyyy
If the first time I input 12/1/1996 it works, but if I enter a wrong date for example like this first, 123/123/123 and the enter a correct date for example 12/1/1996, it still enters the loop.
After debugging, the first line that is bold, the values are different from the second line that is bold, its like the values are changing by their own.
What is the problem here? I have been trying to find out in the past 1 hour.
Thanks in advance!
The problem very likely is in the way you are trying to combine recursive and iterative approach to update values (there is a while loop, that call the function recursively, which may also trigger while loop in next level of call and the previous one will continue calling itself recursively and you will end up with just mess)
There is no real reason to do that recursively, I would do iterative only approach, something like this:
public void askForDate(Scanner in) {
System.out.println("Please enter the date that the vehicle entered the car park in this format dd/mm/yyyy :");
int day, month, year;
do { // We use do-while to get the first read without condition, although setting date to invalid value (like day = 0) and then running standard while loop will work just as fine
String[] dateEnteredSplit = in.nextLine().split("/");
//Assigning each element and converting them to integers.
day = Integer.parseInt(dateEnteredSplit[0]);
month = Integer.parseInt(dateEnteredSplit[1]);
year = Integer.parseInt(dateEnteredSplit[2]);
} while (!(day >= 1 && day <= 31) || !(month >= 1 && month <= 12) || !(year > 1000 && year < 5000));
// Now day month and year variables are set correctly and we can do stuff with it
}
If you insist or recursive approach, the correct way would be to call the function just once:
public void askForDate(Scanner in) {
System.out.println("Please enter the date that the vehicle entered the car park in this format dd/mm/yyyy :");
int day, month, year;
String[] dateEnteredSplit = in.nextLine().split("/");
//Assigning each element and converting them to integers.
day = Integer.parseInt(dateEnteredSplit[0]);
month = Integer.parseInt(dateEnteredSplit[1]);
year = Integer.parseInt(dateEnteredSplit[2]);
if (!(day >= 1 && day <= 31) || !(month >= 1 && month <= 12) || !(year > 1000 && year < 5000)) askForDate(in);
// You need to save day/month/year variables to other than local scope (like this.day = day)
// Otherwise it would just somewhere in recursion stack and you wouldn't be able to use it
}
Just to be complete, keep in mind that date string could be wrong in other way that just number out of range. What if user types 1. 2. 3456 or a/b/c or not even something very different like Hello
At your snippet of code would crash (either throw NumberFormatException when trying to parse non-integer or ArrayIndexOutOfBoundsException when accessing dateEnteredSplit array at element that doesnt exists (there are no '/' in 'Hello'))
Here is what happens. Wrong values on a first while loop iteration make a call to askForDate possible. You receive a second prompt and provide correct input. The second call of askForDate ends as expected. The execution returns again to a while loop, where you still have the first wrongly set values and the process starts again.
If you really do want to use recursion here, you should return a value from your function (dates or boolean flag) and check it in a while loop condition.
List of dates are as below (The list can be in any order):
3-Jan to 31-Mar, 2-Apr to 30-Jun, 1-Jul to 30-Sep, 4-Oct to 31-Dec
Current Date is: 19-Feb
Can someone please help me with the logic?
My approach is:
if(the given date should be greater than start date and less than end date){//this gives current quarter}else if(difference of the month of current date from the end date of each object should be less than or equal to 5)
i am hard coding the condition less than 5, which may break if in future the range of date will be of 4 months
Second approach is:
we can sort the list in ascending order and can get the current quarter index by comparing with current date and the next quarter will be of next index. But the complexity will be more.
I tried below code, but it gives only current quarter date. I am not able to get next quarter considering there would be only 3 objects and current date month is feb.
public static List getCurrentQtrOffr(List detail,Date currentDate) throws ParseException{
int currentQuarter = 9999, diff1;
int nextquarter = 9999, diff2;
Detail detail1;
Detail detail2;
Detail detail3 = null;
Detail detail4 = null;
Iterator<Detail> iterator = detail.iterator();
List<Detail> list = new ArrayList<Detail>();
while(iterator.hasNext()){
detail1 = iterator.next();
diff1 = getDiff(currentDate,detail1.startTime());
if(diff1>0){
if(iterator.hasNext()){
detail2 = iterator.next();
}else{
detail2 = null;
}
if(detail2 != null){
diff2 = getDiff(currentDate,detail2.startTime());
if(diff1 < diff2 ){
if(currentQuarter > diff1){
nextquarter = currentQuarter;
currentQuarter = diff1;
//how to assign detail3 before updating it with next minimum value, as if there will be only 3 object and flow comes in this if block then detail4 will be null
detail4=detail3;
detail3=detail1;
}else if(nextquarter > diff1){
nextquarter = diff1;
detail4=detail1;
}
}else{
if(currentQuarter > diff2){
nextquarter = currentQuarter;
currentQuarter = diff2;
detail4=detail3;
detail3=detail1;
}else if(nextquarter > diff2){
nextquarter = diff2;
detail4=detail1;
}
}
}else{
if(currentQuarter > diff1){
nextquarter = currentQuarter;
currentQuarter = diff1;
detail4=detail3;
detail3=detail1;
}else if(nextquarter > diff1){
nextquarter = diff1;
detail4=detail1;
}
}
}else{
System.out.println("skipped "+diff1);
}
}
list.add(detail3);
list.add(detail4);
return list;
}
If the periods are mutually exclusive (not overlapping) the you simply check for the first occurrence where:
The target is equal to or later than the start, and…
The target is before the stop.
This logic follows the Half-Open approach commonly used in date-time work where the beginning is inclusive while the ending is exclusive.
A shorter way of saying "the target is equal to or later than the start" is "not before start". The exclamation mark ! means not in Java syntax.
Boolean periodContainsTarget = ( ! target.isBefore( start ) ) && target.isBefore( stop ) ;
The above logic would be used with LocalDate if you meant date with a year. If you literally meant a month and day without a year, use the MonthDay class. The logic works for both.
Use Period class to represent the span of time between a pair of LocalDate objects. See Tutorial.
You might also find useful the Interval class in the ThreeTen-Extra project that supplements java.time.
I used this method to check id a date entered by the user is valid or not:
private boolean isThisDateValid(Date dateToValidate) {
Calendar cal = Calendar.getInstance();
if (dateToValidate == null) {
return false;
}
cal.setLenient(false);
cal.setTime(dateToValidate);
try {
cal.getTime();
} catch (Exception e) {
return false;
}
return true;
}
The problem is that when the user writes a wrong year (big year) it doesn't throw an exception example : 12/09/2016666
Should i check the sanity of the year field in a seperate method.
Even though it is far from the present, 2016666 is still a valid year. It's about 2 million years from now, so I can see why you might not want it in lots of contexts, but it would be strange for a date validator to suggest that it is not a legitimate date. It would really be an incorrect behavior.
If you want to do additional validation (such as ensuring that the year field does not exceed the current year) you would need to do that yourself and throw the proper exception.
I need to count the points of a chart for a duration picked by an user.
My chart is about logs, we need to know how many users are connected for every specified minutes while a specific duration. We don't want to use too many queries, so I work essentially with lists.
Dates are stored in String format as "yyyy-MM-dd HH:mm:ss".
My code works but is really too long to load:
old=ofy().load().type(Log.class).filter("site in",selectedSites).filter("license in",ofy().load().type(License.class).filter("name", name)).filter("date_out >=",datemin).filter("date_out <=",datemax).list();
Duration duration = new Duration(firstIn, lastDateOut); //Duration between two dates choosen by the user
int dimension=(int) ((duration.getStandardMinutes())/divideBy); //Number of abscissa points in the chart
DateTime[] dates=new DateTime[dimension+1]; //Init of the dates
int[] counts=new int[dimension+1]; //Init of the count table (count of logged users at the date
DateTime transfert=firstIn; //First date
for(int i=0;i<=dimension;i++){
counts[i]=0;
dates[i]=transfert.minusSeconds(transfert.getSecondOfMinute());
transfert=transfert.plusMinutes(divideBy);
for(Log log:old){
if((StaticMethods.toDateTime(log.getDate_in()).minusSeconds(StaticMethods.toDateTime(log.getDate_in()).getSecondOfMinute()).equals(dates[i]))
||((StaticMethods.toDateTime(log.getDate_in()).minusSeconds(StaticMethods.toDateTime(log.getDate_in()).getSecondOfMinute()).isBefore(dates[i]))
&&(StaticMethods.toDateTime(log.getDate_out()).minusSeconds(StaticMethods.toDateTime(log.getDate_out()).getSecondOfMinute()).isAfter(dates[i])))
||(StaticMethods.toDateTime(log.getDate_out()).minusSeconds(StaticMethods.toDateTime(log.getDate_out()).getSecondOfMinute()).equals(dates[i]))
){
counts[i]++;
}
}
GraphData nw=new GraphData(dates[i].toDate(), counts[i]);
}
I want to know if there is a possible less loading time (have read this and I need to know if there's similar way for approximate values).
you should order your data by Date_out value first, in ascending order. Also you don't need tables for Dates and Counts, try the following instead
Duration duration = new Duration(firstIn, lastDateOut); //Duration between two dates choosen by the user
int dimension=(int) ((duration.getStandardMinutes())/divideBy); //Number of abscissa points in the chart
DateTime transfert=firstIn; //First date
DateTime currentDate=transfert; // X-Axis Date
int currentCount=0; // Y-Axis LoggedUser Count
//Log data
DateTime log_DateIn;
DateTime log_DateOut;
for(int i=0;i<=dimension;i++)
{
currentDate = transfert;
currentCount = 0;
transfert = transfert.plusMinutes(divideBy);
for(Log log:old)
{
// We store our dates into variables, that way we avoid doing the time conversion twice
log_DateIn = StaticMethods.toDateTime(log.getDate_in()).minusSeconds(StaticMethods.toDateTime(log.getDate_in()).getSecondOfMinute());
log_DateOut = StaticMethods.toDateTime(log.getDate_out()).minusSeconds(StaticMethods.toDateTime(log.getDate_out()).getSecondOfMinute());
// Since we made the list ordered by DateOut, we are sure that if the stored DateOut is greater than transfert we can't find another user, that way we can break the for without parsing each log
if(log_DateOut.isAfter(transfert))
break;
// Now we can do checks to see if we need to increase the count
// We just check if the DateIn is between the currentDate and currentDate + divideBy (transfert)
if(log_DateIn.isAfter(currentDate) && log_DateIn.isBefore(transfert))
currentCount++;
// Same thing for DateOut
else if(log_DateOut.isAfter(currentDate) && log_DateOut.isBefore(transfert))
currentCount++;
// Now we need both cases
else if(log_DateIn.isBefore(currentDate) && log_DateOut.isAfter(transfert))
currentCount++;
// Equalities
else if(log_DateIn.equals(currentDate) || log_DateIn.equals(transfert) || log_DateOut.equals(currentDate) || log_DateOut.equals(transfert))
currentCount++;
}
GraphData nw = new GraphData(currentDate, currentCount);
}