java SimpleDateFormat与带时区的ZoneDateTime
我正在尝试将PST时间戳转换为历元时间
我尝试的第一种方法是使用分区datetime,将美国/洛杉矶作为输入时区
public static void changeStringDateFormatToEpoch(String oldDate, String format) throws ParseException {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format);
LocalDateTime dt = LocalDateTime.parse(oldDate, dtf);
ZonedDateTime zdtzone = dt.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println("When date: "+ oldDate + " is in format "+ format + " --> " + zdtzone.toEpochSecond());
}
在此之后,我尝试运行下面的代码,该代码使用SimpleDataFormat执行相同的操作
public static void changeStringDateFormatToEpochSimpleDate(String oldDate, String format) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date dt = sdf.parse(oldDate);
long epoch = dt. getTime();
System.out.println("When date: "+ oldDate + " is in format "+ format + " --> " + epoch);
}
在第二种情况下,我甚至没有指定输入日期的时区,这两种输出是如何相似的呢
由于输入时区是PST(美国/洛杉矶),所以纪元时间不应该受到影响吗
样本输入
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
class Scratch {
public static void main(String[] args) {
String date = "2019-11-27 04:32:41.000-0800"; //yyyy-MM-dd HH:mm:ss.SSSZ
String date2 = "2019-11-27 04:32:41"; // yyyy-MM-dd HH:mm:ss
try {
changeStringDateFormatToEpoch(date, "yyyy-MM-dd HH:mm:ss.SSSZ");
changeStringDateFormatToEpoch(date2, "yyyy-MM-dd HH:mm:ss");
changeStringDateFormatToEpochSimpleDate(date, "yyyy-MM-dd HH:mm:ss.SSSZ");
changeStringDateFormatToEpochSimpleDate(date2, "yyyy-MM-dd HH:mm:ss");
} catch (ParseException e) {
e.printStackTrace();
}
}
public static void changeStringDateFormatToEpoch(String oldDate, String format) throws ParseException {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format);
LocalDateTime dt = LocalDateTime.parse(oldDate, dtf);
ZonedDateTime zdtzone = dt.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println("When date: "+ oldDate + " is in format "+ format + " --> " + zdtzone.toEpochSecond());
}
public static void changeStringDateFormatToEpochSimpleDate(String oldDate, String format) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date dt = sdf.parse(oldDate);
long epoch = dt. getTime();
System.out.println("SimpleDate : When date: "+ oldDate + " is in format "+ format + " --> " + epoch);
}
}
输出
When date: 2019-11-27 04:32:41.000-0800 is in format yyyy-MM-dd HH:mm:ss.SSSZ --> 1574857961
When date: 2019-11-27 04:32:41 is in format yyyy-MM-dd HH:mm:ss --> 1574857961
SimpleDate : When date: 2019-11-27 04:32:41.000-0800 is in format yyyy-MM-dd HH:mm:ss.SSSZ --> 1574857961000
SimpleDate : When date: 2019-11-27 04:32:41 is in format yyyy-MM-dd HH:mm:ss --> 1574857961000
# 1 楼答案
编辑
changeStringDateFormatToEpoch()
后,出现了一个新问题:它现在忽略字符串中给定的偏移量-0800
。只要它恰好与您在代码中提供的硬编码时区一致,结果就可以了;但如果偏移量不同,则会得到错误的结果。即使是美国/洛杉矶时区,当夏令时(DST)结束时,您也会在重叠处得到错误的结果,时钟时间重复,偏移量是您唯一能够区分的机会使用
SimpleDateFormat
的代码可以说有相反的问题:在缺少时区或偏移量的情况下,它使用JVM的默认时区,这可能是预期的,也可能不是预期的。JVM时区设置可以随时由程序的另一部分或在同一JVM中运行的另一个程序更改,这一事实进一步损害了这种可能性如果您知道美国/洛杉矶时区适用于无区域或偏移量的字符串,则解决方案如下:
让我们使用您自己的代码进行尝试:
即使在我的时区欧洲/哥本哈根运行,结果也一致:
回答您的问题
在第二种情况下
SimpleDateFormat
使用JVM的时区设置。仅因为这是美国/洛杉矶(或另一个使用偏移量的时区,11月27日08:00),输出才一致。当在不同的时区运行时,他们不会输出受JVM默认时区的影响。它不使用UTC或其他默认值,除非将默认值设置为UTC或其他默认值
不要使用
SimpleDateFormat
SimpleDateFormat
类是出了名的麻烦和过时。它给你一个令人惊讶的结果并不奇怪。一定要使用java。时间,现代Java日期和时间API,它是日期和时间工作的一部分。它倾向于提供更少的惊喜和更自然的代码# 2 楼答案
基于
SimpleDateFormat
的代码只能在太平洋时区的机器上运行,才能按预期工作SimpleDateFormat
实例使用系统默认时区初始化,但可以更改要使代码健壮且可移植,请使用第一种方法。解析
LocalDateTime
,然后将其与显式ZoneId
组合,而不是推断默认时区示例中解析的某些日期时间使用偏移日期时间。这是有帮助的;许多受夏令时影响的地区的开发商忽视了在存储当地时间戳时,是否需要包括一些指示夏令时当前是否有效的必要性。如果没有它,在秋季向标准时间过渡期间,解析时间就会变得模棱两可
在任何情况下,您都应该知道,也可以将
LocalDateTime
与ZoneOffset
组合起来生成一个OffsetDateTime
,并由此生成一个纪元时间