Java 提供了两个日期与时间处理API:旧的 java.util.Date
和 java.util.Calendar
,以及新的 java.time
包。新的 API 以 Instant
、LocalDateTime
等为核心,具有更清晰的设计和更强大的功能。除非你需要与遗留代码进行交互,否则建议使用新的 API。在需要将新旧 API 进行转换时,了解如何在这两者之间互相转换就显得尤为重要。
1. 旧 API 转 新 API
1.1 Date
转 Instant
和 ZonedDateTime
Java 8 之前的 java.util.Date
和 java.util.Calendar
对象可以通过 toInstant()
方法转换为新的 Instant
对象。Instant
表示一个瞬时点,之后可以通过它来生成 ZonedDateTime
,进一步获取包含时区信息的时间。
示例:
java
// Date -> Instant
Instant ins1 = new Date().toInstant();
// Calendar -> Instant -> ZonedDateTime
Calendar calendar = Calendar.getInstance();
Instant ins2 = calendar.toInstant();
ZonedDateTime zdt = ins2.atZone(calendar.getTimeZone().toZoneId());
在这段代码中,calendar.getTimeZone().toZoneId()
将旧的 TimeZone
对象转换为新的 ZoneId
对象。
1.2 旧 API 的 TimeZone 转 ZoneId
我们还可以注意到,旧版 TimeZone
类提供了 toZoneId()
方法,它允许将旧时区转换为新的时区 ID。这是迁移代码时很常用的技巧。
2. 新 API 转 旧 API
2.1 ZonedDateTime 转 long 和 Date
当需要将新的 ZonedDateTime
对象转换为旧的 Date
或 Calendar
对象时,我们可以使用 ZonedDateTime.toEpochSecond()
方法将 ZonedDateTime
转换为秒级时间戳,然后将其转化为 long
类型,再进行转换。
示例:
java
// ZonedDateTime -> long (秒级时间戳)
ZonedDateTime zdt = ZonedDateTime.now();
long ts = zdt.toEpochSecond() * 1000; // 转换为毫秒
// long -> Date
Date date = new Date(ts);
// long -> Calendar
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
calendar.setTimeInMillis(ts);
2.2 ZoneId 转 TimeZone
在新 API 中,ZoneId
表示时区信息,而在旧 API 中则是 TimeZone
。我们可以通过 ZoneId.getId()
获取时区的 ID 字符串,再使用它来创建旧的 TimeZone
对象。
3. 在数据库中存储日期和时间
3.1 数据库日期时间类型
数据库中通常使用几种不同类型的字段来存储日期和时间:
-
DATETIME:存储日期和时间。
-
DATE:仅存储日期。
-
TIME:仅存储时间。
-
TIMESTAMP:类似
DATETIME
,但数据库在创建或更新记录时会自动更新此字段。
3.2 数据库与 Java 类型的映射
在使用 Java 操作数据库时,常常需要将数据库中的日期和时间类型映射到 Java 类。以下是常见的数据库日期时间类型与 Java 类的映射关系:
数据库类型 | 对应 Java 类(旧 API) | 对应 Java 类(新 API) |
---|---|---|
DATETIME | java.util.Date | LocalDateTime |
DATE | java.sql.Date | LocalDate |
TIME | java.sql.Time | LocalTime |
TIMESTAMP | java.sql.Timestamp | LocalDateTime |
3.3 使用 long 存储时间戳
在数据库中,我们可以选择使用 long
类型来存储时间戳,通常使用 BIGINT
类型进行存储。通过存储一个时间戳,我们可以在不同的时区下,灵活地显示本地时间。
示例:将 long
类型时间戳转化为不同地区的本地时间
java
import java.time.*;
import java.time.format.*;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
long ts = 1574208900000L; // 示例时间戳(毫秒)
System.out.println(timestampToString(ts, Locale.CHINA, "Asia/Shanghai"));
System.out.println(timestampToString(ts, Locale.US, "America/New_York"));
}
static String timestampToString(long epochMilli, Locale lo, String zoneId) {
Instant ins = Instant.ofEpochMilli(epochMilli); // 将时间戳转换为 Instant
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT);
return f.withLocale(lo).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId))); // 格式化为指定时区的日期时间
}
}
输出示例:
yaml
2019年11月20日 上午8:15
Nov 19, 2019, 7:15 PM
在上述例子中,时间戳 1574208900000L
转化为中国和美国纽约的本地时间,并通过 DateTimeFormatter
格式化显示。
4. 小结
-
使用新的
java.time
包:在处理日期和时间时,尽量使用新的java.time
包,它提供了更加简洁、灵活且类型安全的 API。 -
新旧 API 之间的转换:Java 提供了多种方式将旧的
Date
和Calendar
转换为新的Instant
、ZonedDateTime
等,也可以通过long
类型的时间戳进行转换,确保兼容性。 -
数据库中的时间存储:使用
long
类型时间戳存储日期和时间是一个不错的选择,既可以节省空间,又可以方便地跨时区显示本地时间。 -
时区的转换:新旧时区类型(
ZoneId
和TimeZone
)之间的转换同样很重要,尤其是在处理跨时区的应用时。
通过合理的转换和存储方式,可以确保我们在不同的应用场景中高效、准确地处理日期和时间。
标签:java,07,long,日期,API,时间,Java,ZonedDateTime From: https://blog.csdn.net/max202011161630/article/details/144767765