My recommendation for you is that you stop using the long outdated Timestamp
class. Either completely if you can, or at least you minimize your use of it. I will show you code for both options. The modern Java date and time API known as java.time
or JSR-310 is so much nicer to work with. And even more so when it comes to time arithmetic like adding an hour to a date-time.
java.time
Change getInterviewDateAndTime()
to return an Instant
. Instant
is the class from java.time
that naturally replaces the old Timestamp
class. Also change the receiver of your Map
to accept a map with Instant
objects in it. Modern versions of JDBC, JPA, etc., happily retrieve Instant
objects from your database and store Instant
s back into it.
Instant instantStart = scheduled.getInterviewDateAndTime(); //from DB
Map<String, Object> map = new HashMap<>();
map.put("eventTitle", "interview with");
map.put("startDateTime", instantStart);
System.out.println("startDateTime : " + instantStart);
Instant instantEnd = instantStart.plus(1, ChronoUnit.HOURS);
map.put("endDateTime", instantEnd);
System.out.println("endDateTime : " + instantEnd);
Things to note: The code much more naturally and straightforward expresses the fact that one hour is added. No need for multiplications, no need for the reader to check that you multiplied the right constants, or that your multiplication didn’t overflow; it’s all taken care of. The Instant
class is immutable, so there’s no risk of accidentally changing the Instant
object that you have alrady added to the map.
In my example the above code printed:
startDateTime : 2017-11-29T09:15:00Z
endDateTime : 2017-11-29T10:15:00Z
Times are in UTC.
EDIT: As Basil Bourque helpfully pointed out in a comment, adding an hour can also be done this way:
Instant instantEnd = instantStart.plus(Duration.ofHours(1));
The result is the same.
Use with legacy APIs
Assume you cannot change the return type of getInterviewDateAndTime()
and/or the receiver of your map absolutely needs Timestamp
objects in it. The standard way to go about such a restriction is you still use the modern API in your own code. As soon as you receive a Timestamp
, you convert it to Instant
. And when you need to pass a Timestamp
to your legacy code, you convert your Instant
only in the last moment.
Timestamp timestampStart = scheduled.getInterviewDateAndTime(); //from DB
Instant instantStart = timestampStart.toInstant();
Map<String, Object> map = new HashMap<>();
map.put("eventTitle", "interview with");
map.put("startDateTime", timestampStart);
System.out.println("startDateTime : " + timestampStart);
Instant instantEnd = instantStart.plus(1, ChronoUnit.HOURS);
Timestamp timestampEnd = Timestamp.from(instantEnd);
map.put("endDateTime", timestampEnd);
System.out.println("endDateTime : " + timestampEnd);
You still have most of the advantages of the modern API mentioned above, but a couple of extra lines for the conversions. This code printed
startDateTime : 2017-11-29 10:15:00.0
endDateTime : 2017-11-29 11:15:00.0
The times are the same as above, but in my local time zone since Timestamp.toString()
renders them this way (which confuses many).
Question: Can I use the modern API with my Java version?
If using at least Java 6, you can.
- In Java 8 and later the new API comes built-in.
- In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310). Conversion between
Timestamp
and Instant
is a little different and goes through a class named DateTimeUtils
, but it’s not more complicated. The rest is the same.
- On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP, and I think that there’s a wonderful explanation in this question: How to use ThreeTenABP in Android Project.