杰瑞科技汇

Java SQL Timestamp 如何正确处理时间?

Of course! The java.sql.Timestamp class is a core part of the JDBC API for interacting with SQL databases. It's a specific subclass of java.util.Date designed to handle both date and time information with nanosecond precision.

Java SQL Timestamp 如何正确处理时间?-图1
(图片来源网络,侵删)

Here's a comprehensive guide covering what it is, how to use it, and its important nuances.


What is java.sql.Timestamp?

java.sql.Timestamp represents a specific point in time, accurate to the nanosecond. It was created to bridge the gap between Java's date/time objects and SQL's TIMESTAMP data type, which can store date, time, and fractional seconds.

Key Characteristics:

  • Extends java.util.Date: It inherits the basic date and time functionality from Date.
  • Nanosecond Precision: It stores time with nanosecond accuracy (up to 9 digits), whereas java.util.Date is only precise to milliseconds.
  • Legacy API: It's part of the older java.sql package and is considered legacy. For new Java code, the modern java.time package (introduced in Java 8) is strongly recommended.

Core Constructors and Methods

Constructors

  1. Timestamp(long time)

    Java SQL Timestamp 如何正确处理时间?-图2
    (图片来源网络,侵删)
    • Creates a Timestamp object from a millisecond value (since the standard base time of "the epoch": January 1, 1970, 00:00:00 GMT).
    • Important: This constructor truncates the nanoseconds to milliseconds. If you need nanosecond precision, use the setNanos() method after construction.
    long millis = System.currentTimeMillis();
    Timestamp ts1 = new Timestamp(millis);
  2. Timestamp(int year, int month, int date, int hour, int minute, int second, int nano)

    • Creates a Timestamp object from individual date and time components.
    • Note: The month is 0-indexed (0 = January, 11 = December).
    // Creates 2025-10-27 14:30:00.123456789
    Timestamp ts2 = new Timestamp(2025 - 1900, 10 - 1, 27, 14, 30, 0, 123456789);

Key Methods

  • long getTime(): Returns the number of milliseconds since the epoch. This method is inherited from java.util.Date.

  • void setTime(long time): Sets the timestamp based on a millisecond value.

  • int getNanos(): Returns the nanosecond value (0-999,999,999).

    Java SQL Timestamp 如何正确处理时间?-图3
    (图片来源网络,侵删)
  • void setNanos(int n): Sets the nanosecond value. The value n must be between 0 and 999,999,999.

  • static Timestamp valueOf(String s): Parses a String into a Timestamp. The expected format is yyyy-MM-dd hh:mm:ss.fffffffff (where f represents nanoseconds).

    String timestampString = "2025-10-27 15:45:30.123";
    Timestamp ts3 = Timestamp.valueOf(timestampString);

Practical Usage with JDBC

This is the primary use case for java.sql.Timestamp.

Setting a Timestamp in a PreparedStatement

When you need to insert or update a TIMESTAMP or DATETIME column in a database, you use the setTimestamp() method.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
public class JdbcTimestampExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String user = "user";
        String password = "password";
        String sql = "INSERT INTO events (event_name, event_time) VALUES (?, ?)";
        try (Connection conn = DriverManager.getConnection(url, user, password);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            // 1. Create a Timestamp object
            Timestamp now = new Timestamp(System.currentTimeMillis());
            // 2. Set parameters for the PreparedStatement
            pstmt.setString(1, "Java Conference");
            pstmt.setTimestamp(2, now); // This is the key method!
            // 3. Execute the update
            int rowsInserted = pstmt.executeUpdate();
            if (rowsInserted > 0) {
                System.out.println("A new event was inserted successfully!");
                System.out.println("Timestamp used: " + now);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Getting a Timestamp from a ResultSet

When you retrieve a TIMESTAMP or DATETIME column from a database, you use the getTimestamp() method.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
public class JdbcGetTimestampExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String user = "user";
        String password = "password";
        String sql = "SELECT event_name, event_time FROM events WHERE event_id = ?";
        try (Connection conn = DriverManager.getConnection(url, user, password);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, 1); // Let's get the event with ID 1
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    String eventName = rs.getString("event_name");
                    // This is the key method to get the timestamp!
                    Timestamp eventTime = rs.getTimestamp("event_time");
                    System.out.println("Event Name: " + eventName);
                    System.out.println("Event Time: " + eventTime);
                    System.out.println("Raw Milliseconds: " + eventTime.getTime());
                    System.out.println("Nanoseconds: " + eventTime.getNanos());
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

The Modern Alternative: java.time (Java 8+)

java.sql.Timestamp has several well-known issues:

  • Mutable: Its state can be changed after creation, which is bad practice for value objects.
  • Confusing API: Mixing milliseconds and nanoseconds can lead to bugs.
  • Poor Design: Extending java.util.Date was a mistake, as it exposed legacy, confusing methods like getYear() and getMonth().

Since Java 8, the java.time package provides a much better, immutable, and thread-safe API.

Key java.time Classes

  • java.time.LocalDateTime: Represents a date and time without a time zone (e.g., 2025-10-27T10:15:30). This is the most common mapping for SQL TIMESTAMP.
  • java.time.Instant: Represents a point on the timeline in UTC (e.g., 2025-10-27T17:15:30.123456789Z).
  • java.time.ZonedDateTime: Represents a date and time with a specific time zone.

How to Use java.time with JDBC

JDBC 4.2 and later added direct support for java.time types, making it the recommended approach.

Setting a LocalDateTime in a PreparedStatement:

import java.sql.*;
import java.time.LocalDateTime;
// ... (Connection setup)
LocalDateTime now = LocalDateTime.now();
// Use setObject for the modern types
pstmt.setObject(2, now); // Works with JDBC 4.2+

Getting a LocalDateTime from a ResultSet:

// ... (ResultSet setup)
// Use getObject to retrieve the modern type
LocalDateTime eventTime = rs.getObject("event_time", LocalDateTime.class);

Conversion Between Timestamp and java.time

Sometimes you have to work with legacy code or libraries that use Timestamp. Here’s how to convert:

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.Instant;
// --- From Timestamp to java.time ---
// To LocalDateTime (loses time zone information, but is common for DBs)
Timestamp ts = new Timestamp(System.currentTimeMillis());
LocalDateTime ldt = ts.toLocalDateTime();
// To Instant (preserves all information)
Instant instant = ts.toInstant();
// --- From java.time to Timestamp ---
// From LocalDateTime
LocalDateTime ldtNow = LocalDateTime.now();
Timestamp tsFromLdt = Timestamp.valueOf(ldtNow);
// From Instant
Instant instantNow = Instant.now();
Timestamp tsFromInstant = Timestamp.from(instantNow);

Summary: java.sql.Timestamp vs. java.time

Feature java.sql.Timestamp (Legacy) java.time (Modern)
Package java.sql java.time
Immutability Mutable Immutable
Thread Safety Not thread-safe Thread-safe
Precision Nanoseconds Nanoseconds
API Clarity Confusing, mixes millis/nanos Clear, well-designed
JDBC Support Native (setTimestamp, getTimestamp) Native (JDBC 4.2+) (setObject, getObject)
Recommendation Avoid for new code. Use only when interfacing with legacy APIs or older JDBC drivers. Strongly recommended for all new Java applications.

Final Advice:

  • For new projects: Use java.time objects (LocalDateTime, Instant, etc.) throughout your application.
  • For JDBC interactions: Use pstmt.setObject() and rs.getObject() with your java.time objects.
  • Only use java.sql.Timestamp: When you absolutely must, such as when calling a legacy API that requires it or when using a very old JDBC driver that doesn't support java.time.
分享:
扫描分享到社交APP
上一篇
下一篇