Compare string date to current long time - java

A search API is returning date in String format,I want to compare that date with current date and do something. I created a date object and parsed it but still getting error when I do the compare.
Calendar currentDate = Calendar.getInstance();
long dateNow = currentDate.getTimeInMillis();
String eventDate = meta.getString("startDate"); //This is the string API returns
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss.SSS");
Date date = formatter.parse(eventDate);
long modifiedDate= date.getTime();
if (dateNow.compareTo(modifiedDate)>0) {
//Do Something
}
Error I get is :
Cannot invoke compareTo(long) on the primitive type long
Thanks.

When comparing primitive longs just use a vanilla comparison operator:
dateNow > modifiedDate
This is not recommended, but if you want to use compareTo, first convert to Long:
Long.valueOf(dateNow).compareTo(Long.valueOf(modifiedDate)) > 0

compareTo method is part of wrapper classes, long is primitive datatype - you cannot call method on primitive datatype. Either change long to Long or compare long directly like dateNow > modifiedDate

long is a primitive type, which means it is not an object and doesn't have basic methods like compareTo, etc. You can perform mathematical operations to compare them though:
if (dateNow - modifiedDate > 0) /* dateNow is later than modifiedDate */
Another solution is using Long (capital L) which is an object. Then you can use compareTo, etc.

compareTo is a method. It is not defined for the primitive type long. It is defined for the Date class.
Date dateNow = currentDate.getTime(); // instead of getTimeInMillis()
...
if (dateNow.compareTo(date)) { // this will now work
If they're both Date objects, you can do dateNow.before(date) which makes much more sense semantically.
Alternatively, you can use the > and < operators and do dateNow < modifiedDate if you leave dateNow as a long.

Related

Sort Array object by date of its field

I have an Object MyTimes and in that object there are fields name ,start_date and configuration.
I have an array of this object, MyTimes [] mytimes
I am trying to sort the array by the start time but am struggling how to go about it.
The start_time field is a string, so this needs converting to a datetime.
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
for(int i=0; i<mytimes.length; i++) {
Date date = formatter.parse(mytimes[i].getStartTime());
}
I'd then put the date into an array list perhaps and then sort by datetime? But then I wouldnt know which start_time corresponds with which mytimes object...
What is the most efficient way of doing this?
Under the right circumstances this is a one-liner:
Arrays.sort(myTimes, Comparator.comparing(MyTimes::getStartDate));
Let’s see it in action:
MyTimes[] myTimes = {
new MyTimes("Polly", "2019-03-06T17:00:00Z"),
new MyTimes("Margaret", "2019-03-08T09:00:00Z"),
new MyTimes("Jane", "2019-03-01T06:00:00Z")
};
Arrays.sort(myTimes, Comparator.comparing(MyTimes::getStartDate));
Arrays.stream(myTimes).forEach(System.out::println);
Output:
Jane 2019-03-01T06:00:00Z
Polly 2019-03-06T17:00:00Z
Margaret 2019-03-08T09:00:00Z
I am assuming that getStartDate returns an Instant or another type the natural order of which agrees with the chronological order you want. For example:
public class MyTimes {
private String name;
private Instant startDate;
// Constructor, getters, toString, etc.
}
If you are receiving your start dates as strings somehow, you may write a convenient constructor that accepts a string for start date. I am already using such a constructor in the above snippet. One possibility is having two constructors:
public MyTimes(String name, Instant startDate) {
this.name = name;
this.startDate = startDate;
}
public MyTimes(String name, String startDate) {
this(name, Instant.parse(startDate));
}
The Instant class is part of java.time, the modern Java date and time API.
I am exploiting the fact that your strings are in the ISO 8601 format for an instant, the format that Instant.parse accepts and parses.
Avoid SimpleDateFormat and Date
I recommend you don’t use SimpleDateFormat and Date. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. There is also an error in your format pattern string for parsing: Z (pronounced “Zulu”) means UTC, and of you don’t parse it as such, you will get incorrect times (on most JVMs). Instant.parse efficiently avoids any problems here.
Don’t store date-tine as a string
It looks like you are are storing start time in a String field in your object? That would be poor modelling. Use a proper date-time type. Strings are for interfaces. Date-time classes like Instant offer much more functionality, for example define sort order.
You have two main approaches:
Make your class implement Comparable
Use a custom Comparator
Then, you can choose the field to compare from, and transform it.
IE (implementing comparable):
class Example implements Comparable<Example> {
private String stringDate;
public int compareTo(Example e) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date date1 = formatter.parse(this.stringDate);
Date date2 = formatter.parse(e.stringDate);
return date1.getTime() - date2.getTime();
}
}
And then using Arrays.sort would use your custom comparison.
Let your class implement Comparable and implement compareTo using modern formatting and date classes. Note that LocalDateTime also implements Comparable so once the string has been parsed you let LocalDateTime do the comparison
public class MyTimes implements Comparable<MyTimes> {
private final DateTimeFormatter dtf = DateTimeFormatter.ISO_INSTANT;
//other code
public int compareTo(MyTimes o) {
LocalDateTime thisDate = LocalDateTime.from(dtf.parse(this.getStartTime()));
LocalDateTime otherDate = LocalDateTime.from(dtf.parse(o.getStartTime()));
return thisDate.compareTo(otherDate);
}
}
You can also create a separate class as a comparator if this comparison is special and what you not always want to use
public class MyTimesComparator implements Comparator<MyTimes> {
#Override
public int compare(MyTimes arg0, MyTimes arg1) {
DateTimeFormatter dtf = DateTimeFormatter.ISO_INSTANT;
LocalDateTime thisDate = LocalDateTime.from(dtf.parse(this.getStartTime()));
LocalDateTime otherDate = LocalDateTime.from(dtf.parse(o.getStartTime()));
return thisDate.compareTo(otherDate);
}
}
and then use it like
someList.sort(new MyTimesComparator());
or use an inline function (I am using Instant here)
someList.sort( (m1, m2) -> {
DateTimeFormatter dtf = DateTimeFormatter.ISO_INSTANT;
Instant instant1 = Instant.from(dtf.parse(m1.getStartTime));
Instant instant2 = Instant.from(dtf.parse(m2.getStartTime));
return intant1.compareTo(instant2);
});
I noticed now that you have an array and not a list so you need to convert to a list or use Arrays.sort instead.

LocalDate with Joda constructor says The constructor LocalDate(int, int, int) is not visible

According to the documentation in Joda:
public LocalDate(int year,
int monthOfYear,
int dayOfMonth,
Chronology chronology)
Should take the above which I did. I tried to set Chronology to null but I get the following error:
The constructor LocalDate(int, int, int, null) is undefined
However I am passing the correct values, but from what I understand the chronology null means ISOChronology in default time zone.
Therefore how can I pass three correct Integer values and use the constructor correctly?
if (cit.hasNext()) {
cell = cit.next();
cell.setCellType(Cell.CELL_TYPE_NUMERIC);
if (DateUtil.isCellDateFormatted(cell))
{
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String cellValue = sdf.format(cell.getDateCellValue());
//System.out.println(cellValue);
//bufferDate is getting mm/dd/yyyy from excel cell
String[] dateSpliter = cellValue.split("/");
int month= Integer.parseInt(dateSpliter[0]);
int day= Integer.parseInt(dateSpliter[1]);
int year= Integer.parseInt(dateSpliter[2]);
_date = new LocalDate(year,month,day,null);
po.setDate(_date);
}
It looks to me as if you have imported the wrong class.
The Java 8 java.time.LocalDate class has no public constructors, but it does have a private constructor that takes three int values. I think this class is what you have imported by mistake, when you wanted org.joda.time.LocalDate instead.
I know that this question is old, but you can just write:
LocalDate date = LocalDate.of(int, int, int);
I hope somebody will find this helpfull.

Comparing Converting ISO8601-compliant date with Java date?

As per this question, I have found how to parse the Solr date, but I am still unable to compare it with Java date.
DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
String jtdate = "2010-01-01T12:00:00+01:00";
System.out.println(parser2.parseDateTime(jtdate));
Currently I have got date in this format : 2013-07-28T13:48:02Z and I need to apply compareTo() operator on this date with current date from Java.
Assuming you do not care about the time, consider using DateTimeComparator.getDateOnlyInstance(), which is a Comparator that ignores the time fields when making the comparison, e.g.:
final DateTime a = parser2.parseDateTime(jtdate);
final Date b = new Date();
DateTimeComparator comparator = DateTimeComparator.getDateOnlyInstance();
comparator.compare(a, b);
Or,
comparator.compare(a, DateTime.now());

A method to return 3 formats of data

I have Date in this format 2009-09-17T00:00:00.000-35:00 . As per the business Rules for my Application , i have written 3 Methods which will accept this Date and returns the Date in MM/yyyy , yyyyMM and dd .
For example one method is shown below MM/yyyy
private String getMonthYear(String date) throws Exception {
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
String s1 = date;
String s2 = null;
Date d;
try {
d = sdf.parse(s1);
s2 = (new SimpleDateFormat("MM/yyyy")).format(d);
} catch (ParseException e) {
e.printStackTrace();
}
return s2;
}
Similarly i have other two methods which will return data in yyyyMM and dd formats ??
This works fine , but does not look good
My question is can we have only one utility which satisfies my requirement ??
My question is can we have only one utility which satisfies my requirement ??
I think you're going about this the wrong way to start with. Fundamentally the data is just a date. You can apply formats later, when you need to. I suggest you start using Joda Time and make your method return a LocalDate. That captures all the real information, and you can then have three separate DateTimeFormatter objects used to format the value whenever you want.
Wherever you can, represent data using a type which most naturally represents the real information. Get your data into that natural format as early as possible, and keep it in that format until you have to convert it into something else (such as a string).
You could define a single method and receive as a parameter the string with the expected date format, the three strings with the formats could be defined as constants.
Yes, you could group the three methods together, and use an additional argument (an enum, for example) to specify which kind of output format you want. But I would not do that. Your solution is cleaner. Why do you think it doesn't look good?
What I would do, however, is transforming the String to a Date once and for all, and using a Date everywhere rather than the String, and transforming the Date with one of your 3 methods (which would take a Date as argument rather than a String) when needed.
The Apache Commons Lang library already has utility methods to do this for you.
For example:
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
///
// first, convert the string to a date object
Date parsedDate = DateUtils.parseDate("2012-05-25T16:10:30.000",
new String[] {"yyyy-MM-dd'T'HH:mm:ss.SSS"});
// now, format the date object to a string, using different formats
String formattedDate = DateFormatUtils.format(parsedDate, "MM/yyyy");
String formattedDate2 = DateFormatUtils.format(parsedDate, "yyyyMM");
Take a look at DateFormatUtils and DateUtils for more information.
You could just have a Date class which has the three methods. Like below:
public class MyDate {
private String date = null;
public MyDate(String date) {
this.date = date;
}
public String getMonthYear() {
return null;
}
public String getYearMonth() {
return null;
}
public String getDay() {
return null;
}
}
You can format the String into three different Strings in the constructor and just return those strings on method calls. That implementation would be good if you make numberous/repeated calls on the same date string. Or you could format the string in the method call, if you are doing it once but if you are doing it once you may want to make the class/methods static and get rid of the constructor.

Converting java.sql.Date to java.util.Date

What's the simplest way to convert a java.sql.Date object to a java.util.Date while retaining the timestamp?
I tried:
java.util.Date newDate = new Date(result.getDate("VALUEDATE").getTime());
with no luck. It's still only storing the date portion into the variable.
The class java.sql.Date is designed to carry only a date without time, so the conversion result you see is correct for this type. You need to use a java.sql.Timestamp to get a full date with time.
java.util.Date newDate = result.getTimestamp("VALUEDATE");
If you really want the runtime type to be util.Date then just do this:
java.util.Date utilDate = new java.util.Date(sqlDate.getTime());
Brian.
Since java.sql.Date extends java.util.Date, you should be able to do
java.util.Date newDate = result.getDate("VALUEDATE");
This function will return a converted java date from SQL date object.
public static java.util.Date convertFromSQLDateToJAVADate(
java.sql.Date sqlDate) {
java.util.Date javaDate = null;
if (sqlDate != null) {
javaDate = new Date(sqlDate.getTime());
}
return javaDate;
}
From reading the source code, if a java.sql.Date does actually have time information, calling getTime() will return a value that includes the time information.
If that is not working, then the information is not in the java.sql.Date object. I expect that the JDBC drivers or the database is (in effect) zeroing the time component ... or the information wasn't there in the first place.
I think you should be using java.sql.Timestamp and the corresponding resultset methods, and the corresponding SQL type.
In the recent implementation, java.sql.Data is an subclass of java.util.Date, so no converting needed.
see here: https://docs.oracle.com/javase/1.5.0/docs/api/java/sql/Date.html

Categories