当我尝试获取表示(1-1-1970 01:00:00)的日期对象的时间时,它以负值返回毫秒。
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm:ss"); Date
date = sdf.parse("1/1/70 01:00:00");
System.out.println(date.getTime());
上面的代码将打印负值。我想了解如何计算毫秒,以及该日期如何获得负值。
答案 0 :(得分:3)
SimpleDateFormat是特定于时区的。使用dateFormat.parse(timesStamp)将返回特定时区的Date对象。因此它会因您当地时间与格林尼治标准时间的差异而被抵消。
要解决此问题,请尝试添加dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
=
答案 1 :(得分:3)
您的行Date date = sdf.parse("1/1/70 01:00:00");
是时区敏感的。您处于GMT + 2时区,因此该时区的日期等于格林尼治标准时间1969年12月31日23:00:00。
答案 2 :(得分:2)
是的,当您使用旧的Date
和SimpleDateFormat
时,这可能会造成混淆。解释是您的毫秒值是从纪元开始计算的,并且纪元在UTC中定义为1970-01-01 00:00 UTC。因此,如果您所在的时区偏离UTC,则1970-01-01 00:00处于不同的时间点,不同的时刻,不同的时刻。因此,取决于您是在UTC之前还是之后,毫秒值将小于或大于0。
使用现代Java日期和时间API java.time时,事情可能会变得更加清晰。该API邀请我们在相关时区明确显示时区,这有助于避免混淆。例如,尝试以下方法:
public static void printMilliseconds(ZoneId zone) {
LocalDateTime dateTime = LocalDateTime.of(1970, Month.JANUARY, 1, 0, 0);
ZonedDateTime zdt = dateTime.atZone(zone);
System.out.println("In time zone: " + zdt);
Instant i = zdt.toInstant();
System.out.println("As Instant: " + i);
long milliseconds = i.toEpochMilli();
System.out.println("Milliseconds since the epoch: " + milliseconds);
}
假设您的时区为亚洲/加尔各答,那么将该时区传递给方法。
printMilliseconds(ZoneId.of("Asia/Kolkata"));
然后输出为:
In time zone: 1970-01-01T00:00+05:30[Asia/Kolkata] As Instant: 1969-12-31T18:30:00Z Milliseconds since the epoch: -19800000
Instant
以UTC打印(以尾随Z
表示),因此我们可以看到印度的时间对应于纪元前五个半小时,即-19 80万毫秒。
对于格林威治以西的时区,我们得到一个正值。让我们尝试一下America / Mexico_City。
In time zone: 1970-01-01T00:00-06:00[America/Mexico_City] As Instant: 1970-01-01T06:00:00Z Milliseconds since the epoch: 21600000
为了完整起见,UTC本身。这应该给出0(零)。让我们看看。
printMilliseconds(ZoneOffset.UTC);
In time zone: 1970-01-01T00:00Z As Instant: 1970-01-01T00:00:00Z Milliseconds since the epoch: 0
类Date
和SimpleDateFormat
的设计很差,这为您的困惑提供了很多解释。我建议我们不再使用它们。
Oracle tutorial: Date Time解释了如何使用java.time。