我需要遍历一系列日期。不知道第二天如何循环。 我正在使用java.util.Date
.因此,plusDays(1)
不能在 for 循环中用于获取下一个日期。
用于 for 循环date1 = new Date(date1.getTime() + (1000 * 60 * 60 * 24))
。但是我认为每次在 for 循环中通过调用 new 来创建对象不是一个好主意。
请建议第二天循环服用的更好方法。
tl;博士
LocalDate.now().plusDays( 1 ) // Get tomorrow's date.
避免使用旧的日期时间类。
切勿使用java.util.Date
。
这个可怕的类几年前被JSR 310中定义的现代java.time类所取代。Calendar
、GregorianCalendar
和SimpleDateFormat
同上。
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 及更高版本中。这些类取代了麻烦的旧旧日期时间类,如java.util.Date
、Calendar
和SimpleDateFormat
。
要了解更多信息,请参阅Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。规范为 JSR 310。
Joda-Time项目现在处于维护模式,建议迁移到 java.time 类。
您可以直接与数据库交换java.time对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要java.sql.*
类。Hibernate 5 和 JPA 2.2 支持java.time。
从哪里获得java.time类?
Java SE 8、Java SE 9、Java SE- 10、Java SE 11及更高版本 - 标准 Java API 的一部分,具有捆绑实现。
- Java 9带来了一些小功能和修复。
Java SE 6 和 Java - SE7
- 大多数java.time功能在ThreeTen-Backport中向后移植到 Java 6 和 7。
Android - 更高版本的 Android (26+) 捆绑了java.time类的实现。
- 对于早期的Android(<26),一个称为API脱糖的过程带来了最初未内置于Android中的java.time功能的子集。
- 如果脱糖不能提供你需要的东西,ThreeTenABP项目将ThreeTen-Backport(如上所述)适应Android。请参阅如何使用ThreeTenABP...。
您可以通过将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
所有现有的答案都很棒。这个答案提供了一些额外的信息,这些信息也可以解决你的问题,或者至少引导你朝着正确的方向前进。
使用现代 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 及其格式 APISimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到现代日期时间 API。有关现代日期时间 API 的更多信息,请参阅跟踪:日期时间。
注意:出于任何原因,如果你必须坚持使用Java 6或Java 7,你可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到Java 6和7。
如果您正在为 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请查看通过脱糖提供的 Java 8+ API 和如何在 Android Project 中使用 ThreeTenABP。
正如其他人所说,如果有任何方法,请避免使用java.util.Date
。更喜欢Basil Bourque的好答案。
有时我们需要与使用遗留日期时间类作为Date
的遗留代码进行互操作,并且我们无法立即升级到java.time。
-
如果您获得
Date
形成遗留 API,请使用 ariefbayu 的答案。 -
如果对于迭代的每个日期,您需要一个用于旧 API 的老式
Date
对象,我将向您展示如何操作。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
时区运行了这个片段并得到了以下输出:
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()
给了我们一连串的LocalDate
。通过一系列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))
对于循环。但我认为通过以下方式创建对象不是一个好主意 每次在 for 循环中调用 new。
每次创建一个新对象都没有问题(除非在非常特殊的情况下)。代码不好还有其他几个原因:
做我们自己的时间数学是一个坏习惯。我们应该依赖库类,因为
A. 它提供了更清晰的代码
B. 日期和时间数学通常比我们想象的要复杂,因此很容易出错;具体来说,我们可能会错过很多极端情况,这在测试中经常被忽视。
代码假定一天始终为 24 小时。正如我上面所说,情况并非如此。
链接
Oracle 教程:日期时间解释如何使用 java.time。