在 ZonedDateTime 或 Instant 中将小时分钟和秒设置为 00

Posted

技术标签:

【中文标题】在 ZonedDateTime 或 Instant 中将小时分钟和秒设置为 00【英文标题】:Set hours minutes and seconds to 00 in ZonedDateTime or Instant 【发布时间】:2017-07-23 17:25:11 【问题描述】:

我有一个 Utc 格式的日期字符串 -

    String dateStr = "2017-03-03T13:14:28.666Z";

我想在 ZonedDateTime 中将其转换为以下 Java 日期表示格式。

ZonedDateTime 被打印时,它应该显示

    String dateStr = "2017-03-03T00:00:00.000Z";

我已经尝试过以下代码 -

    String timeZone = "America/Los_Angeles";
    DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    ZoneId zoneId1 = ZoneId.of(timeZone);
    String dateStr = "2017-03-03T13:14:28.666Z";
    Instant inst = Instant.parse(dateStr, dtf2);


    ZonedDateTime dateTimeInTz = ZonedDateTime.ofInstant(inst, zoneId1);

    ZonedDateTime startTime = dateTimeInTz.with(LocalTime.of(0, 0, 0, 0));
    ZonedDateTime endTime = dateTimeInTz.with(LocalTime.MAX);

    System.out.println("Start:"+startTime+", End:"+endTime);
    System.out.println("Start:"+startTime.toString()+", End:"+endTime.toString());  

    ZonedDateTime nT = ZonedDateTime.of ( LocalDate.parse(dateStr, dtf1) , LocalTime.of (0,0,0,0) , ZoneId.of ( timeZone ) );

    System.out.println("Start:"+nT);

输出:

Start:2017-03-03T00:00-08:00[America/Los_Angeles], End:2017-03-03T23:59:59.999999999-08:00[America/Los_Angeles]
Start:2017-03-03T00:00-08:00[America/Los_Angeles], End:2017-03-03T23:59:59.999999999-08:00[America/Los_Angeles]
Start:2017-03-03T00:00-08:00[America/Los_Angeles]

我希望在 ZonedDateTime 中标准化开始时间。 我只想使用 java 库而不是任何第三方库来实现它。

【问题讨论】:

【参考方案1】:
   String timeZone = "America/Los_Angeles";
    DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    ZoneId zoneId1 = ZoneId.of(timeZone);
    String dateStr = "2017-03-03T13:14:28.666Z";
    Instant inst = Instant.parse(dateStr, dtf2);


    ZonedDateTime dateTimeInTz = ZonedDateTime.ofInstant(inst, zoneId1);

    ZonedDateTime startTime = dateTimeInTz.with(LocalTime.of(0, 0, 0, 0));
    ZonedDateTime endTime = dateTimeInTz.with(LocalTime.MAX);

    String strStart = (startTime.toString().split("T"))[0] + "T00:00:00.000Z";
    String strEnd  =  (endTime.toString().split("T"))[0] + "T00:00:00.000Z";

    System.out.println("Start:"+strStart +", End:"+strEnd  );

编辑新方法:

TimeZone timeZone = TimeZone.getTimeZone("Europe/Copenhagen");
Calendar cal = Calendar.getInstance(timeZone);
Calendar defaut = new GregorianCalendar( cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH),0,0,0);

您只需要获取所有必要的字段。例如,使用 dateFormat。

希望对你有帮助

【讨论】:

是的,这绝对是其中一种方式,但是否可以使用 java api 而不是字符串操作。 我可能误解了这个问题,你能解释一下吗? 就像我尝试过但没有解决问题的那些。例如,使用 java 将小时、分钟、秒设置为 00【参考方案2】:

你可以这样做:

DateUtils.truncate(yourDate, Calendar.DAY_OF_MONTH);

希望对你有帮助

【讨论】:

与 org.apache.commons.lang3.time.DateUtils 不正确。 Apache DateUtils 用于与 Java 的最早版本捆绑在一起的麻烦的旧旧日期时间类。这个问题是关于他们的替代品,java.time 类。 你能把这个的来源发给我吗? 你的意思是 DateUtils 用于麻烦的遗留类吗? Apache Commons Lang 项目的 DateUtils 类的 JavaDoc 仅接受 DateCalendar 参数,即遗留类。如果您指的是有关 java.time 类的信息,请参阅 JavaDoc in Java 8、Oracle Tutorial 和 JSR 310。 我在谈论 java 7 ;是的,DateUtils 类只接受 Date 和日历参数,但他可以解析 String 以获取 Date 并使用 truncate 截断 date 。非常感谢您的回复【参考方案3】:

tl;博士

你工作太辛苦了。

Instant.parse( "2017-03-03T13:14:28.666Z" )
       .truncatedTo( ChronoUnit.DAYS )
       .toString()

2017-03-03T00:00.00Z

详情

“在 ZonedDateTime 中标准化”是什么意思?请编辑您的问题以澄清。

打印 ZonedDateTime 时,它​​应该显示……“2017-03-03T00:00:00.000Z”

你问的是矛盾的。 ZonedDateTime 有一个指定的时区,当您想通过特定区域的挂钟时间查看某个时刻时。因此,要求 ZonedDateTime 以 UTC 格式生成字符串,例如 "2017-03-03T00:00:00.000Z" 是没有意义的。 ZZulu 的缩写,表示 UTC。

您的输入字符串采用标准 ISO 8601 格式。 java.time 类默认使用这些标准格式。所以不需要指定格式模式,不需要DateTimeFormatter 类。

解析为Instant,UTC 时间轴上的一个点,分辨率为纳秒。

Instant instant = Instant.parse( "2017-03-03T13:14:28.666Z" );

如果您想要 UTC 的午夜,请截断。

Instant instantMidnightUtc = instant.truncatedTo( ChronoUnit.DAYS );

instantMidnightUtc.toString(): 2017-03-03T00:00.00Z

不需要ZonedDateTime 类。

如果您想使用没有任何时间和时区的仅日期,请使用 LocalDate 类。

顺便说一句,不要假设一天的第一时刻总是00:00:00。这对于 UTC 来说是正确的。但不同时区可能存在异常情况,例如夏令时 (DST),其中一天可能从另一个时间开始,例如 01:00:00


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

从哪里获得 java.time 类?

Java SE 8SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6SE 7 ThreeTen-Backport 中的大部分 java.time 功能都向后移植到 Java 6 和 7。 Android ThreeTenABP 项目专门针对 android 改编了 ThreeTen-Backport(如上所述)。 见How to use ThreeTenABP…

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 和more。

【讨论】:

以上是关于在 ZonedDateTime 或 Instant 中将小时分钟和秒设置为 00的主要内容,如果未能解决你的问题,请参考以下文章

Java 8 - ZonedDateTime 的 DateTimeFormatter 和 ISO_INSTANT 问题

在 Spring Boot 和 ElasticSearch 中使用 Instant、LocalDateTime 和 ZonedDateTime

JAVA8新特性随笔

为啥 java.time.Clock 有区域信息?

获取当前时间UTC时间的下一个15分钟时间点

如何使用 ZonedDateTime 或 Java 8 将任何日期时间转换为 UTC