Good day everyone! I have a get method in rest and the result is stored in something like this:
#XmlRootElement(name = "FooDTO")
public class Foo {
#XmlElement(nillable = true)
private String approvedDate;
private static final DateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat(
"dd.MM.yyyy");
public Date getApprovedDate() {
try {
return StringUtils.isBlank(approvedDate) ? null
: DEFAULT_DATE_FORMAT.parse(approvedDate);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
public void setApprovedDate(Date approvedDate) {
this.approvedDate = approvedDate == null ? "" : DEFAULT_DATE_FORMAT
.format(approvedDate);
}
}
It works in Glassfish server and I get approvedDate as a String in dd.MM.yyyy format. However, in Payara, the String is getting formatted to yyyy-MM-ddTHH:mm:ssZ[Timezone]. How do I adjust this so that the String doesn't get "interpreted" as DateTime? Thanks!
As I see you have a field approvedDate that is private so the the process marshal/unmarshal accesses this field through the get/set, in this case it's returning as Date type on the getApprovedDate method.
Try:
#XmlRootElement(name = "FooDTO")
public class Foo {
#XmlElement(nillable = true)
private String approvedDate;
private static final DateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy");
public String getApprovedDate() {
return approvedDate;
}
public void setApprovedDate(Date approvedDate) {
this.approvedDate = approvedDate == null ? "" : DEFAULT_DATE_FORMAT
.format(approvedDate);
}
}
Related
How can I use Spring Specification with Date field? I have no problem with 'normal' fields like Strings. But when I have Date, I have a problem and can't find a solution to solve it.
Here is my TaskEntity.class:
#Entity
#Table(name = "TASKS")
public class TaskEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String description;
#ManyToOne
private StatusEntity status;
private Date expiryDate;
// ....
}
And here is my TaskSpecification.class:
public class TaskSpecification implements Specification<TaskEntity> {
private static final Logger LOGGER = Logger.getLogger(TaskSpecification.class.getName());
private List<SearchCriteria> searchCriteriaList;
public TaskSpecification() {
this.searchCriteriaList = new ArrayList<>();
}
public void add(SearchCriteria criteria) {
searchCriteriaList.add(criteria);
}
#Override
public Predicate toPredicate(Root<TaskEntity> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
LOGGER.info("toPredicate()");
List<Predicate> predicates = new ArrayList<>();
for (SearchCriteria criteria : searchCriteriaList) {
if (criteria.getValue() instanceof Date) {
// WHAT TO DO HERE?
} else {
predicates.add(
builder.equal(
root.get(criteria.getKey()),
criteria.getValue().toString())
);
}
}
LOGGER.info("toPredicate(...)");
return builder.and(predicates.toArray(new Predicate[0]));
}
}
Ihe same problem I faced a month ago but this solution solved my issue.
public static Date startDate(Date date) {
try {
DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd");
String strDate = df2.format(date) + "T00:00:00";
LocalDateTime localDate = LocalDateTime.parse(strDate);
Instant instant = localDate.atZone(ZoneId.systemDefault()).toInstant();
date = Date.from(instant);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
return date;
}
Create a function and call where you use the date.
like that
values.add(EntitiesSpecification.startDate(fr.getValues().get(0)));
you can get the date value and add the date format in entity like MM-DD-YYYY. Could you please try this way?
NUllpointerexception is occured while trying to compare dates.
I noticed that while debugging that expectedDate and arrivedDate variable value is getting current date time where as i am using set Method to set date.Please correct my code for comparing dates. My method is used to find whether the shipment will arrive on time or before expected or after expected.
public class ShipmentBO {
public void displayStatusOfShipment(Shipment shipment) {
Date expectedDate = new Date();
Date arrivedDate = new Date();
SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy");
Shipment s = new Shipment();
ShipmentStatus SStatus = new ShipmentStatus();
expectedDate = s.getexpectedDeliveryDate();
arrivedDate = SStatus.getarrivedDate();
String s1 = df.format(expectedDate);
String s2 = df.format(arrivedDate);
if (expectedDate.after(arrivedDate)) {
System.out.println("The shipment arrived after the expected date");
} else
if (expectedDate.before(arrivedDate)) {
System.out.println("The shipment arrived before the expected date");
}
}
I am setting the date in the below main class
public static void main(String[] args) throws ParseException {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the shipment details :");
String userDetail = sc.nextLine();
String userDetailParts[] = userDetail.split(",");
//System.out.println(Arrays.toString(userDetailParts));
Shipment shipment = new Shipment();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
shipment.setid(userDetailParts[0]);
shipment.setsourcePort(userDetailParts[1]);
shipment.setdestinationPort(userDetailParts[2]);
shipment.setexpectedDeliveryDate(sdf.parse(userDetailParts[3]));
shipment.setcustomerName(userDetailParts[4]);
}
And the input I am giving as a comma separated - STAJU01, Hong Kong, Cochin,20-05-2017, karthick
Shipment class:
import java.util.Date;
public class Shipment {
private String id;
private String sourcePort;
private String destinationPort;
private Date expectedDeliveryDate;
private String customerName;
private ShipmentStatus[] shipmentStatus;
public String getid() {
return id;
}
public void setid(String id) {
this.id = id;
}
public String getsourcePort() {
return sourcePort;
}
public void setsourcePort(String sourcePort) {
this.sourcePort = sourcePort;
}
public String getdestinationPort() {
return destinationPort;
}
public void setdestinationPort(String destinationPort) {
this.destinationPort = destinationPort;
}
public Date getexpectedDeliveryDate() {
return expectedDeliveryDate;
}
public void setexpectedDeliveryDate(Date expectedDeliveryDate) {
this.expectedDeliveryDate = expectedDeliveryDate;
}
public String getcustomerName() {
return customerName;
}
public void setcustomerName(String customerName) {
this.customerName = customerName;
}
public Shipment() {
}
public Shipment(String id, String sourcePort, String destinationPort, Date expectedDeliveryDate,
String customerName) {
this.id = id;
this.sourcePort = sourcePort;
this.destinationPort = destinationPort;
this.expectedDeliveryDate = expectedDeliveryDate;
this.customerName = customerName;
}
public ShipmentStatus[] getShipmentStatus() {
return shipmentStatus;
}
public void setShipmentStatus(ShipmentStatus[] shipmentStatus) {
this.shipmentStatus = shipmentStatus;
}
}
ShipmentStatus:
import java.util.Date;
public class ShipmentStatus {
private String arrivalPort;
private String departurePort;
private Date arrivedDate;
private String status;
private Shipment shipment;
public Shipment getshipment() {
return shipment;
}
public void setshipment(Shipment shipment) {
this.shipment = shipment;
}
public String getarrivalPort() {
return arrivalPort;
}
public void setarrivalPort(String arrivalPort) {
this.arrivalPort = arrivalPort;
}
public String getdeparturePort() {
return departurePort;
}
public void setdeparturePort(String departurePort) {
this.departurePort = departurePort;
}
public Date getarrivedDate() {
return arrivedDate;
}
public void setarrivedDate(Date arrivedDate) {
this.arrivedDate = arrivedDate;
}
public String getstatus() {
return status;
}
public void setstatus(String status) {
this.status = status;
}
public ShipmentStatus() {
}
public ShipmentStatus(String arrivalPort, String departurePort, Date arrivedDate, String status,
Shipment shipment) {
this.arrivalPort = arrivalPort;
this.departurePort = departurePort;
this.arrivedDate = arrivedDate;
this.status = status;
this.shipment = shipment;
}
}
You are calling the getexpectedDeliveryDate() on a new Shipment(), but I suspect you want to call it on the shipment you receive as a parameter, which you otherwise leave untouched. Basically, try changing expectedDate = s.getexpectedDeliveryDate(); to expectedDate = shipment.getexpectedDeliveryDate();
See comments in code:
public void displayStatusOfShipment(Shipment shipment) {
// not used:
// SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy");
// extract date from passed shipment instance
Date expectedDate = shipment.getexpectedDeliveryDate();
// I assume ShipmentStatus is part of Shipment so you don't need a new instance here
// ShipmentStatus SStatus = new ShipmentStatus();
// extract arrivalDate from passed shipment's ShipmentStatus:
Date arrivedDate = shipment.getShipmentStatus().getarrivedDate();
// not used :
// String s1 = df.format(expectedDate);
// String s2 = df.format(arrivedDate);
if (expectedDate.after(arrivedDate)) {
System.out.println("The shipment arrived after the expected date");
} else
if (expectedDate.before(arrivedDate)) {
System.out.println("The shipment arrived before the expected date");
}
}
In Shipment add a method which contains the logic to obtain the arrivedDate of the shipment using the ShipmentStatus array. You say it's the third last ShipmentStatus so the code can be:
class Shipment {
public Date getArrivedDate() {
if(shipmentStatus!=null && shipmentStatus.length>=3)
return shipmentStatus[shipmentStatus.length-3].getArrivedDate();
return null;
}
}
I'm not sure if the 3rd last status is a good way to identify the right shipment status. It think it would be better to make your choice based on some business logic. For example:
* first shipment status with arrivedDate!=null
* last shipment status with arrivedDate!=null
* shipmentStatus with status='arrival'
get method is returning null value even if i have set the date
It's because you are not using the Shipment object passed to displayStatusOfShipment(Shipment shipment); rather, you are creating a new instance as follows:
Date expectedDate = new Date();
Shipment s=new Shipment();
expectedDate = s.getexpectedDeliveryDate();
You should replace all the above three lines with the following line:
Date expectedDate = shipment.getexpectedDeliveryDate();
Similarly, to this method, you should pass a parameter of the type, ShipmentStatus for the arrival date and use the same to get the arrival date i.e. you need to replace the following three lines in the similar way as shown above:
Date arrivedDate = new Date();
ShipmentStatus SStatus = new ShipmentStatus();
arrivedDate = SStatus.getarrivedDate();
On comparing dates:
I had suggested you to stop using the poorly designed java.util.Date and to switch to the modern java.time API. This scenario is a perfect example for you to make that switch immediately. Let's see why:
The modern date-time API has a class called, LocalDate which represents just date i.e. it has just three fields: year, month and day and therefore when you compare two instances of LocalDate, only these fields are compared. LocalDate has a rich set of API for comparison e.g. LocalDate#isAfter, LocalDate#isBefore, LocalDate#isEqual etc. which compare the values of these three fields to give you the result.
You will say that java.util.Date also has Date#before, Date#after etc. but this is where the comparison of these methods with those of the LocalDate ends. These methods of java.util.Date compare the milliseconds since January 1, 1970, 00:00:00 GMT i.e. one instance of Date can be before/after even with a difference of a millisecond (unlike two instances of LocalDate which can be before/after only with the difference in one or more of the fields, day, month, and year).
public class Main {
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date();
date2.setTime(date1.getTime() - 1);
System.out.println(date1);
System.out.println(date2);
System.out.println(date1.after(date2));
}
}
Output:
Wed Aug 19 16:34:56 BST 2020
Wed Aug 19 16:34:56 BST 2020
true
If you still insist to use java.util.Date:
If you still insist to use java.util.Date, you will have to get the day, month and year from the two instances of Date yourself and compare them to determine before/after cases. The choice is yours.
I have a Mongo collection with objects of this format:
{
id: 1,
date: "2020-08-06T12:00:00Z",
...
}
I have Java code that needs to read from this collection but never writes to it. The process that writes to this collection is not owned by me so I can't necessarily change the format of that date string. I initially tried to model my Java Morphia object like this:
#Entity public class MyDocument {
#Id
private Integer id;
private Date date;
...
}
This did not work because Morphia didn't know how to deserialize that date format into a Date object. The solution that I came up with was treating the date as a String on the POJO and then having a getDate() method that did the actual deserialization. I am wondering, is there a better way for me to do this? I know if you're using Jackson you can annotate certain fields with #JsonDeserialize and pass a deserializer so I was wondering if there was something similar for Morphia.
My solution (which feels suboptimal to me):
#Entity public class MyDocument {
#Id
private Integer id;
private String date;
...
private Date getDate() {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
try {
return dateFormat.parse(date);
} catch (Exception ex) {
return null;
}
}
}
You can go ahead and create a simple converter extending the TypeConverter like so:
public class DateConverter extends TypeConverter {
private static final String FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private final SimpleDateFormat simpleDateFormat;
public DateConverter() {
super(Date.class);
this.simpleDateFormat = new SimpleDateFormat(FORMAT);
}
#Override
public Object decode(Class<?> targetClass, Object fromDBObject, MappedField optionalExtraInfo) {
try {
return simpleDateFormat.parse(((String) fromDBObject));
} catch (ParseException e) {
return null;
}
}
}
The go ahead and register your formatter for your document entity like so:
#Entity("Documents")
#Converters(DateConverter.class)
public class Document {
#Id
private Integer id;
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
private Date date;
public Date getDate() { return date; }
public void setDate(Date date) { this.date = date; }
#Override
public String toString() {
return "Document{" +
"id=" + id +
", date=" + date +
'}';
}
}
This will effectively tell Morphia to decode the database incoming values via parsing the string with the desired pattern, resulting directly into a concrete Date object without any additional conversion logic.
The timestamp '2015-06-15 13:01:48' which is stored in MySQL database is coming as 1434369708000 in my rest api response. How to handle so that the response also has the same format. I'm using Java, Hibernate, Restful WS with MySQL.
Entity:
private Date CreatedDateTime;
#Column(name = "created_Date_Time", columnDefinition = "TIMESTAMP")
public Date getCreatedDateTime() {
return createdDateTime;
}
public void setCreatedDateTime(Date createdDateTime) {
this.createdDateTime= createdDateTime;
}
JSON View:
#JsonView({MessageView.class})
public Date getCreatedDateTime() {
if (device != null) {
return device.getCreatedDateTime();
}
return null;
}
public void setCreatedDateTime(Date CurrentServerUTC) {
if (device != null) {
this.device.getCreatedDateTime(CurrentServerUTC);
}
}
http://fasterxml.github.io/jackson-annotations/javadoc/2.0.0/com/fasterxml/jackson/annotation/JsonFormat.html
On Entity try annotating CreatedDateTime with:
#JsonFormat(pattern = "yyyy-MM-dd kk:mm:ss")
private Date CreatedDateTime;
Double check the pattern though, I'm not %100 sure it's correct. It's the same as Java SimpleDatePattern string.
PS: non-static field names start with lowercase letter in Java as a convention.
I wrote a simple test to showcase this annotation:
public class JacksonDateTest {
#Test
public void test() throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectMapper om = new ObjectMapper();
om.writeValue(baos, new Sth());
baos.write("\n Sth2 \n".getBytes());
om.writeValue(baos, new Sth2());
System.out.println(baos.toString());
baos.close();
}
public class Sth {
#JsonFormat(pattern = "yyyy-MM-dd kk:mm:ss")
Date creationDate = new Date();
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
}
public class Sth2 {
Date creationDate = new Date();
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
}
}
It works. Sth is serialized as:
{"creationDate":"2015-06-16 16:09:06"}
while Sth2 is serialized as:
{"creationDate":1434470946137}
There must be something else going wrong in your code.
Hy, my xml looks like this:
<forecast>
<time day="2014-06-02">
<symbol></symbol>
</time>
<time day="2014-06-03">
<symbol></symbol>
</time>
</forecast>
I need map day attribute for each "time" object but it looks like it didn't work as I expect.
Heres my classes (java):
public class Forecast {
#XmlElement
public List<WeatherEvent> time;
}
public class WeatherEvent {
#XmlAttribute(name = "day")
#XmlJavaTypeAdapter(DateAdapter.class)
public Date day;
#XmlElement
public Symbol symbol;
}
public class DateAdapter extends XmlAdapter<String, Date> {
private final SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss");
#Override
public String marshal(Date v) throws Exception {
return dateFormat.format(v);
}
#Override
public Date unmarshal(String v) throws Exception {
Date date = dateFormat.parse(v);
if (date == null) {
SimpleDateFormat simplierFormat = new SimpleDateFormat("yyyy-MM-dd");
date = simplierFormat.parse(v);
}
return date;
}
}
How to map "day" attribute properly to make it not null?
The following line is going to throw a ParseException and exit the method and never get to the logic below when the date looks like: 2014-06-02.
Date date = dateFormat.parse(v);
You will need to catch the exception and ignore it, and then apply the second formatter to it.
Date date = null;
try {
Date date = dateFormat.parse(v);
} catch(ParseException e) {
SimpleDateFormat simplierFormat = new SimpleDateFormat("yyyy-MM-dd");
date = simplierFormat.parse(v);
}
return date;