156

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!

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756
  • 2
    FYI, the [*Joda-Time*](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [*java.time*](http://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). Also, the `java.sql.Timestamp` class is now legacy, supplanted by the *java.time* classes, specifically by [`Instant`](https://docs.oracle.com/javase/9/docs/api/java/time/Instant.html). – Basil Bourque Mar 13 '18 at 05:46

7 Answers7

315

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);
Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Watch out when converting `LocalDateTime` to `DateTime` as not all `LocalDateTime`s are valid `DateTime`s. Source: http://joda-time.sourceforge.net/faq.html#illegalinstant and just running into this. – Christophe De Troyer Aug 10 '15 at 08:53
  • 1
    got compile error on argument as valueOf() accepts a string. – Patriotic Jul 03 '20 at 17:32
  • 1
    @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`. – BalusC Jul 03 '20 at 22:21
  • 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())` – Dr.jacky Mar 11 '21 at 13:43
  • 1
    Just follow the last example in answer instead of doing `toString()` on it for no reason. – BalusC Mar 11 '21 at 13:51
  • can someone help me out with this? its not working https://stackoverflow.com/questions/69533213/java-jdbctemplate-insert-localdatetime-to-sqlserver-datetime-column-not-working @BalusC – mattsmith5 Oct 12 '21 at 05:15
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!

ScottM
  • 620
  • 7
  • 20
Grigory Kislin
  • 16,647
  • 10
  • 125
  • 197
  • can someone help me out with this? its not working https://stackoverflow.com/questions/69533213/java-jdbctemplate-insert-localdatetime-to-sqlserver-datetime-column-not-working @BalusC – mattsmith5 Oct 12 '21 at 05:16
  • Jesus Christ ... seems Java still messing with dates... I only wish to get the current date classic millis format ... – Magno C Nov 03 '22 at 18:47
32

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • As a side note: in the latest JDBC Specification [version 4.3](https://download.oracle.com/otn-pub/jcp/jdbc-4_3-mrel3-eval-spec/jdbc4.3-fr-spec.pdf?AuthParam=1649214958_4adf759a80a29816780b1ff20d1d6677) 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](https://jdbc.postgresql.org/documentation/head/java8-date-time.html) explicitly states that `java.time.Instant` is not supported. – informatik01 Apr 06 '22 at 03:29
  • [Continued] Also the latest MySQL JDBC driver documentation doesn't mention `Instant` too on the reflated "Java - MySQL" Type [mappings page](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-type-conversions.html). – informatik01 Apr 06 '22 at 03:40
  • [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. – informatik01 Apr 06 '22 at 03:42
  • 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. – Magno C Nov 03 '22 at 18:50
  • 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 Greenwich – Magno C Nov 03 '22 at 18:58
  • @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()` – Basil Bourque Nov 03 '22 at 19:43
7

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

Ahmad sibai
  • 147
  • 2
  • 4
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);
user1302021
  • 51
  • 1
  • 1
3

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);
prime
  • 14,464
  • 14
  • 99
  • 131
  • 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. – Basil Bourque Mar 12 '18 at 17:03
  • Whay do you mean by do not assume the day starts at 00.00 – prime Mar 13 '18 at 01:57
  • 1
    Anomalies such as [Daylight Saving Time (DST)](https://en.wikipedia.org/wiki/Daylight_saving_time) 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`](https://docs.oracle.com/javase/9/docs/api/java/time/LocalDate.html#atStartOfDay-java.time.ZoneId-) to get a `ZonedDateTime`. See examples in [my Answer](https://stackoverflow.com/a/49246027/642706). As I commented, the `LocalDateTime` class is useless and counter-productive in all this. – Basil Bourque Mar 13 '18 at 03:54
  • So with `LocalDateTime` we must use a `ZoneId` ? – prime Mar 13 '18 at 05:01
  • 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. – Basil Bourque Mar 13 '18 at 05:40
  • 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. – Fer B. Jun 08 '20 at 22:47
0

Java8 +

import java.time.Instant;
Instant.now().getEpochSecond(); //timestamp in seconds format (int)
Instant.now().toEpochMilli(); // timestamp in milliseconds format (long)
piet.t
  • 11,718
  • 21
  • 43
  • 52
Mohamed.Abdo
  • 2,054
  • 1
  • 19
  • 12