1. Overview

Handling timestamps in Java is a common task that allows us to manipulate and display date and time information more еffеctivеly еspеcially when we’re dealing with databases or global applications. Two fundamental classes for handling timestamps and timezones are java.sql.Timestamp and org.joda.time.DateTime.

In this tutorial, we’ll look at various approaches to converting between org.joda.time.DateTime and java.sql.Timestamp.

2. Converting java.sql.Timestamp to org.joda.time.DateTime

First, we’ll look into multiple approaches to converting java.sql.Timestamp to org.joda.time.DateTime.

2.1. Using Constructor

One of the simplest approaches to convert java.sql.Timestamp to org.joda.time.DateTime involves using the constructor. In this approach, we’ll use the getTime() method to get the milliseconds since the Unix epoch and provide this value as input to the DateTime constructor.

Let’s look at how we can use the getTime() method:

DateTime convertToDateTimeUsingConstructor(Timestamp timestamp) {
    return new DateTime(timestamp.getTime());
}

Let’s see the following test code:

public void givenTimestamp_whenUsingConstructor_thenConvertToDateTime() {
    long currentTimeMillis = System.currentTimeMillis();
    Timestamp timestamp = new Timestamp(currentTimeMillis);
    DateTime expectedDateTime = new DateTime(currentTimeMillis);
    DateTime convertedDateTime = DateTimeAndTimestampConverter.convertToDateTimeUsingConstructor(timestamp);
    assertEquals(expectedDateTime, convertedDateTime);
}

2.2. Using the Instant class

The easiest way to think of the Instant class is as a single moment in the UTC zone. If we think of time as a line, Instant represents a single point on the line.

Under the hood, the Instant class is just counting the number of seconds and nanoseconds relative to the standard Unix epoch time of January 1, 1970, at 00:00:00. This point in time is denoted by 0 seconds and 0 nanoseconds, and everything else is just an offset from it.

Storing the number of seconds and nanoseconds relative to this specific time point allows the class to store negative and positive offsets. In other words, the Instant class can represent times before and after the epoch time.

Let’s look at how we can work with the Instant class to convert a Timestamp to DateTime:

DateTime convertToDateTimeUsingInstant(Timestamp timestamp) {
    Instant instant = timestamp.toInstant();
    return new DateTime(instant.toEpochMilli());
}

In the above method, we convert the provided timestamp to an Instant by using the toInstant() method of the Timestamp class, which represents a moment on the timeline in UTC. Then, we use the toEpcohMilli() method on the Instant object to get the number of milliseconds since the Unix epoch.

Let’s test this method by using the system’s current milliseconds:

@Test
public void givenTimestamp_whenUsingInstant_thenConvertToDateTime() {
    long currentTimeMillis = System.currentTimeMillis();
    Timestamp timestamp = new Timestamp(currentTimeMillis);
    DateTime expectedDateTime = new DateTime(currentTimeMillis);
    DateTime convertedDateTime = DateTimeAndTimestampConverter.convertToDateTimeUsingInstant(timestamp);
    assertEquals(expectedDateTime, convertedDateTime);
}

2.3. Using the LocalDateTime class

The java.timе packagе was introduced in Java 8 and offers a modern date and time API. LоcalDatеTimе is one of the classes in this packagе, which can store and manipulate data and time of different timezones. Let’s take a look at this approach:

DateTime convertToDateTimeUsingLocalDateTime(Timestamp timestamp) {
    LocalDateTime localDateTime = timestamp.toLocalDateTime();
    return new DateTime(localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}

The toLocalDateTime() method of the Timestamp class converts the Timestamp to a LocalDateTime, which represents a date and time without timezone information. Let’s take a look at this approach:

@Test
public void givenTimestamp_whenUsingLocalDateTime_thenConvertToDateTime() {
    long currentTimeMillis = System.currentTimeMillis();
    Timestamp timestamp = new Timestamp(currentTimeMillis);
    DateTime expectedDateTime = new DateTime(currentTimeMillis);
    DateTime convertedDateTime = DateTimeAndTimestampConverter.convertToDateTimeUsingLocalDateTime(timestamp);
    assertEquals(expectedDateTime, convertedDateTime);
}

3. Converting org.joda.time.DateTime to java.sql.Timestamp

Now, we’ll look into multiple approaches to converting org.joda.time.DateTime to java.sql.Timestamp.

3.1. Using Constructor

We can also use the Timestamp constructor to convert org.joda.time.DateTime to java.sql.Timestamp. Here, we’ll use the getMillis() method of the DateTime class which will return the number of milliseconds since the Unix epoch, and then provide this value to the Timestamp constructor.

Let’s look at how we can use the getMillis() method:

Timestamp convertToTimestampUsingConstructor(DateTime dateTime) {
    return new Timestamp(dateTime.getMillis());
}

Now, let’s test this approach:

@Test
public void givenDateTime_whenUsingConstructor_thenConvertToTimestamp() {
    long currentTimeMillis = System.currentTimeMillis();
    DateTime dateTime = new DateTime(currentTimeMillis);
    Timestamp expectedTimestamp = new Timestamp(currentTimeMillis);
    Timestamp convertedTimestamp = DateTimeAndTimestampConverter.convertToTimestampUsingConstructor(dateTime);
    assertEquals(expectedTimestamp, convertedTimestamp);
}

3.2. Using the Instant class

Let’s look at how we can use the Instant class to convert the DateTime to java.sql.Timestamp:

Timestamp convertToTimestampUsingInstant(DateTime dateTime) {
    Instant instant = Instant.ofEpochMilli(dateTime.getMillis());
    return Timestamp.from(instant);
}

In the above method, we converted the provided dateTime to an Instant by providing the number of milliseconds since the Unix epoch. After that, we get the Timestamp from an Instant object using the Timestamp’s constructor.

Let’s see the following test code:

@Test
public void givenDateTime_whenUsingInstant_thenConvertToTimestamp() {
    long currentTimeMillis = System.currentTimeMillis();
    DateTime dateTime = new DateTime(currentTimeMillis);
    Timestamp expectedTimestamp = new Timestamp(currentTimeMillis);
    Timestamp convertedTimestamp = DateTimeAndTimestampConverter.convertToTimestampUsingInstant(dateTime);
    assertEquals(expectedTimestamp, convertedTimestamp);
}

3.3. Using the LocalDateTime class

Let’s use the LocalDateTime class to convert the DateTime to java.sql.Timestamp:

Timestamp convertToTimestampUsingLocalDateTime(DateTime dateTime) {
    Instant instant = Instant.ofEpochMilli(dateTime.getMillis());
    LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    return Timestamp.valueOf(localDateTime);
}

In the above method, we converted the provided dateTime to an Instant by providing the number of milliseconds since the Unix epoch. LocalDateTime represents a date and time without a timezone. After this, we retrieve the system default time zone using the ZoneId.systemDefault() to ensure that the LocalDateTime is created using the local time zone settings.

Now, let’s run our test:

@Test
public void givenDateTime_whenUsingLocalDateTime_thenConvertToTimestamp() {
    long currentTimeMillis = System.currentTimeMillis();
    DateTime dateTime = new DateTime(currentTimeMillis);
    Timestamp expectedTimestamp = new Timestamp(currentTimeMillis);
    Timestamp convertedTimestamp = DateTimeAndTimestampConverter.convertToTimestampUsingLocalDateTime(dateTime);
    assertEquals(expectedTimestamp, convertedTimestamp);
}

4. Conclusion

In this quick tutorial, we learned how to convert between org.joda.time.DateTime to java.sql.Timestamp classes in Java.

As always, the code used in this article can be found over on GitHub.