Java 8 LocalDate - 如何获取两个日期之间的所有日期?

问题描述 投票:45回答:9

是否可以在新的qazxsw poi API中获取两个日期之间的所有日期?

假设我有这部分代码:

java.time

现在我需要@Test public void testGenerateChartCalendarData() { LocalDate startDate = LocalDate.now(); LocalDate endDate = startDate.plusMonths(1); endDate = endDate.withDayOfMonth(endDate.lengthOfMonth()); } startDate之间的所有日期。

我想要获得两个日期的endDate并迭代:

daysBetween

有更好的方法来获取日期吗?

java date java-8 java-time
9个回答
66
投票

假设您主要想迭代日期范围,那么创建一个可迭代的long daysBetween = ChronoUnit.DAYS.between(startDate, endDate); for(int i = 0; i <= daysBetween; i++){ startDate.plusDays(i); //...do the stuff with the new date... } 类是有意义的。那会让你写:

DateRange

就像是:

for (LocalDate d : DateRange.between(startDate, endDate)) ...

添加equals和hashcode方法,getters,可能有一个静态工厂+私有构造函数来匹配Java时间API的编码风格等是有意义的。


62
投票

首先,您可以使用public class DateRange implements Iterable<LocalDate> { private final LocalDate startDate; private final LocalDate endDate; public DateRange(LocalDate startDate, LocalDate endDate) { //check that range is valid (null, start < end) this.startDate = startDate; this.endDate = endDate; } @Override public Iterator<LocalDate> iterator() { return stream().iterator(); } public Stream<LocalDate> stream() { return Stream.iterate(startDate, d -> d.plusDays(1)) .limit(ChronoUnit.DAYS.between(startDate, endDate) + 1); } public List<LocalDate> toList() { //could also be built from the stream() method List<LocalDate> dates = new ArrayList<> (); for (LocalDate d = startDate; !d.isAfter(endDate); d = d.plusDays(1)) { dates.add(d); } return dates; } } 来获取该月的最后一天。接下来TemporalAdjuster API提供Stream,它是适合您的问题的正确工具。

Stream::iterate

25
投票

Java 9

在Java 9中,使用LocalDate start = LocalDate.now(); LocalDate end = LocalDate.now().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()); List<LocalDate> dates = Stream.iterate(start, date -> date.plusDays(1)) .limit(ChronoUnit.DAYS.between(start, end)) .collect(Collectors.toList()); System.out.println(dates.size()); System.out.println(dates); 方法增强了LocalDate类,该方法将日期范围内的所有日期作为LocalDate.datesUntil(LocalDate endExclusive)返回。

Stream<LocalDate>

9
投票

您可以使用.isAfter和.plusDays在循环中执行此操作。我不会说更好,因为我没有对该主题进行大量研究,但我可以自信地说它使用Java 8 API并且是一个轻微的替代方案。

List<LocalDate> dates = startDate.datesUntil(endDate).collect(Collectors.toList());

产量

LocalDate startDate = LocalDate.now();
LocalDate endDate = startDate.plusMonths(1);
while (!startDate.isAfter(endDate)) {
 System.out.println(startDate);
 startDate = startDate.plusDays(1);
}

2016-07-05 2016-07-06 ... 2016-08-04 2016-08-05


6
投票

你可以创建一个Example Herestream对象。我也有这个问题,我发布了我的解决方案LocalDate

用你的例子......

java-timestream on github.

它或多或少等同于此处提出的其他解决方案,但它会处理所有日期数学并知道何时停止。您可以提供特定或相对结束日期,并告诉它跳过每次迭代的时间(上面的默认值是一天)。


2
投票

LocalDateStream .from(LocalDate.now()) .to(1, ChronoUnit.MONTHS) .stream() .collect(Collectors.toList()); 库有一个ThreeTen-Extra类,可以完全满足您的要求:

LocalDateRange

1
投票

在我的时间库LocalDateRange.ofClosed(startDate, endDate).stream() .forEach(/* ...do the stuff with the new date... */); 中,我编写了一个优化的分裂器来构建具有良好并行化特征的日历日期流。适应您的用例:

Time4J

如果您对相关功能感兴趣,例如每个日历日期的时钟间隔(分区流)或其他间隔功能,并希望避免笨拙的手写代码,请参阅LocalDate start = ...; LocalDate end = ...; Stream<LocalDate> stream = DateInterval.between(start, end) // closed interval, else use .withOpenEnd() .streamDaily() .map(PlainDate::toTemporalAccessor); 的API,这个简短的方法可能是一个有趣的起点。


1
投票

您可以在Google的DateInterval库中使用Range功能。在Guava实例上定义DiscreteDomain后,您可以获得该范围内所有日期的LocalDate

ContiguousSet

1
投票

tl;dr

在Java 9及更高版本中使用来自LocalDate d1 = LocalDate.parse("2017-12-25"); LocalDate d2 = LocalDate.parse("2018-01-05"); DiscreteDomain<LocalDate> localDateDomain = new DiscreteDomain<LocalDate>() { public LocalDate next(LocalDate value) { return value.plusDays(1); } public LocalDate previous(LocalDate value) { return value.minusDays(1); } public long distance(LocalDate start, LocalDate end) { return start.until(end, ChronoUnit.DAYS); } public LocalDate minValue() { return LocalDate.MIN; } public LocalDate maxValue() { return LocalDate.MAX; } }; Set<LocalDate> datesInRange = ContiguousSet.create(Range.closed(d1, d2), localDateDomain); 的流扩展了良好的Answer by Singh

datesUntil

[2018-09-20, 2018-09-21, 2018-09-22, 2018-09-23, 2018-09-24, 2018-09-25, 2018-09-26, 2018-09-27, 2018-09-28, 2018-09-29, 2018-09-30, 2018-10-01, 2018-10-02, 2018-10-03, 2018-10-04, 2018-10-05, 2018-10-06, 2018-10-07, 2018-10-08, 2018-10-09, 2018-10-10, 2018-10-11, 2018-10-12, 2018-10-13, 2018-10-14, 2018-10-15, 2018-10-16, 2018-10-17, 2018-10-18, 2018-10-19]

today // Determine your beginning `LocalDate` object. .datesUntil( // Generate stream of `LocalDate` objects. today.plusMonths( 1 ) // Calculate your ending date, and ask for a stream of dates till then. ) // Returns the stream. .collect( Collectors.toList() ) // Collect your resulting dates in a `List`. .toString() // Generate text representing your found dates. stream

从Java 9开始,您可以要求提供日期流。打电话给LocalDate::datesUntil

首先确定今天的日期。这需要一个时区。对于任何给定的时刻,日期在全球范围内因地区而异。

LocalDate::datesUntil

确定结束日期。

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
LocalDate today = LocalDate.now( z ) ;

询问从开始到结束的日期流。

LocalDate stop = today.plusMonths( 1 ) ;

从该流中拉出日期,将它们收集到Stream< LocalDate > stream = today.datesUntil( today.plusMonths( 1 ) ); 中。

List

打印我们的日期列表,以标准List< LocalDate > datesForMonthFromToday = stream.collect( Collectors.toList() ); 格式生成文本。

ISO 8601

About java.time

System.out.println( datesForMonthFromToday ); 框架内置于Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,如legacyjava.util.DateCalendar

现在在SimpleDateFormatJoda-Time项目建议迁移到maintenance mode班。

要了解更多信息,请参阅java.time。并搜索Stack Overflow以获取许多示例和解释。规格是Oracle Tutorial

您可以直接与数据库交换java.time对象。使用符合JSR 310或更高版本的JDBC driver。不需要字符串,不需要JDBC 4.2类。

从哪里获取java.time类?

How to use ThreeTenABP…项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。你可能会在这里找到一些有用的类,如ThreeTen-ExtraIntervalYearWeekYearQuarter

© www.soinside.com 2019 - 2024. All rights reserved.