I have a private java.sql.Timestamp myDate in some model (POJO) class like below
private String isActive;
private Date dob;
private Timestamp createdDate;
private Timestamp lastMktPrefUpdateAt;
We were using spring boot version to 1.5.10.RELEASE and REST API response for timestamp field was in millisecond format like below -
{
"isActive": "y",
"lastMktPrefUpdateAt": 1632195609787,
"dob": "08/12/1991",
"createdDate": 1632195609788
}
We have recently upgraded the spring boot version to 2.3.0.RELEASE and this started sending timestamp field in response to some ISO format like below -
{
"isActive": "y",
"lastMktPrefUpdateAt": "2021-09-20T22:10:09.787+0000",
"dob": "07/12/1991",
"createdDate": "2021-09-20T22:10:09.788+0000"
}
Can someone please help answering, how can we format Timestamp back to millisecond format?
We need to format Timestamp at global level meaning without changing all the POJO classes.
Try this in your properties file
spring.jackson.serialization.write-dates-as-timestamps:true
OR
Use #JsonFormat(shape = JsonFormat.Shape.NUMBER) above the property that you want.
Update
If you want to add millis to your timestamp, try to pass the long value to the Timestamp constructor and call the getTime() method to receive a 13-digits timestamp.
long now = System.currentTimeMillis();
Timestamp timeStamp= new Timestamp(now);
System.out.println(timeStamp.getTime());
You could convert that string to a ZonedDateTime object which has a .toInstant().toEpochMilli() method.
Something like:
long millis = ZonedDateTime.of(LocalDateTime.parse(str), ZoneId.of("Etc/UTC")).toInstant().toEpochMilli();
see:
How to get milliseconds from LocalDateTime in Java 8
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html
https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html
However, I would recommend refactoring the system to use the immutable LocalDatTime object at a later point.
(There may be an appropriate annotation you can put on that timestamp field to parse it in a specific way, but not one that I am aware of.)
Related
I write application on Spring Boot with Spring Data(postgresql).
I have the following case. I want to store in database time at UTC timezone, and parse it to/from "America/San-Paulo" timezone in dto.
For example: in controller I get dto with LocalDateTime in America/San-Paulo timezone. And I want to save it in database in UTC timezone.
I can do in when mapping from dto to entity. But maybe there is another simple way like setting some properties of hibernate/spring?
Since Java 8, we have the Date/Time API under java.time!
(1) Convert the timezone in annotated #PrePersist, #PreUpdate, and #PostLoad methods.
For example, in annotated #PostLoad, convert from UTC to America/San-Paulo.
private static ZoneId UTC_ZONE = ZoneId.of("UTC");
private static ZoneId LOCAL_ZONE = ZoneId.of("America/San_Paulo");
private LocalDateTime dateTime;
#PostLoad
public void toLocal() {
dateTime = dateTime.atZone(UTC_ZONE).withZoneSameInstant(LOCAL_ZONE).toLocalDateTime();
}
(2) Assuming you are using Jackson, you can write a custom serializer/deserializer.
UPDATE:
With PostgreSQL, you can use the type timestamp with time zone. By default, if you insert/update the column, it will convert the value to UTC.
In JPA:
#Column(columnDefinition = "timestamp with time zone")
UPDATE (22-07-01):
You could also use an AttributeConverter.
I use Spring boot and JPA and my Order domain object have this field:
#Column(name = "TIMESTAMP")
private ZonedDateTime timestamp;
I create a date with this method:
protected static ZonedDateTime createZonedDateTime(final String date) {
LocalDateTime ldt = LocalDateTime.parse(date + " 00:00", DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm"));
return ldt.atZone(ZoneId.systemDefault());
}
When I insert this in database throw JPA, with showsql to true, I can see that the inserted date is: [2020-01-01T00:00+01:00[Europe/Paris]]
when I retrieve the data throw JPA repository, the date I get is: 2020-01-01T01:00+01:00[Europe/Paris]
How come I have one hour shift? It's not working since hsqldb 2.6.0. Works perfectly with 2.5.0.
I use Liquidbase to create the field with:
<column name="TIMESTAMP" type="TIMESTAMP WITH TIME ZONE"
remarks="The timestamp of the order"/>
I have a Spring Boot API where in JSON request Date field is send but in application code it is not getting formatted correctly and hence DB call is failing due to binding issue
This field is sent in JSON request :-
"created_at": "2014-08-12 11:48:41.000000"
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss.SSSSSS", timezone="AEST")
private Date createdAt;
When the getCreatedAt() method is called the Date is coming in format - Tue Aug 12 07:48:41 EDT 2014
But I am expecting it in same format the way it was sent
Add #JsonSerialize(as = Date.class) annotation first and do JsonFormat
#JsonSerialize(as = Date.class)
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss.SSSSSS", timezone="AEST")
private Date createdAt;
#JsonFormat annotation is used to specify the format that will be used to serialize the property and seems to be doing it right. when you call getCreatedAt() you will get a Date object and it is up to you how you want to format it.
you can use LocalDateTime like this:
#JsonFormat(shape= JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS")
#JsonProperty("create_time")
LocalDateTime createTime;
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
you need this dependency
I've recently started using Joda time library for my test project.
Particularly i have been enjoying the capabilities of DateTime and functions for its manipulation.
My query is how do you store DateTime in MySql. I am using Spring & Hibernate for my application.
my current entity throws deserialisation errors whenever I try and use it:
#Entity
#Table(name = "test_storage")
public class TestEntity {
#Id #GeneratedValue
private int id;
#Column
private DateTime testDate;
//getters and setters
}
The mysql table structure is as follows:
Name: test_storage
Columns:
id INT NOT_NULL, AUTO_INCREMENT
testDate DATETIME
Any advice?
If you are using Hibernate 4+, then you can adopt the Jadira user types which allow you to map DateTime (and other JODA date time related class like LocalDate, LocalDateTime etc) to DB fields using different strategies.
Your mapping will look like
public class TestEntity {
//...
#Column
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime testDate;
}
Read the documents to know how to properly use these types to fit your requirements.
The biggest pitfall that you may face soon is, as Java's Date does not include timezone information nor does it sticks to UTC (JODA's user types still need to map to Timestamp/Date internally), you may want to make sure the way you store does provide proper information. For example, either store the date time as UTC, or store timezone information as a separate field, etc.
DATETIME would be my choice. See some more details at What difference between the DATE, TIME, DATETIME, and TIMESTAMP Types and http://infopotato.com/blog/index/datetime_vs_timestamp
I'm Using Oracle 11g and JPA 2.0 (hibernate in JBoss 6.0.0).
I need to represent a time range in an entity, so I defined those fields:
#Temporal(TemporalType.TIME)
private Date startTime;
#Temporal(TemporalType.TIME)
private Date endTime;
The generated tables use two DATE fields, and this is ok since Oracle doesn't have a type representing just the time part.
When loading the entity from db, just the time part is loaded (the field contains a java.sql.Time).
I've seen instead that if I set a complete date+time in the fields, the date part will be persisted to the db.
Is there a way to ensure that the date part will not be persisted to the db?
You can write setter methods which remove the date component. Quick and dirty example:
public void setStartTime(Date startTime)
{
this.startTime = new Time(startTime.getTime() % 86400000L);
}
Though you'd be better off using Joda Time to do your date/time calculations (see this question). I didn't test this to make sure it's correct, but it should show you the basic idea:
public void setStartTime(Date startTime)
{
this.startTime = new Time(LocalTime.fromDateFields(startTime).millisOfDay().get());
}