在 ZonedDateTime 或 Instant 中将小时分和秒设置为 00tl;博士详关于 java.time

2022-09-02 20:06:51

我有一个 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

tl;博士

你工作得太辛苦了。

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

2018-12-31T00:00.00Z

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

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

你所问的是一个矛盾。A 具有指定的时区,用于当您想要通过特定区域的挂钟时间查看某个时刻时。因此,要求 a 在 UTC 中生成字符串是没有意义的。是 UTC 的缩写,表示 UTC。ZonedDateTimeZonedDateTime"2017-03-03T00:00:00.000Z"ZZulu

您的输入字符串采用标准 ISO 8601 格式。默认情况下,java.time 类使用这些标准格式。因此,无需指定格式设置模式,也无需类。DateTimeFormatter

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

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

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


关于 java.time

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

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过其他类扩展了 java.time。这个项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter


答案 2
   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);

您只需要获取所有必要的字段。例如,使用日期格式。

希望它能帮助你