Установите часы, минуты и секунды на 00 в ZonedDateTime или Instant

У меня есть строка даты в формате UTC -

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

И я хочу преобразовать его в формат ниже в представлении даты Java в ZonedDateTime.

Когда печатается 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, а не какую-либо стороннюю библиотеку.


person WitVault    schedule 03.03.2017    source источник


Ответы (3)


tl;dr

Вы слишком много работаете.

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", не имеет смысла. Z является сокращением от Zulu и означает 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 и выше. Эти классы заменяют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и SimpleDateFormat.

Проект Joda-Time, теперь в режим обслуживания, советует перейти на java.time.

Чтобы узнать больше, см. учебник по Oracle. И поищите множество примеров и пояснений в Stack Overflow. Спецификация: JSR 310.

Где получить классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательным полигоном для возможных дополнений к java.time в будущем. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и подробнее.

person Basil Bourque    schedule 03.03.2017

   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.

Надеюсь, это поможет вам

person hartar    schedule 03.03.2017
comment
Да, определенно, это один из способов, но можно ли использовать java-apis вместо манипуляций со строками. - person WitVault; 03.03.2017
comment
Возможно, я неправильно понял вопрос, можете ли вы объяснить мне это по-другому? - person hartar; 03.03.2017
comment
Как и те, которые я пробовал, но не работали в вопросе. например, установка часов, минут, секунд до 00 с помощью java - person WitVault; 03.03.2017

Вы можете просто сделать:

DateUtils.truncate(yourDate, Calendar.DAY_OF_MONTH);

Надеюсь, что это поможет вам

person Younes Ouchala    schedule 03.03.2017
comment
с org.apache.commons.lang3.time.DateUtils - person Younes Ouchala; 03.03.2017
comment
Неправильно. Apache DateUtils предназначен для проблемных старых устаревших классов даты и времени, связанных с самыми ранними версиями Java. Этот вопрос касается их замены, классов java.time. - person Basil Bourque; 03.03.2017
comment
Вы можете отправить мне источник этого? - person Younes Ouchala; 05.03.2017
comment
Вы имеете в виду DateUtils для проблемных устаревших классов? Документ JavaDoc для DateUtils принимает только аргументы Date и Calendar, устаревшие классы. Если вы имели в виду информацию о классах java.time, см. JavaDoc в Java 8, учебник по Oracle и JSR 310. - person Basil Bourque; 06.03.2017
comment
Я говорю о Java 7; да, класс DateUtils принимает только аргументы даты и календаря, но он может анализировать строку, чтобы получить дату, и использовать усечение для усечения даты. Большое спасибо за ваш ответ - person Younes Ouchala; 06.03.2017
comment
Что касается Java 7, большая часть функций java.time была перенесена на Java 6 и Java 7. См. мой ответ для ссылок. Нет необходимости когда-либо снова прикасаться к жалким старым классам Date и Calendar. - person Basil Bourque; 26.07.2018