
在java 8之前,开发者通常依赖java.util.date和java.text.simpledateformat来处理日期和时间。然而,这些api存在诸多问题,尤其是在处理时区和并发性方面:
上述问题在处理来自不同系统或地域的日期时间数据时尤为突出,如将美国出生日期转换为Epoch时间戳时,若不正确处理时区偏移,将导致存储的时间戳与实际时间不符。
自Java 8起,引入了全新的java.time包,它提供了一套强大、直观且线程安全的日期时间API,彻底解决了传统API的痛点。该API基于ISO 8601标准,核心类包括:
在将字符串转换为Epoch时间戳时,推荐的流程是:字符串 -> LocalDateTime (解析不带时区的日期时间) -> ZonedDateTime (应用时区) -> Instant (转换为瞬时点) -> Epoch时间戳。
在实际应用中,我们可能需要处理多种格式的日期时间字符串。java.time.format.DateTimeFormatterBuilder提供了一种优雅的方式来构建一个能够解析多种模式的DateTimeFormatter。
立即学习“Java免费学习笔记(深入)”;
例如,要同时解析"yyyy-MM-dd HH:mm:ss"和"dd-MMM-yyyy"两种格式,并为只有日期的格式提供默认时间(例如午夜00:00),可以这样构建DateTimeFormatter:
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;
public class DateTimeParser {
public static DateTimeFormatter createFlexibleFormatter() {
return new DateTimeFormatterBuilder()
// 尝试解析 "dd-MMM-yyyy HH:mm" 或 "dd-MMM-yyyy"
.appendPattern("[dd-MMM-uuuu[ HH:mm]]")
// 尝试解析 "yyyy-MM-dd HH:mm:ss"
.appendPattern("[uuuu-MM-dd HH:mm:ss]")
// 忽略大小写,例如 "Nov" 和 "nov" 都能解析
.parseCaseInsensitive()
// 如果时间部分缺失,默认小时为0
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
// 如果时间部分缺失,默认分钟为0
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
// 设置解析的语言环境,例如解析 "Nov" 需要英文环境
.toFormatter(Locale.ENGLISH);
}
}说明:
要将LocalDateTime转换为带有正确时区偏移的Epoch时间戳,必须明确指定其所处的时区。java.time.ZoneId用于表示时区。
以下是一个将多种格式的日期时间字符串,考虑时区转换为Epoch毫秒的完整示例:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;
public class ZonedEpochConverter {
/**
* 创建一个灵活的日期时间格式化器,支持多种输入格式并处理默认时间。
* 支持 "dd-MMM-yyyy HH:mm" (可选 HH:mm) 和 "yyyy-MM-dd HH:mm:ss"。
*
* @return 配置好的 DateTimeFormatter
*/
public static DateTimeFormatter createFlexibleFormatter() {
return new DateTimeFormatterBuilder()
// 尝试解析 "dd-MMM-uuuu[ HH:mm]" (例如 "14-Nov-2022" 或 "14-Nov-2022 08:00")
.appendPattern("[dd-MMM-uuuu[ HH:mm]]")
// 尝试解析 "uuuu-MM-dd HH:mm:ss" (例如 "2022-11-14 08:40:50")
.appendPattern("[uuuu-MM-dd HH:mm:ss]")
.parseCaseInsensitive() // 忽略大小写,如 "Nov"
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0) // 如果时间缺失,默认小时为0
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) // 如果时间缺失,默认分钟为0
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) // 如果时间缺失,默认秒为0
.toFormatter(Locale.ENGLISH); // 使用英文语言环境解析月份缩写
}
/**
* 将日期时间字符串(可能包含不同格式)在给定区域转换为Epoch毫秒。
*
* @param dateTimeString 待转换的日期时间字符串
* @param zoneId 该日期时间字符串所处的时区
* @return 对应的Epoch毫秒值
* @throws java.time.format.DateTimeParseException 如果字符串无法解析
*/
public static long convertToEpochMilli(String dateTimeString, ZoneId zoneId) {
DateTimeFormatter formatter = createFlexibleFormatter();
LocalDateTime ldt = LocalDateTime.parse(dateTimeString, formatter);
return ldt.atZone(zoneId).toInstant().toEpochMilli();
}
public static void main(String[] args) {
String[] dateStrings = {
"2022-11-14 08:40:50", // 包含日期和时间
"14-Nov-2022" // 只包含日期
};
// 假设这些日期时间都属于美国纽约时区
ZoneId newYorkZone = ZoneId.of("America/New_York");
System.out.println("Converting date strings to Epoch milliseconds in " + newYorkZone + ":");
for (String sdt : dateStrings) {
try {
long epoch = convertToEpochMilli(sdt, newYorkZone);
System.out.println("Input: \"" + sdt + "\" -> Epoch: " + epoch);
} catch (Exception e) {
System.err.println("Error parsing \"" + sdt + "\": " + e.getMessage());
}
}
// 示例:不同时区的转换
ZoneId losAngelesZone = ZoneId.of("America/Los_Angeles");
String specificDate = "2023-01-01 12:00:00";
long epochNewYork = convertToEpochMilli(specificDate, newYorkZone);
long epochLosAngeles = convertToEpochMilli(specificDate, losAngelesZone);
System.out.println("\nSpecific date \"" + specificDate + "\":");
System.out.println(" In " + newYorkZone + ": " + epochNewYork);
System.out.println(" In " + losAngelesZone + ": " + epochLosAngeles);
// 注意:同一字符串在不同时区解析出的Epoch值是不同的,因为它们代表了不同的UTC时间点。
}
}输出示例:
Converting date strings to Epoch milliseconds in America/New_York: Input: "2022-11-14 08:40:50" -> Epoch: 1668433250000 Input: "14-Nov-2022" -> Epoch: 1668402000000 Specific date "2023-01-01 12:00:00": In America/New_York: 1672592400000 In America/Los_Angeles: 1672603200000
通过采用Java 8的java.time API,我们可以克服传统日期时间API在处理时区和多种格式时的诸多挑战。DateTimeFormatterBuilder提供了强大的灵活性来解析不同模式的日期时间字符串,而ZoneId和ZonedDateTime则确保了时区处理的准确性。遵循本文提供的指南和示例代码,开发者可以构建出更加健壮、可靠的日期时间转换逻辑,从而避免因时区问题导致的数据不一致或错误。
以上就是Java中带时区的日期时间转换为Epoch时间戳的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号