【发布时间】:2011-07-07 03:08:11
【问题描述】:
我在 Java 中创建了一个 Date 对象。当我这样做时,它会显示类似:date=Tue Aug 09 00:00:00 IST 2011。结果,我的 Excel 文件似乎小了一天(2 月 27 日变为 2 月 26 日,依此类推)我认为这一定是因为时间。如何将其设置为下午 5:30?
【问题讨论】:
标签: java date datetime calendar
我在 Java 中创建了一个 Date 对象。当我这样做时,它会显示类似:date=Tue Aug 09 00:00:00 IST 2011。结果,我的 Excel 文件似乎小了一天(2 月 27 日变为 2 月 26 日,依此类推)我认为这一定是因为时间。如何将其设置为下午 5:30?
【问题讨论】:
标签: java date datetime calendar
如果您无法访问 java 8 和 API java.time,这是我使用旧的 java.util.Calendar 将一个日期的时间复制到另一个日期的简单函数(受 Jigar Joshi 启发):
/**
* Copy only the time of one date to the date of another date.
*/
public static Date copyTimeToDate(Date date, Date time) {
Calendar t = Calendar.getInstance();
t.setTime(time);
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, t.get(Calendar.HOUR_OF_DAY));
c.set(Calendar.MINUTE, t.get(Calendar.MINUTE));
c.set(Calendar.SECOND, t.get(Calendar.SECOND));
c.set(Calendar.MILLISECOND, t.get(Calendar.MILLISECOND));
return c.getTime();
}
【讨论】:
java.util.Date、java.util.Calendar 和 java.text.SimpleDateFormat 等非常麻烦的日期时间类现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.
我想提供现代答案。这涉及使用现代 Java 日期和时间 API java.time,而不是旧的 Date 或 Calendar,除非无法避免。
您的问题很可能确实是时区问题。当它是 2011 年 8 月 9 日星期二 00:00:00 IST 时,在 IST 以西的时区中,尚未达到午夜。现在仍然是 8 月 8 日。例如,如果您将日期放入 Excel 的 API 需要 UTC,则日期将是您想要的日期的前一天。我相信真正好的解决方案是生成 00:00 UTC 的日期时间(或任何预期并在另一端使用的时区或偏移量)。
LocalDate yourDate = LocalDate.of(2018, Month.FEBRUARY, 27);
ZonedDateTime utcDateDime = yourDate.atStartOfDay(ZoneOffset.UTC);
System.out.println(utcDateDime);
打印出来
2018-02-27T00:00Z
Z 表示 UTC(将其视为与 UTC 或祖鲁时区的偏移量为零)。当然,如果您可以将第一行代码中的 LocalDate 传递给 Excel,那就更好了。它不包括一天中的时间,因此不会造成混淆。另一方面,如果您需要一个老式的Date 对象,请在传递Date 之前进行转换:
Date oldfashionedDate = Date.from(utcDateDime.toInstant());
System.out.println(oldfashionedDate);
在我的电脑上打印
Tue Feb 27 01:00:00 CET 2018
别被骗了,这是正确的。我的时区(中欧时间)在 2 月(标准时间)与 UTC 的偏移量为 +01:00,因此这里的 01:00:00 等于 00:00:00 UTC。这只是Date.toString() 抓取 JVM 时区并使用它来生成字符串。
如何将其设置为下午 5:30?
要直接回答您的直接问题,如果您有 ZonedDateTime、OffsetDateTime 或 LocalDateTime,在所有这些情况下,以下将完成您的要求:
yourDateTime = yourDateTime.with(LocalTime.of(17, 30));
如果yourDateTime 是2018-02-27T00:00 的LocalDateTime,则现在将是2018-02-27T17:30。其他类型也类似,只是它们也酌情包含了偏移量和时区。
如果您只有一个日期,如上面的第一个 sn-p,您还可以向其中添加时间信息:
LocalDate yourDate = LocalDate.of(2018, Month.FEBRUARY, 27);
LocalDateTime dateTime = yourDate.atTime(LocalTime.of(17, 30));
例如,对于大多数用途,您应该更喜欢添加特定时区中的时间
ZonedDateTime dateTime = yourDate.atTime(LocalTime.of(17, 30))
.atZone(ZoneId.of("Asia/Kolkata"));
这会产生2018-02-27T17:30+05:30[Asia/Kolkata]。
Date 和 Calendar 与 java.time
您使用的Date 类以及其他答案中使用的Calendar 和SimpleDateFormat 早已过时,尤其是SimpleDateFormat 已被证明很麻烦。在所有情况下,现代 Java 日期和时间 API 都更易于使用。这就是为什么我想为一个仍在访问的老问题提供这个答案。
链接:Oracle Tutorial Date Time,解释如何使用java.time。
【讨论】:
你能展示你用来设置日期对象的代码吗?无论如何
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse("2011-01-01 00:00:00")
【讨论】:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY,17);
cal.set(Calendar.MINUTE,30);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MILLISECOND,0);
Date d = cal.getTime();
另见
【讨论】:
java.util.Date、java.util.Calendar 和 java.text.SimpleDateFormat 等非常麻烦的日期时间类现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.