为什么日期转换 return 不同的时间戳?
Why does a date conversion return different timestamps?
我正在将 GregorianCalendar 实例转换为 Date 以获得 unix 时间戳。
但我想知道为什么相同的日期 returns 每次都有不同的 Unix 时间戳。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar = new GregorianCalendar();
calendar.set(2018, 0, 1, 0,0,0);
System.out.println(sdf.format(calendar.getTime()));
Date date = calendar.getTime();
System.out.println(sdf.format(date));
System.out.println(date.getTime());
日期本身是正确的,并且始终相同,"2018/01/01 00:00:00"
。但是为什么每次的unix时间戳都不一样呢?例如,这些是执行 5 次后的值。
1514761200624
1514761200618
1514761200797
1514761200209
1514761200132
当您创建新日历时,它包含当前日期和时间。之后,您更新除毫秒之外的所有字段。如您所见,所有输出中只有最后 3 个数字不同,这是执行时间的毫秒数。
我假设您在示例中的循环中实例化所有内容?
如果是这样,则说明您没有设置毫秒差,因此它们在循环的每次迭代中都会发生变化(尽管很小)。
为避免这种情况,您可以设置毫秒数,或在循环外进行实例化:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar = new GregorianCalendar();
calendar.set(2018, 0, 1, 0, 0, 0);
for (int i = 0; i < 5; i++) {
System.out.println(sdf.format(calendar.getTime()));
Date date = calendar.getTime();
System.out.println(sdf.format(date));
System.out.println(date.getTime());
}
这将产生:
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
在时间戳中,最后3位代表毫秒。在这里,您明确设置了日期和时间,但没有设置毫秒。这就是你面对这个的原因。为避免这种情况,您可以将其添加到您的代码中:
calendar.set(Calendar.MILLISECOND, 0);
java.time
ZoneId zone = ZoneId.of("Europe/Brussels");
ZonedDateTime start2018 = LocalDate.of(2018, Month.JANUARY, 1).atStartOfDay(zone);
Instant asInstant = start2018.toInstant();
System.out.println(asInstant.toEpochMilli());
这始终给出以下输出:
1514761200000
如果不是 Europe/Brussels,请替换为您想要的时区。
要格式化输出:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
System.out.println(start2018.format(formatter));
2018/01/01 00:00:00
您使用的日期和时间 类 — SimpleDateFormat
、Calendar
、GregorianCalendar
和 Date
— 设计不佳且早已过时. SimpleDateFormat
尤其是出了名的麻烦,但在这种情况下,是 Calendar
的糟糕设计给了你意想不到的结果。其他答案已经解释了如何,我就不用重复了。我建议您使用现代的 Java 日期和时间 API,而不是旧的 类。与它一起工作要好得多。
Link: Oracle tutorial: Date Time 解释如何使用 java.time.
我正在将 GregorianCalendar 实例转换为 Date 以获得 unix 时间戳。
但我想知道为什么相同的日期 returns 每次都有不同的 Unix 时间戳。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar = new GregorianCalendar();
calendar.set(2018, 0, 1, 0,0,0);
System.out.println(sdf.format(calendar.getTime()));
Date date = calendar.getTime();
System.out.println(sdf.format(date));
System.out.println(date.getTime());
日期本身是正确的,并且始终相同,"2018/01/01 00:00:00"
。但是为什么每次的unix时间戳都不一样呢?例如,这些是执行 5 次后的值。
1514761200624
1514761200618
1514761200797
1514761200209
1514761200132
当您创建新日历时,它包含当前日期和时间。之后,您更新除毫秒之外的所有字段。如您所见,所有输出中只有最后 3 个数字不同,这是执行时间的毫秒数。
我假设您在示例中的循环中实例化所有内容?
如果是这样,则说明您没有设置毫秒差,因此它们在循环的每次迭代中都会发生变化(尽管很小)。
为避免这种情况,您可以设置毫秒数,或在循环外进行实例化:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar = new GregorianCalendar();
calendar.set(2018, 0, 1, 0, 0, 0);
for (int i = 0; i < 5; i++) {
System.out.println(sdf.format(calendar.getTime()));
Date date = calendar.getTime();
System.out.println(sdf.format(date));
System.out.println(date.getTime());
}
这将产生:
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
在时间戳中,最后3位代表毫秒。在这里,您明确设置了日期和时间,但没有设置毫秒。这就是你面对这个的原因。为避免这种情况,您可以将其添加到您的代码中:
calendar.set(Calendar.MILLISECOND, 0);
java.time
ZoneId zone = ZoneId.of("Europe/Brussels");
ZonedDateTime start2018 = LocalDate.of(2018, Month.JANUARY, 1).atStartOfDay(zone);
Instant asInstant = start2018.toInstant();
System.out.println(asInstant.toEpochMilli());
这始终给出以下输出:
1514761200000
如果不是 Europe/Brussels,请替换为您想要的时区。
要格式化输出:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
System.out.println(start2018.format(formatter));
2018/01/01 00:00:00
您使用的日期和时间 类 — SimpleDateFormat
、Calendar
、GregorianCalendar
和 Date
— 设计不佳且早已过时. SimpleDateFormat
尤其是出了名的麻烦,但在这种情况下,是 Calendar
的糟糕设计给了你意想不到的结果。其他答案已经解释了如何,我就不用重复了。我建议您使用现代的 Java 日期和时间 API,而不是旧的 类。与它一起工作要好得多。
Link: Oracle tutorial: Date Time 解释如何使用 java.time.