【问题标题】:Iterate over dates in java在java中迭代日期
【发布时间】:2023-03-31 17:21:01
【问题描述】:

我需要遍历一系列日期。不确定如何在 for 循环中进行第二天。 我正在使用java.util.Date。所以plusDays(1)不能在for循环中用于获取下一个日期。

在 for 循环中使用了 date1 = new Date(date1.getTime() + (1000 * 60 * 60 * 24))。但我认为每次在 for 循环中调用 new 来创建对象并不是一个好主意。

请提出一个更好的方法来让第二天进入 for 循环。

【问题讨论】:

  • 为什么要在循环中添加 1 天?
  • 如果不构造一个新的 Date 实例,就不能有 next 日期。所以必须这样做。说到plusDays(),你为什么不用java.time.LocalDate
  • 你为什么使用Date?该课程设计不良且早已过时,无法满足您的需求。如果您确实需要 Date 来获取某些旧版 API,则需要进行一些转换。恕我直言,您能做的最好的事情就是在LocalDateZonedDateTimejava.time, the modern Java date and time API 之间进行转换。

标签: java date for-loop next


【解决方案1】:

tl;博士

LocalDate.now().plusDays( 1 )  // Get tomorrow's date.

避免使用旧的日期时间类。

永远不要使用java.util.Date

这个可怕的类在几年前被 JSR 310 中定义的现代 java.time 类所取代。CalendarGregorianCalendarSimpleDateFormat 同上。

LocalDate

对于仅日期值、没有时间和时区,请使用 LocalDate 类。

致电LocalDate.now 获取当前日期。

对于任何特定时刻,日期在全球各地都因时区而异。因此,请指定您要查看日期的时区。如果省略,则会隐式应用 JVM 当前的默认时区。

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ) ;  // Capture the current date as seen in a particular time zone.
for ( int i = 0 ; i < 7 ; i++ )
{
    LocalDate localDate = today.plusDays( i );
    System.out.println( "localDate = " + localDate );
}

运行时。

localDate = 2020-12-17
localDate = 2020-12-18
localDate = 2020-12-19
localDate = 2020-12-20
localDate = 2020-12-21
localDate = 2020-12-22
localDate = 2020-12-23

如果您熟悉 Java 流,请使用 LocalDate::datesUntil

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );  // Capture the current date as seen in a particular time zone.
today.datesUntil( today.plusWeeks( 1 ) ).forEach( System.out :: println );

关于java.time

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

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

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

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time

从哪里获取 java.time 类?

【讨论】:

    【解决方案2】:

    您可以通过将Date 转换为LocalDate 来使用plusDays()

    import java.util.*;
    import java.time.*;
    
    public class MyClass {
        public static void main(String args[]) {
            Date date = new Date();
            LocalDate dateCopy =  date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            System.out.println("Date:  " + dateCopy);
            
            for(int counter = 1; counter <= 5; counter++){
                dateCopy = dateCopy.plusDays(1);
                System.out.println("Date:  " + dateCopy);
    
            }
        }
    }
    

    请注意,我使用相同的 dateCopy 变量,因为 plusDays() 返回 LocalDate 的副本,我不想创建新变量。

    以上代码将产生以下控制台日志:

    Date:  2020-12-17
    Date:  2020-12-18
    Date:  2020-12-19
    Date:  2020-12-20
    Date:  2020-12-21
    Date:  2020-12-22
    

    【讨论】:

    • 无需将糟糕的遗留类 Datejava.time 类混在一起。
    【解决方案3】:

    所有现有的答案都很棒。这个答案提供了一些额外的信息,这些信息也可以解决您的问题或至少引导您朝着正确的方向前进。

    使用现代 API:

    import java.time.LocalDate;
    
    class Main {
        public static void main(String[] args) {
            LocalDate startDate = LocalDate.of(2020, 12, 5);// 5th Dec 2020
            LocalDate endDate = LocalDate.of(2020, 12, 15);// 15th Dec 2020
            for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
                System.out.println(date);
            }
        }
    }
    

    输出:

    2020-12-05
    2020-12-06
    2020-12-07
    2020-12-08
    2020-12-09
    2020-12-10
    

    如果您将日期作为字符串对象:

    import java.time.LocalDate;
    import java.time.format.DateTimeFormatter;
    
    class Main {
        public static void main(String[] args) {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d/M/uuuu");
            LocalDate startDate = LocalDate.parse("5/12/2020", dtf);// 5th Dec 2020
            LocalDate endDate = LocalDate.parse("10/12/2020", dtf);// 10th Dec 2020
            for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
                System.out.println(date);
            }
        }
    }
    

    输出:

    2020-12-05
    2020-12-06
    2020-12-07
    2020-12-08
    2020-12-09
    2020-12-10
    

    使用旧版 API:

    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    
    class Main {
        public static void main(String[] args) {
            Calendar calendar = Calendar.getInstance();
            calendar.set(2020, 11, 5);// 5th Dec 2020
            Date startDate = calendar.getTime();
    
            calendar.set(2020, 11, 10);// 10th Dec 2020
            Date endDate = calendar.getTime();
    
            SimpleDateFormat sdfForOutput = new SimpleDateFormat("yyyy-MM-dd");
            Date date = startDate;
            for (calendar.setTime(startDate); !date.after(endDate); calendar.add(Calendar.DAY_OF_YEAR,
                    1), date = calendar.getTime()) {
                System.out.println(sdfForOutput.format(date));
            }
        }
    }
    

    输出:

    2020-12-05
    2020-12-06
    2020-12-07
    2020-12-08
    2020-12-09
    2020-12-10
    

    如果您将日期作为字符串对象:

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    
    class Main {
        public static void main(String[] args) throws ParseException {
            SimpleDateFormat sdfForParsing = new SimpleDateFormat("d/M/yyyy");
            Date startDate = sdfForParsing.parse("5/12/2020");// 5th Dec 2020
            Date endDate = sdfForParsing.parse("10/12/2020");// 10th Dec 2020
            Calendar calendar = Calendar.getInstance();
    
            SimpleDateFormat sdfForOutput = new SimpleDateFormat("yyyy-MM-dd");
            Date date = startDate;
            for (calendar.setTime(startDate); !date.after(endDate); calendar.add(Calendar.DAY_OF_YEAR,
                    1), date = calendar.getTime()) {
                System.out.println(sdfForOutput.format(date));
            }
        }
    }
    

    输出:

    2020-12-05
    2020-12-06
    2020-12-07
    2020-12-08
    2020-12-09
    2020-12-10
    

    请注意,java.util 的日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到modern date-time API。通过 Trail: Date Time 了解有关现代日期时间 API 的更多信息。

    注意:出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它向后移植了大部分 java.time 功能到 Java 6 和 7。

    如果您正在为一个 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

    【讨论】:

      【解决方案4】:

      正如其他人所说,尽可能避免使用java.util.Date。更喜欢 Basil Bourque 的好答案。

      有时我们需要与使用旧日期时间类作为 Date 的旧代码进行互操作,而我们无法立即升级到 java.time。

      • 如果您从旧版 API 中获得 Date,请使用 ariefbayu 的答案。

      • 如果对于每个迭代的日期反过来,您需要一个老式的 Date 对象用于旧版 API,我将向您展示如何操作。

         LocalDate startDateInclusive = LocalDate.of(2021, Month.MARCH, 12);
         LocalDate endDateExlusive = LocalDate.of(2021, Month.MARCH, 17);
        
         startDateInclusive.datesUntil(endDateExlusive)
                 .map(d -> d.atStartOfDay(ZoneId.systemDefault()))
                 .map(ZonedDateTime::toInstant)
                 .map(Date::from)
                 .forEach(System.out::println);
        

      我在America/Cambridge_Bay 时区运行了这个 sn-p 并得到了这个输出:

      Fri Mar 12 00:00:00 MST 2021
      Sat Mar 13 00:00:00 MST 2021
      Sun Mar 14 00:00:00 MST 2021
      Mon Mar 15 00:00:00 MDT 2021
      Tue Mar 16 00:00:00 MDT 2021
      

      LocalDate.datesUnitil() 为我们提供LocalDates 流。通过一系列map 操作,我将每个LocalDate 转换为Date,最后打印出来。您需要调用一个或多个遗留方法而不是打印,例如:

                  .forEach(jud -> {
                      someLegayMethod(jud);
                      someOtherLegacyMethod(jud, "some other argument");
                  });
      

      在上面的输出中,您会注意到 Java 知道夏令时 (DST) 是在 3 月 14 日引入的,因此从 3 月 15 日起,时区缩写为 MDT 代表山区夏令时间,而不是 MST 代表山区标准时间.当这两个 Date 对象都在 00:00 下降时,它们之间实际上只有 23 小时。

      使用date1 = new Date(date1.getTime() + (1000 * 60 * 60 * 24)) in for 循环。但我认为通过以下方式创建对象不是一个好主意 每次在 for 循环中调用 new。

      每次创建一个新对象都没有问题(除非在非常特殊的情况下)。您的代码不好还有其他几个原因:

      • 自己计算时间是个坏习惯。我们应该依赖库类,因为

        一个。它提供了更清晰易读的代码

        b.日期和时间数学通常比我们想象的要复杂,因此很容易出错;特别是我们可能会遗漏很多极端情况,而这些情况在测试中经常被忽视。

      • 您的代码假定一天始终是 24 小时。正如我上面所说,情况并非如此。

      链接

      Oracle tutorial: Date Time 解释如何使用 java.time。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-04
        • 1970-01-01
        • 2016-07-09
        • 2014-05-19
        • 1970-01-01
        • 2023-03-15
        • 2019-02-04
        • 2010-11-13
        相关资源
        最近更新 更多