-1

I found no way to insert date/time into MySQL database in a standard zone like UTC.

The following segment of code authenticates a user by using Apache DBCP.

public final class AuthenticationDAO {

    public boolean isAuthenticated(String userName, String password) throws SQLException {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        boolean status = false;

        try {
            connection = DatabaseConnection.getConnection();
            preparedStatement = connection.prepareStatement("select * from admin_tbl where lower(admin_id)=lower(?) and BINARY password=?");
            preparedStatement.setString(1, userName);
            preparedStatement.setString(2, password);
            resultSet = preparedStatement.executeQuery();
            status = resultSet.next();

            if (status) {
                preparedStatement = connection.prepareStatement("update admin_tbl set last_login=? where lower(admin_id)=lower(?) and BINARY password=?");
                preparedStatement.setTimestamp(1, new Timestamp(new Date().getTime())); // java.util.Date / java.sql.Timestamp
                preparedStatement.setString(2, userName);
                preparedStatement.setString(3, password);
                preparedStatement.executeUpdate();
            }
        } finally {
            if (connection != null) {connection.close();}
            if (resultSet != null) {resultSet.close();}
            if (preparedStatement != null) {preparedStatement.close();}
        }
        return status;
    }
}

Only one line of this code will be of our interest.

preparedStatement.setTimestamp(1, new Timestamp(new Date().getTime()));

This line updates the login date/time, when a login attempt by a user/admin is successful. The column last_login in MySQL is of type DATETIME.


I want to insert date/time in UTC zone in MySQL that doesn't happen. It appears that it takes a local zone.

By any means, is it possible to insert date/time into MySQL in UTC zone? Any data type in Java and/or MySQL may be suggested - not only which I'm presenting here.

4

2 回答 2

3

您可以在两个地方为您的 mySQL 数据设置时区:全局配置和会话配置。你不能指定 mysql '这个日期是 GMT,但这个日期是 EST'。您必须将它们转换为公共时区。

最佳实践是将您的服务器设置为特定时区 [例如:GMT],并​​确保您在存储期间相应地转换日期/时间。实际上,所有后端数据都应该使用一个时区,并且任何转换都应该在输出之前立即进行。

于 2013-10-16T22:11:55.340 回答
2

Date在 Java 中与时区无关。它始终采用 UTC(默认情况下且始终如此)。因此,DateorTimestamp本身不是原因,而是当Date/Timestamp通过 JDBC 驱动程序传递到数据库时,它根据 JVM 时区解释日期/时间,而 JVM 时区又默认为系统时区(本机操作系统时区)。

因此,除非 MySQL JDBC 驱动程序被显式强制使用 UTC 区域或 JVM 本身设置为使用该区域,否则它不会使用 UTC 将Date/存储Timestamp到目标数据库中,即使 MySQL 本身被配置为使用 UTC 使用default_time_zone='+00:00'inmy.inimy.cnf[mysqld]节中。像 Oracle 这样的一些数据库可能支持带时区的时间戳,这可能是我不熟悉的一个例外(未经测试,因为我目前没有那个环境)。

void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException

使用给定的 Calendar 对象将指定的参数设置为给定的java.sql.Timestamp值。驱动程序使用 Calendar 对象构造一个 SQLTIMESTAMP值,然后驱动程序将其发送到数据库。使用 Calendar 对象,驱动程序可以在考虑自定义时区的情况下计算时间戳。如果未Calendar指定对象,则驱动程序使用默认时区,即运行应用程序的虚拟机的时区

java.sql.PreparedStatement对于在类中处理日期时间的其他相关 getter 和 setter 方法,也提到了同样的事情。

setTimestampInternal()这可以通过检查MySQL JDBC 驱动程序实现的方法调用来进一步澄清。

请参阅从方法的两个重载版本中对该方法的以下两个调用。setTimestampInternal()setTimestamp()

/**
 * Set a parameter to a java.sql.Timestamp value. The driver converts this
 * to a SQL TIMESTAMP value when it sends it to the database.
 *
 * @param parameterIndex the first parameter is 1...
 * @param x the parameter value
 *
 * @throws SQLException if a database access error occurs
 */
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
    setTimestampInternal(parameterIndex, x, this.connection.getDefaultTimeZone());
}

/**
 * Set a parameter to a java.sql.Timestamp value. The driver converts this
 * to a SQL TIMESTAMP value when it sends it to the database.
 *
 * @param parameterIndex the first parameter is 1, the second is 2, ...
 * @param x the parameter value
 * @param cal the calendar specifying the timezone to use
 *
 * @throws SQLException if a database-access error occurs.
 */
public void setTimestamp(int parameterIndex, java.sql.Timestamp x,Calendar cal) throws SQLException {
    setTimestampInternal(parameterIndex, x, cal.getTimeZone());
}

因此,当没有Calendar使用该PreparedStatement#setTimestamp()方法指定实例时,将使用默认时区 ( this.connection.getDefaultTimeZone()) 或使用提供Calendar实例的指定时区 ( cal.getTimeZone())。

因此,只需将实例java.util.Calendar或其子类java.util.GregorianCalendar传递给PreparedStatement#setTimestamp()您感兴趣的适当时区(我们感兴趣的 UTC)。

Timestamp timestamp = new Timestamp(new java.util.Date().getTime());
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

preparedStatement.setTimestamp(1, timestamp, calendar);

指定的时区将用于Timestamp在将其传递给基础数据库之前生成所提供的字符串表示形式。


如果您碰巧处理了诸如 Hibernate、EclipseLink 之类的 ORM 框架以及使用适当的数据源在应用程序服务器/Servlet 容器中创建连接池,那么请参考此答案,该答案基于该答案并直接从中复制。

于 2016-01-11T19:40:14.443 回答