Печать даты и времени между двумя метками времени в Java

#java #time

#Ява #время

Вопрос:

Вот мое требование. Почти уверен, что есть элегантный способ сделать это. Нужна твоя помощь. Мне нужно создать серверную программу для обработки и вставки нескольких дат в таблицу, используя время начала и окончания, выбранное пользователем.

Ввод:

 StartTime: 11/26/2021 11:00 PM EndTime: 11/28/2021 04:00 AM  

Результат, которого я ожидаю

 11/26/2021 11:00 PM 11/26/2021 11:59 PM 11/27/2021 12:00 AM 11/27/2021 11:59 PM 11/28/2021 12:00 AM 11/28/2021 04:00 AM  

Мой Код

 public static void main(String[] args) {    String StartTime = "11/27/2021 11:00 PM";  String EndTime = "11/29/2021 04:00 AM";    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a");  LocalDate localStartDate = LocalDate.parse(StartTime, formatter);  LocalDate localEndDate = LocalDate.parse(EndTime, formatter);   LocalDateTime localStartTime = LocalDateTime.parse(StartTime,formatter);  LocalDateTime localEndTime = LocalDateTime.parse(EndTime,formatter);      Listlt;LocalDateTimegt; totalDates = new ArrayListlt;gt;();  while (!localStartTime.isAfter(localEndTime)) {  totalDates.add(localStartTime);  totalDates.add(localStartTime.with(LocalTime.MAX));  localStartTime = localStartTime.plusDays(1);  localStartTime = localStartTime.with(LocalTime.MIN);  }    totalDates.add(localEndTime.with(LocalTime.MIN));  totalDates.add(localEndTime);    for (int i = 0; i lt; totalDates.size(); i  ) {  System.out.print(totalDates.get(i)   "n");  }   }  

Мой Вывод:

 2021-11-27T23:00 2021-11-27T23:59:59.999999999 2021-11-28T00:00 2021-11-28T23:59:59.999999999 2021-11-29T00:00 2021-11-29T23:59:59.999999999 2021-11-29T00:00 2021-11-29T04:00  

Комментарии:

1. Чего вы пытаетесь достичь с помощью MIN MAX и plusDays ? Я сбит с толку. Если вы объясните свою цель, возможно, мы сможем лучше направлять вас. Как минимум, я подозреваю, что вам нужно узнать о Полуоткрытом подходе к определению промежутка времени.

2. Я знаю полуоткрытый подход. Вот мое требование, пользователь вводит две метки времени, мне нужно преобразовать их в разные выходные данные на основе количества дней между вводом пользователем.

3. Предоставьте пояснения в виде изменений к вашему вопросу, а не в виде комментариев.

Ответ №1:

Вам также необходимо проанализировать выходные данные. Поэтому вы можете использовать уже определенный DateTimeFormatter , у которого есть parse метод.

Код для вывода:

 System.out.println(totalDates.get(i).format(formatter));  

Также у вас есть одна дополнительная строка в вашем выводе. Это происходит от линии, где вы установили localStartTime = localStartTime.with(LocalTime.MIN); . Здесь я бы предложил это изменение:

 LocalDateTime workingStartTime = localStartTime;  Listlt;LocalDateTimegt; totalDates = new ArrayListlt;gt;(); while (!workingStartTime.isAfter(localEndTime)) {  if(!workingStartTime.equals(localStartTime)) {  workingStartTime = workingStartTime.with(LocalTime.MIN);  }  totalDates.add(workingStartTime);  totalDates.add(workingStartTime.with(LocalTime.MAX));  workingStartTime = workingStartTime.plusDays(1); }  

Изменить: Решение с использованием потоков и плоской карты

Вот как вы строите окончательный список с потоками (дополнительное добавление последнего дня не требуется):

 Listlt;LocalDateTimegt; totalDates = localStartTime.toLocalDate().datesUntil(localEndTime.toLocalDate().plusDays(1))  .flatMap(date -gt; Stream.of(  date.equals(localStartTime.toLocalDate()) ? LocalDateTime.of(date, localStartTime.toLocalTime()) : LocalDateTime.of(date, LocalTime.MIN),  date.equals(localEndTime.toLocalDate()) ? LocalDateTime.of(date, localEndTime.toLocalTime()) : LocalDateTime.of(date, LocalTime.MAX))  )  .collect(Collectors.toList());  

Комментарии:

1. По крайней мере, в вашем выводе использовался правильный порядок, основанный на ISO 8601 🙂

2. Альтернативный код для вывода: System.out.println(totalDates.get(i).format(formatter));

3. @Гобой Thx для ввода. Адаптировал ответ на этот вопрос.

4. Решение с использованием потоков не работает. Ошибка ниже. Cannot infer type argument(s) for lt;Rgt; flatMap(Functionlt;? super T,? extends Streamlt;? extends Rgt;gt;)

5. Ты тоже написал эту Stream.of роль? Это важно для flatMap . (работал в моей IDE)

Ответ №2:

 String startTime = "11/26/2021 11:00 PM"; String endTime = "11/28/2021 04:00 AM";  DateTimeFormatter dtf =  DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a"); LocalDateTime start = LocalDateTime.parse(startTime, dtf); LocalDateTime end = LocalDateTime.parse(endTime, dtf);  
  • Начните потоковую передачу дат, как указано
  • затем создайте внутренний поток, создав два LocalDateTime экземпляра, используя текущий LocalDate экземпляр.
    • текущая дата 1 minute и время до полуночи
    • текущая дата 1 day и время до полуночи
  • затем flatMap этот поток и поместите даты в связанный список.
  • чтобы закончить, добавьте текущее начало LocalDateTime в начало списка
  • и конец LocalDateTime в конце списка
 Listlt;LocalDateTimegt; list =  start.toLocalDate().datesUntil(end.toLocalDate())  .flatMap(date -gt; Stream.of(  date.atTime(23,59),  date.atTime(0,0).plusDays(1)))  .collect(Collectors  .toCollection(LinkedList::new)); list.add(0, start); list.add(end); list.forEach(d -gt; System.out.println(d.format(dtf)));  

С принтами

 11/26/2021 11:00 PM 11/26/2021 11:59 PM 11/27/2021 12:00 AM 11/27/2021 11:59 PM 11/28/2021 12:00 AM 11/28/2021 04:00 AM  

Ответ №3:

Кажется, это работает. Если есть другие элегантные способы сделать это.. Пожалуйста, дайте мне знать.

 public static void main(String[] args) {   String StartTime = "02/27/2021 11:00 PM";  String EndTime = "03/02/2021 01:00 PM";   DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a");  LocalDate localStartDate = LocalDate.parse(StartTime, formatter);  LocalDate localEndDate = LocalDate.parse(EndTime, formatter);   LocalDateTime localStartTime = LocalDateTime.parse(StartTime, formatter);  LocalDateTime localEndTime = LocalDateTime.parse(EndTime, formatter);   Listlt;LocalDateTimegt; totalDates = new ArrayListlt;gt;();  while (localEndDate.isAfter(localStartDate)) {   totalDates.add(localStartTime);  totalDates.add(localStartTime.with(LocalTime.MAX));   if (!localStartDate.equals(localEndDate)) {  localStartTime = localStartTime.plusDays(1).with(LocalTime.MIN);  }  localStartDate = localStartDate.plusDays(1);   }   totalDates.add(localEndTime.with(LocalTime.MIN));  totalDates.add(localEndTime);   for (int i = 0; i lt; totalDates.size(); i  ) {  System.out.print(formatter.format(totalDates.get(i))   "n");  } }