在Java中打印两个时间戳之间的日期时间

Posted

技术标签:

【中文标题】在Java中打印两个时间戳之间的日期时间【英文标题】:Print Datetime between Two timestamps in Java 【发布时间】:2022-01-05 19:39:23 【问题描述】:

这是我的要求。很确定有一种优雅的方法可以做到这一点。需要你的帮助。我需要构建一个后端程序来使用用户选择的开始和结束时间来处理多个日期并将其插入到表中。

输入:

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);
        
        
        List<LocalDateTime> totalDates = new ArrayList<>();
        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 < 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

【问题讨论】:

你想用 MIN MAX 和 plusDays 完成什么?我很困惑。如果你解释你的目标,也许我们可以更好地指导你。至少,我怀疑您需要了解定义时间跨度的半开放方法。 我知道半开放的方法。这是我的要求,用户输入两个时间戳,我需要根据用户输入之间的天数将其转换为不同的输出。 提供解释作为对您问题的编辑,而不是作为 cmets。 【参考方案1】:
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);
按照给定的日期开始流式传输 然后通过使用当前LocalDate 实例创建两个LocalDateTime 实例来创建内部流。 1 minute 午夜前的当前日期时间 1 day 午夜前的当前日期时间 然后flatMap 该流并将日期时间放入链接列表中。 最后,将当前开始LocalDateTime 添加到列表的开头 和结尾LocalDateTime 到列表末尾
List<LocalDateTime> list =
        start.toLocalDate().datesUntil(end.toLocalDate())
                .flatMap(date -> 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 -> 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

【讨论】:

【参考方案2】:

这似乎有效。如果还有其他优雅的方法可以做到这一点..请告诉我。

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);

    List<LocalDateTime> totalDates = new ArrayList<>();
    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 < totalDates.size(); i++) 
        System.out.print(formatter.format(totalDates.get(i)) + "\n");
    

【讨论】:

【参考方案3】:

您还需要解析输出。因此你可以使用已经定义好的DateTimeFormatter,它有一个parse方法。

输出代码:

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

您的输出中还有一行。这个来自您设置localStartTime = localStartTime.with(LocalTime.MIN); 的行。在这里,我建议进行此更改:

LocalDateTime workingStartTime = localStartTime;

List<LocalDateTime> totalDates = new ArrayList<>();
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);

编辑:使用流和 flatMap 的解决方案

以下是使用流构建最终列表的方法(不需要额外添加最后一天):

List<LocalDateTime> totalDates = localStartTime.toLocalDate().datesUntil(localEndTime.toLocalDate().plusDays(1))
    .flatMap(date -> 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());

【讨论】:

至少您的输出使用了基于 ISO 8601 的正确顺序 :-) 输出的替代代码:System.out.println(totalDates.get(i).format(formatter)); @Oboe Thx 用于输入。改编了这个答案。 使用流的解决方案不起作用。低于错误。 Cannot infer type argument(s) for &lt;R&gt; flatMap(Function&lt;? super T,? extends Stream&lt;? extends R&gt;&gt;) 你也写了Stream.of 部分吗?这对flatMap 很重要。 (在我的 IDE 中工作)

以上是关于在Java中打印两个时间戳之间的日期时间的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 获取两个日期时间/时间戳之间的随机日期时间/时间戳

检查两个日期之间的时间戳

Java程序获取没有时间戳的当前日期

Redshift - 在两个日期之间添加日期(月间隔)

在pyspark数据框中的两个日期之间生成每月时间戳

从没有时间戳列的数据库表中增量获取两个日期之间的记录