Spring Mapping using a custom mapper method - java

I have two objects with all the same members except for the date member.
In Obj1.date is a java.sql.Date, and Obj2.date is a long (epoch).
I need to write a mapper to map obj1 to obj2. This is what I tried to do:
#Named("sqlDateToEpoch")
default long sqlDateToEpoch(Date timestamp) throws ParseException {
return myUtils.sqlDateToEpoch(timestamp);
}
#Mapping(source = "date", target = "date", qualifiedByName = "sqlDateToEpoch")
Obj2 toObj2(Obj1 source);
List<Obj2> toRecordList(List<Obj1> source);
But the mapperImpl just has its own implementation for the date conversion:
if (source.getDate() != null) {
Obj2.setDate(Long.parseLong(source.getDate()));
}
I'm getting:
java.lang.NumberFormatException: For input string: "2019-04-02 00:00:00.0"
What is the right way for this kind of conversion?

I think that the reason why it doesn't work is because your source.getDate() is returning a String and not a java.sql.Date. This leads to MapStruct using the implicit String to long conversion.
In order to fix this you would either need to make sure that source.getDate() returns java.sql.Date or add a method that would get a String and return Long.

Related

Converting LocalDateTime Object to LocalDateTime

I am new to Java and I am working on Java 8.
I am trying to convert LocalDateTime Object to LocalDateTime but not able to find any way without converting it to String. Is there any direct method for converting Object to LocalDateTime when the underlying Object type is LocalDateTime?
Moreover, if there is any way to convert, can it work for underlying String type LocalDateTime Object too?
Below is my current code which is converting the Object to String before converting it to LocalDateTime as LocalDateTime.parse method needs String input.
public static LocalDateTime toDateTime(Object dateTimeObject) {
LocalDateTime dateTime = LocalDateTime.parse(dateTimeObject.toString(), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"));
return dateTime;
}
If the object is a LocalDateTime, you can cast the object.
public static LocalDateTime toDateTime(Object dateTimeObject) {
if (dateTimeObject instanceof LocalDateTime) {
return (LocalDateTime) dateTimeObject;
}
return null;
}
According to the Java 8 LocalDateTime API there is no method that takes an Object argument and returns a LocalDateTime. But there is one that takes a CharSequence parameter, which is why it works when you convert the object to String, and why it won't work if you just pass the Object parameter. If you don't want to have to do the call to the toString() method, perhaps the parameter of toDateTime(Object o) should be of a different type.

How to get the object containing the latest LocalDate inside a hashmap

I have a properties inside the DVDs object called releaseDate and its a String.
getReleaseDateFormatted() is a method inside my DVDs object where I would parse a String to LocalDate.
I assume the following code would group all the releaseDate together in LocalDate type? I need to find the latest date inside this group.
#Override
public DVDs getOldestDVD() throws PersistenceException {
return dvdMap.values()
.stream()
.collect(Collectors.groupingBy(d -> d getReleaseDateFormatted()))
}
The question is very vague and confusing, but if my understanding is correct, you shouldn't need any streams. Try this:
return Collections.max(dvdMap.values(),
Comparator.comparing(DVDs::getReleaseDateFormatted));

Java template function

I have a function that sometimes has to return a Date other times a DateTime (Joda-Time).
static public <T extends Object> T convertTimeForServer(DateTime toSave) {
DateTime temp = null;
try {
temp = toSave.withZone(DateTimeZone.forID(getServerTimeZone()));
} catch (Exception e) {
}
T toReturn = null;
if (toReturn.getClass().equals(temp)) {
return (T) temp;//Return DATETIME
} else {
return (T) temp.toDate();//Return DATE
}
}
Is it the right approach?
How to use it?
like this (timerHelper is the name of class):
DateTime t = timerHelper.<DateTime>convertTimeForServer(new DateTime());
Date t2 = timerHelper.<Date>convertTimeForServer(new DateTime());
or
DateTime t = (DateTime)timerHelper.convertTimeForServer(new DateTime());
Date t2 = (Date)timerHelper.convertTimeForServer(new DateTime());
And how to use this function instead?
static public <T extends Object> T current_Moment(){
return convertTimeForServer(new DateTime());
}
I suspect you're being too clever trying to use generics here. Because you don't have polymorphism on return types doesn't mean you should resort to generics to try and achieve that effect.
You can implement this simply as two methods: public static Date convertToDateForServer(DateTime toSave) {...} and public static DateTime convertToDateTimeForServer(DateTime toSave) {...}. The calling code seems to know what it wants, so it can simply call the method needed. If there really is a complex commonality to both methods, make a private method that both can call internally.
If Java 8 is available you could always implement an Either using the new Optional class.
This is one of the tricky areas of Generics. The only way to get this to work would be to take a Class argument, so the method knows what type of object to create. It can't know at the moment, because of Type Erasure.
Alternatively (much simpler) is to always return DateTime and do away with generics here.
The client will always know what it wants, and if the client wants a Date, it can create one from the DateTime far more easily than what you are trying to do.
Example:
Client 1 wants a DateTime:
DateTime result = service.convertTimeForServer(dt);
Client 2 wants a Date:
Date result = service.convertTimeForServer(dt).toDate();

convert object into date

I get an ArrayList of Object[] from a database and I want to convert the java.sql.Date stored in an object into a java.util.Date (in order to use it in jfreechart):
my code is as follows:
fills up the Array of object with data from MySQL
ArrayList<Object[]> mydata=new ArrayList<>();
mydata=sqlGetter.getMdbObjectList(sqlString, null);
for(Object[] myobject : mydata){
if (myobject[1].getClass()==java.sql.Date.class){
java.util.Date mydate=null;
mydate = Date ( myobject[1]);
}
}
Netbeans return an error: "Java incompatible types: Object cannot be converted to Date"
While I understand the idea, I would have expected to be able to cast the object into a Date after having checked that it is indeed of the right class.
I'm starting java, so please any helps on the obvious mistake that I must be doing would be useful.
You are missing a cast. Additionally, you'd be better off using the instanceof operator:
for(Object[] myobject : mydata){
// Note that java.sql.Date extends java.util.Date
if (myobject[1] instanceof java.util.Date) {
java.util.Date mydate = (java.util.Date) myobject[1];
}
}
you just need to explicit cast the object to Date
ex: (Date) obj;

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.

Categories