如何在 JAVA 中将纪元转换为 mySQL 时间戳

Posted

技术标签:

【中文标题】如何在 JAVA 中将纪元转换为 mySQL 时间戳【英文标题】:How to convert epoch to mySQL timestamp in JAVA 【发布时间】:2013-10-05 12:22:28 【问题描述】:

如何获取mysqltimestamp中的mySQL时间戳格式?

long epochNow = System.currentTimeMillis()/1000;
long epochWeek = 604800;
long date7daysAgo = epochNo2013 w - epochWeek;
String mySQLtimestamp = /* 2013-09-23:50:00 */ 

【问题讨论】:

【参考方案1】:

java.time

随着 2014 年 3 月 Java SE 8 的发布,过时且容易出错的传统日期时间 API(java.util 日期时间类型及其格式类型,SimpleDateFormat 等)被java.time 取代,现代日期时间 API*。 following table 描述了 ANSI SQL 类型与 java.time 类型的映射:

ANSI SQL Java SE 8
DATE LocalDate
TIME LocalTime
TIMESTAMP LocalDateTime
TIME WITH TIMEZONE OffsetTime
TIMESTAMP WITH TIMEZONE OffsetDateTime

请注意,任何 JDBC 驱动程序都不支持 ZonedDateTimeInstant,而某些驱动程序例如PostgreSQL 也不支持OffsetTime / TIME [ WITHOUT TIMEZONE ]。另外,请注意,所有OffsetDateTime 实例都必须采用 UTC(偏移量为 0)。这是因为后端将它们存储为 UTC。

如何在JDBC中使用?

下面是一个示例代码,用于将 UTC 中的当前 OffsetDateTime 插入到 columnfooTIMESTAMP WITH TIMEZONE 类型)中:

OffsetDateTime odt = Instant.now().atOffset(ZoneOffset.UTC);
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, odt);
st.executeUpdate();
st.close();

Instant 表示时间线上的一个瞬时点,并且独立于时区,即它的时区偏移量为 +00:00 小时。

下面是从columnfoo 检索OffsetDateTime 的示例代码:

Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
while (rs.next()) 
    // Assuming the column index of columnfoo is 1
    OffsetDateTime odt = rs.getObject(1, OffsetDateTime.class));
    System.out.println(odt);

rs.close();
st.close();

以防万一您需要将 OffsetDateTime 转换为具有不同偏移量的另一个:

有几种方法可以做到这一点,但我主要使用OffsetDateTime#withOffsetSameInstant,将OffsetDateTime 转换为具有不同时区偏移量的另一个,例如

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main 
    public static void main(String[] args) 
        // A sample OffsetDateTime in UTC.
        OffsetDateTime odt = Instant.now().atOffset(ZoneOffset.UTC);
        System.out.println(odt);

        OffsetDateTime offsetTimeAtOffset0100 = odt.withOffsetSameInstant(ZoneOffset.of("+02:00"));
        System.out.println(offsetTimeAtOffset0100);

        // Time at JVM's default timezone offset
        ZoneOffset jvmTzOffset = ZonedDateTime.now(ZoneId.systemDefault()).getOffset();
        OffsetDateTime offsetTimeAtJvmTzOffset = odt.withOffsetSameInstant(jvmTzOffset);
        System.out.println(offsetTimeAtJvmTzOffset);
    

输出:

2021-05-29T13:36:15.258076Z
2021-05-29T15:36:15.258076+02:00
2021-05-29T14:36:15.258076+01:00

与上面给出的代码相关的几点:

    输出中的Z 是零时区偏移的timezone designator。它代表 Zulu,并指定 Etc/UTC 时区(时区偏移量为 +00:00 小时)。 代码将odt 转换为OffsetDateTime 的两个实例——每个实例都以不同的方式。第一个实例具有固定的时区偏移量+02:00 小时,而第二个实例具有 JVM 的时区偏移量。请注意,观察DST 的地方的时区偏移量会根据夏季/冬季时间而变化。因此,如果一个地方遵守 DST,而不是使用固定的时区偏移量,例如+02:00小时;我们应该从 API 中获取它。 我的 JVM 时区是 Europe/London,目前它的偏移量是 +01:00 小时。

通过 Trail: Date Time 了解有关 modern date-time API* 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。

【讨论】:

【参考方案2】:

为什么不一直使用普通的Date

Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, -7);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
String output = formatter.format(cal.getTime());

【讨论】:

期望的输出是(String) "29-09-2013 23:50:00" @Ultra:我改变了答案。但是默认的 SQL 日期时间格式是2013-09-29 23:50:00 您是对的,但您的解决方案返回错误的日期:265-09-2013 19:07:16 但使用SimpleDateFormat("yyyy-MM-dd HH:mm:ss") 重新格式化很容易

以上是关于如何在 JAVA 中将纪元转换为 mySQL 时间戳的主要内容,如果未能解决你的问题,请参考以下文章

在mysql中将纪元数转换为人类可读的日期

如何在 python 中将 1970 年前的日期转换为纪元? [复制]

如何在 Perl 中将日期转换为纪元时间?

如何在 python 中将普通时间戳转换为纪元时间戳

如何在python中将日期转换为纪元时间[重复]

如何在 Perl 中将纪元时间转换为正常时间?