0

In a MySQL database table, there is column named loginTime and its type is timestamp. Its value is 2023-02-14 10:02:26.

when I get the value to date type variable using java and I get value as 2023-02-14 10:02. How can I get the date with seconds also. As same as the database. I tried but still unable to find solution.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
WCM
  • 595
  • 3
  • 11
  • 27
  • 1
    Retrieve into an `OffsetDateTime`. See for example [this good answer by Arvind Kumar Avinash](https://stackoverflow.com/a/67505173/5772882) (the question is about the opposite problem, but the answer does cover both. Since a MySQL `timestamp` is always in UTC, `OffsetDateTime` should be the right class to use in Java, but you may have to experiment a little. – Ole V.V. Mar 23 '23 at 09:36
  • *when I get the value to date type variable using java and I get value as 2023-02-14 10:02.* That shouldn't be happening. `java.sql.Date` shouldn't even give you *any* time. `rs.getTimestamp(0).toLocalDateTime()` is the sort of thing you need – g00se Mar 23 '23 at 12:27
  • @g00se That’s an improvement. It’s still better to avoid the `Timestamp` class completely: `rs.getObject(0, LocalDateTime.class)` (assuming JDBC 4.2 or later). – Ole V.V. Mar 23 '23 at 17:47
  • @OleV.V. Oh yes, I forgot, thanks. – g00se Mar 23 '23 at 18:00
  • 1
    @OleV.V. Your second comment using `LocalDateTime` contradicts your first comment using `OffsetDateTime`. (the first comment being the correct usage) – Basil Bourque Mar 24 '23 at 07:00

2 Answers2

3

tl;dr

Correct modern solution:

myResultSet.getObject( … , OffsetDateTime.class )  // Returns an `java.time.OffsetDateTime` object.

You said:

column named loginTime and its type is timestamp. Its value is 2023-02-14 10:02:26.

No, you are incorrect. The TIMESTAMP type represents a date with time-of-day as seen in UTC. Your reported value lacks the indication of an offset from UTC of zero, which is vital info.

Details

The accepted Answer is ill-advised in three ways:

  • The first part uses terribly flawed legacy date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
  • The second part employs the LocalDateTime class. LocalDateTime is the wrong class to use here. The TIMESTAMP data type in MySQL is a date with time as seen in UTC. The LocalDateTime lacks any concept of offset, so that solution tragically discards valuable information. Note earlier Comment by Ole V.V.
  • Both parts focus on parsing text retrieved from the database. Instead, date-time column values should be retrieved into date-time types in Java. No need to resort to text.

First step is to read the documentation for the TIMESTAMP data type in MySQL 8.0. To quote:

The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.

Those mentions of “UTC” are vital. That term is an abbreviation meaning “with an offset from the temporal meridian of UTC of zero hours-minutes-seconds”.

In the SQL Standard, this type is equivalent to TIMESTAMP WITH TIME ZONE (where the Standard authors incorrectly used the term “time zone” where they meant “offset”).

java.time.OffsetDateTime

So the appropriate Java type mapped to such a column in the JDBC 4.2+ specification is OffsetDateTime.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

To write such a value to the database, pass your OffsetDateTime object to PreparedStatement#setObject.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

You most probably need to include the timestamp class which allows the JDBC API to identify a java.util.Date object as an SQL TIMESTAMP value. Here we set a timestamp value to include fractional seconds and display this:

// old classes and approach in use here, read on for more 
import java.sql.Timestamp;
import java.text.SimpleDateFormat;

public class TimestampExample {
    public static void main(String[] args) {
        try {
            String timestampStr = "2023-02-14 10:02:26.123";
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
            Timestamp loginTime = new Timestamp(dateFormat.parse(timestampStr).getTime());
            System.out.println("loginTime: " + loginTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Added: Here is an alternative using Java.time (see comments under answer)

// don't use this approach if the source data has embedded time zone information 
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class TimestampExample {
    public static void main(String[] args) {
        try {
            String timestampStr = "2023-02-14 10:02:26.123";
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
            LocalDateTime loginTime = LocalDateTime.parse(timestampStr, formatter);
            System.out.println("loginTime: " + loginTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

There was never an intent to focus on handling date/time information as text, the snippets above were simply designed to easily visualize sub-second precision. Based on the rolling wave of advice from the comments I'll presume that something along the following lines will more correctly handle a MySQL "timestamp".

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.time.OffsetDateTime;

public class TimestampExample {
    public static void main(String[] args) {
        try {
            // Assume the connection has been established

            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT login_time FROM users WHERE id = 1");

            if (rs.next()) {
                OffsetDateTime loginTime = rs.getObject("login_time", OffsetDateTime.class);
                System.out.println("loginTime: " + loginTime);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

this variant is untested

Paul Maxwell
  • 33,002
  • 3
  • 32
  • 51
  • that's the point, if it comes as date the your loose precision, are you saying you cannot use the timestamp suggestion? – Paul Maxwell Mar 23 '23 at 07:58
  • can you just use getString ? Maybe you should include a script snippet on how you get the data now (IN the QUESTION please, not here, use the Edit seen under the tags of your question). – Paul Maxwell Mar 23 '23 at 08:02
  • 4
    Please don’t teach the young ones to use the poorly designed, troublesome and long outdated `SimpleDateFormat` and `Timestamp` classes. Use [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/index.html) and [JDBC 4.2](https://stackoverflow.com/a/67505173/5772882), which supports java.time types. – Ole V.V. Mar 23 '23 at 09:38
  • 2
    Thanks for extending the answer with the modern version of the code, which, as I said, is certainly recommended over the old one. Another point, retrieving a timestamp as a string from the database is the second best way at best. Prefer to retrieve a proper date-time object such as an `OffsetDateTime`, an `Instant` or if all else fails, then a `LocalDateTime`. – Ole V.V. Mar 23 '23 at 13:57
  • 1
    `LocalDateTime` is the wrong class to use here. The `TIMESTAMP` data type in MySQL is a date with time as seen in UTC. The `LocalDateTime` lacks any concept of offset, so you are tragically discarding valuable information. I must down-vote for being incorrect. – Basil Bourque Mar 24 '23 at 06:09
  • 1
    third variant added to "answer" (which I am now unable to delete) – Paul Maxwell Mar 24 '23 at 07:16