Convert LocalDate to LocalDateTime or java.sql.Timestamp
Asked Answered
A

7

160

I am using JodaTime 1.6.2.

I have a LocalDate that I need to convert to either a (Joda) LocalDateTime, or a java.sqlTimestamp for ormapping.

The reason for this is I have figured out how to convert between a LocalDateTime and a java.sql.Timestamp:

LocalDateTime ldt = new LocalDateTime();
DateTimeFormatter dtf = DateTimeFormatter.forPattern("yyyy-MM-dd HH:mm:ss");
Timestamp ts = Timestamp.valueOf(ldt.toString(dtf));

So, if I can just convert between LocalDate and LocalDateTime, then I can make the continued conversion to java.sql.Timestamp. Thanks for any nudges in the right direction!

Argo answered 24/1, 2012 at 18:46 Comment(1)
FYI, the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. See Tutorial by Oracle. Also, the java.sql.Timestamp class is now legacy, supplanted by the java.time classes, specifically by Instant.Byrom
C
321

JodaTime

To convert JodaTime's org.joda.time.LocalDate to java.sql.Timestamp, just do

Timestamp timestamp = new Timestamp(localDate.toDateTimeAtStartOfDay().getMillis());

To convert JodaTime's org.joda.time.LocalDateTime to java.sql.Timestamp, just do

Timestamp timestamp = new Timestamp(localDateTime.toDateTime().getMillis());

JavaTime

To convert Java8's java.time.LocalDate to java.sql.Timestamp, just do

Timestamp timestamp = Timestamp.valueOf(localDate.atStartOfDay());

To convert Java8's java.time.LocalDateTime to java.sql.Timestamp, just do

Timestamp timestamp = Timestamp.valueOf(localDateTime);
Casto answered 24/1, 2012 at 19:3 Comment(6)
Watch out when converting LocalDateTime to DateTime as not all LocalDateTimes are valid DateTimes. Source: joda-time.sourceforge.net/faq.html#illegalinstant and just running into this.Scenery
got compile error on argument as valueOf() accepts a string.Upholstery
@Patriotic: That will only happen if you're actually not using Java SE 1.8 or newer. As indicated in the answer and in the provided links to the Javadoc (the blue texts in above answer are actually links, you can click them to drill down into the Javadoc), the Timestamp#valueOf() method accepts since Java SE 1.8 also a LocalDateTime.Casto
java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff];;;; I do Timestamp.valueOf(Timestamp(longtimestampppp).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().toString())Parvis
Just follow the last example in answer instead of doing toString() on it for no reason.Casto
can someone help me out with this? its not working #69533713 @CastoSuzisuzie
N
69

The best way use Java 8 time API:

  LocalDateTime ldt = timeStamp.toLocalDateTime();
  Timestamp ts = Timestamp.valueOf(ldt);

For use with JPA put in with your model (https://weblogs.java.net/blog/montanajava/archive/2014/06/17/using-java-8-datetime-classes-jpa):

@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime ldt) {
        return Timestamp.valueOf(ldt);
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp ts) {
        return ts.toLocalDateTime();
    }
}

So now it is relative timezone independent time. Additionally it is easy do:

  LocalDate ld = ldt.toLocalDate();
  LocalTime lt = ldt.toLocalTime();

Formatting:

 DateTimeFormatter DATE_TME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
 String str = ldt.format(DATE_TME_FORMATTER);
 ldt = LocalDateTime.parse(str, DATE_TME_FORMATTER);

UPDATE: postgres 9.4.1208, HSQLDB 2.4.0 etc understand Java 8 Time API without any conversations!

Naphthyl answered 7/1, 2015 at 21:54 Comment(2)
can someone help me out with this? its not working #69533713 @CastoSuzisuzie
Jesus Christ ... seems Java still messing with dates... I only wish to get the current date classic millis format ...Brotherinlaw
B
33

tl;dr

The Joda-Time project is in maintenance-mode, now supplanted by java.time classes.

  • Just use java.time.Instant class.
  • No need for:
    • LocalDateTime
    • java.sql.Timestamp
    • Strings

Capture current moment in UTC.

Instant.now()  

To store that moment in database:

myPreparedStatement.setObject( … , Instant.now() )  // Writes an `Instant` to database.

To retrieve that moment from datbase:

myResultSet.getObject( … , Instant.class )  // Instantiates a `Instant`

To adjust the wall-clock time to that of a particular time zone.

instant.atZone( z )  // Instantiates a `ZonedDateTime`

LocalDateTime is the wrong class

Other Answers are correct, but they fail to point out that LocalDateTime is the wrong class for your purpose.

In both java.time and Joda-Time, a LocalDateTime purposely lacks any concept of time zone or offset-from-UTC. As such, it does not represent a moment, and is not a point on the timeline. A LocalDateTime represents a rough idea about potential moments along a range of about 26-27 hours.

Use a LocalDateTime for either when the zone/offset is unknown (not a good situation), or when the zone-offset is indeterminate. For example, “Christmas starts at first moment of December 25, 2018” would be represented as a LocalDateTime.

Use a ZonedDateTime to represent a moment in a particular time zone. For example, Christmas starting in any particular zone such as Pacific/Auckland or America/Montreal would be represented with a ZonedDateTime object.

For a moment always in UTC, use Instant.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Apply a time zone. Same moment, same point on the timeline, but viewed with a different wall-clock time.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, different wall-clock time.

So, if I can just convert between LocalDate and LocalDateTime,

No, wrong strategy. If you have a date-only value, and you want a date-time value, you must specify a time-of-day. That time-of-day may not be valid on that date for a particular zone – in which case ZonedDateTime class automatically adjusts the time-of-day as needed.

LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 14 , 0 ) ;  // 14:00 = 2 PM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

If you want the first moment of the day as your time-of-day, let java.time determine that moment. Do not assume the day starts at 00:00:00. Anomalies such as Daylight Saving Time (DST) mean the day may start at another time such as 01:00:00.

ZonedDateTime zdt = ld.atStartOfDay( z ) ;

java.sql.Timestamp is the wrong class

The java.sql.Timestamp is part of the troublesome old date-time classes that are now legacy, supplanted entirely by the java.time classes. That class was used to represent a moment in UTC with a resolution of nanoseconds. That purpose is now served with java.time.Instant.

JDBC 4.2 with getObject/setObject

As of JDBC 4.2 and later, your JDBC driver can directly exchange java.time objects with the database by calling:

For example:

myPreparedStatement.setObject( … , instant ) ;

… and …

Instant instant = myResultSet.getObject( … , Instant.class ) ;

Convert legacy ⬌ modern

If you must interface with old code not yet updated to java.time, convert back and forth using new methods added to the old classes.

Instant instant = myJavaSqlTimestamp.toInstant() ;  // Going from legacy class to modern class.

…and…

java.sql.Timestamp myJavaSqlTimestamp = java.sql.Timestamp.from( instant ) ;  // Going from modern class to legacy class.

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Byrom answered 12/3, 2018 at 23:35 Comment(6)
As a side note: in the latest JDBC Specification version 4.3 there are no mentions on java.time.Instant in the "Appendix B" , where the "Data Type Conversion Tables" are presented. For example the PostgreSQL JDBC driver documentation explicitly states that java.time.Instant is not supported.Alithea
[Continued] Also the latest MySQL JDBC driver documentation doesn't mention Instant too on the reflated "Java - MySQL" Type mappings page.Alithea
[Continued] I am implementing a DAO method and initially wanted to use Instant as a parameter to the Spring's NamedParameterJdbcTemplate, but no results are returned when using it (latest MySQL database and driver). Unlike LocalDateTime which works flawlessly. We anyways have a global convention for storing all the date and time values in UTC , so I ended up using LocalDateTime for querying data (i.e. pass it as a parameter to NamedParameterJdbcTemplate) - it does the job without a problem.Alithea
All of this just to take the date and time ... Hope this become simple before I die. The apocalypse comes everytime someone ask about date in Java.Brotherinlaw
So... what's the purpose of someone wants the UTC time by default and then convert it to its timezone? It will be more intuitive to take Instant of my timezone and convert to UTC ONLY IF I WANT to do it. Less code. I think this class was codded by someone living in GreenwichBrotherinlaw
@MagnoC Not really so complicated. (a) If you want the current moment as seen in a particular time zone: ZonedDateTime.now( ZoneId.of( "America/Sao_Paulo" ) ). (b) UTC time (an offset of zero hours-minutes-seconds) should be used generally for logging, debugging, data storage, data exchange, and most business logic because it is precise, unambiguous, and not under the control of capricious politicians. Instant.now()Byrom
N
7

function call asStartOfDay() on java.time.LocalDate object returns a java.time.LocalDateTime object

Niggardly answered 15/3, 2019 at 14:3 Comment(1)
It's actually LocalDate.atStartOfDay(), rather than asStartOfDay()Lactose
L
5

Depending on your timezone, you may lose a few minutes (1650-01-01 00:00:00 becomes 1649-12-31 23:52:58)

Use the following code to avoid that

new Timestamp(localDateTime.getYear() - 1900, localDateTime.getMonthOfYear() - 1, localDateTime.getDayOfMonth(), localDateTime.getHourOfDay(), localDateTime.getMinuteOfHour(), localDateTime.getSecondOfMinute(), fractional);
Lakisha answered 10/4, 2012 at 23:12 Comment(0)
P
4

Since Joda is getting faded, someone might want to convert LocaltDate to LocalDateTime in Java 8. In Java 8 LocalDateTime it will give a way to create a LocalDateTime instance using a LocalDate and LocalTime. Check here.

public static LocalDateTime of(LocalDate date, LocalTime time)

Sample would be,

    // just to create a sample LocalDate
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
    LocalDate ld = LocalDate.parse("20180306", dtf);

    // convert ld into a LocalDateTime
    // We need to specify the LocalTime component here as well, it can be any accepted value
    LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00

Just for reference, For getting the epoch seconds below can be used,

    ZoneId zoneId = ZoneId.systemDefault();
    long epoch = ldt.atZone(zoneId).toEpochSecond(); 

    // If you only care about UTC
    long epochUTC = ldt.toEpochSecond(ZoneOffset.UTC);
Plumber answered 12/3, 2018 at 9:55 Comment(6)
No need to be using LocalDateTime at all here. That class purposely lacks any concept of time zone or offset-from-UTC. So it serves no useful purpose here. Instead: LocalDate.parse( “20180306” , DateTimeFormatter.BASIC_ISO_DATE ).atStartOfDay( ZoneId.of( “Africa/Tunis” ).toEpochSecond() Do not assume the day starts at 00:00, not always the case.Byrom
Whay do you mean by do not assume the day starts at 00.00Plumber
Anomalies such as Daylight Saving Time (DST) mean that on some dates in some places the day may start at another time, such as 01:00:00. So, rather than assume, let java.time determine the first moment by calling java.time.LocalDate.atStartOfDay to get a ZonedDateTime. See examples in my Answer. As I commented, the LocalDateTime class is useless and counter-productive in all this.Byrom
So with LocalDateTime we must use a ZoneId ?Plumber
I think you have missed all my points. Reread my Answer on this page. Search Stack Overflow to learn more from many more examples and discussions. But I'll say for the last time here: LocalDateTime is not appropriate to the problem at hand here. A LocalDateTime does not represent a moment. A LocalDateTime has nothing to do with any particular locality or time zone though the name may imply otherwise at first glance – learn more about the intention and details of this class. The LocalDateTime class does serve a purpose, but not the purpose seen in this Question.Byrom
It's just exactly what I was looking for. Just the convertion of LocalDateTime to LocalTime with the time part to 00:00:00. Excellent! And it answers the OP question without the noise of "don't use it", "use timeZone", etc. If someone wants to use LocalDateTime it's because really wants to and needs to.Nereidanereids
M
0

Java8 +

import java.time.Instant;
Instant.now().getEpochSecond(); //timestamp in seconds format (int)
Instant.now().toEpochMilli(); // timestamp in milliseconds format (long)
Mandymandych answered 5/12, 2018 at 7:0 Comment(2)
Useful, but don’t really seem to answer the question.Incurve
Thanks for the code, but it has nothing to do with the question.Demo

© 2022 - 2024 — McMap. All rights reserved.