![](/img/trans.png)
[英]Java 8 LocalDateTime - How to Get All Times Between Two Dates
[英]Java 8 LocalDate - How do I get all dates between two dates?
是否可以在新的java.time
API中获取两个日期之间的所有日期 ?
假设我有这部分代码:
@Test
public void testGenerateChartCalendarData() {
LocalDate startDate = LocalDate.now();
LocalDate endDate = startDate.plusMonths(1);
endDate = endDate.withDayOfMonth(endDate.lengthOfMonth());
}
现在我需要startDate
和endDate
之间的所有日期。
我想要获取两个日期之间的daysBetween
并迭代:
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)) ...
就像是:
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;
}
}
添加equals和hashcode方法,getters,可能有一个静态工厂+私有构造函数来匹配Java时间API的编码风格等是有意义的。
首先,您可以使用TemporalAdjuster
来获取该月的最后一天。 接下来, Stream
API提供了Stream::iterate
,它是适合您的问题的正确工具。
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);
Java 9
在Java 9中, LocalDate
类使用LocalDate.datesUntil(LocalDate endExclusive)方法进行了增强,该方法以Stream<LocalDate>
形式返回日期范围内的所有日期。
List<LocalDate> dates = startDate.datesUntil(endDate).collect(Collectors.toList());
您可以使用.isAfter和.plusDays在循环中执行此操作。 我不会说更好,因为我没有对该主题进行大量研究,但我可以自信地说它使用Java 8 API并且是一个轻微的替代方案。
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
您可以创建LocalDate
对象stream
。 我也有这个问题,我在github上将我的解决方案发布为java-timestream。
用你的例子......
LocalDateStream
.from(LocalDate.now())
.to(1, ChronoUnit.MONTHS)
.stream()
.collect(Collectors.toList());
它或多或少等同于此处提出的其他解决方案,但它会处理所有日期数学并知道何时停止。 您可以提供特定或相对结束日期,并告诉它跳过每次迭代的时间(上面的默认值是一天)。
ThreeTen-Extra库有一个LocalDateRange类,可以完全按照您的要求执行:
LocalDateRange.ofClosed(startDate, endDate).stream()
.forEach(/* ...do the stuff with the new date... */);
在我的Time4J时间库中,我编写了一个优化的spliterator来构建具有良好并行化特征的日历日期流。 适应您的用例:
LocalDate start = ...;
LocalDate end = ...;
Stream<LocalDate> stream =
DateInterval.between(start, end) // closed interval, else use .withOpenEnd()
.streamDaily()
.map(PlainDate::toTemporalAccessor);
如果您还对每个日历日期的时钟间隔(分区流)或其他间隔功能等相关功能感兴趣并希望避免使用笨拙的手写代码,则此简短方法可能是一个有趣的起点,另请参阅DateInterval的API。
扩展了Singh的优秀答案 ,使用来自Java 9及更高版本的datesUntil
的流。
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.
[2018-09-20,2018-09-21,2018-09-22,2018-09-23,2018-09-24,2018-09-25,2018-09-26,2018-09-27,20188 -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-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]
LocalDate::datesUntil
流 从Java 9开始,您可以要求提供日期流。 调用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格式的文本。
System.out.println( datesForMonthFromToday );
java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的类,比如Interval
, YearWeek
, YearQuarter
,和更多 。
您可以在Google的Guava库中使用Range功能。 在LocalDate
实例上定义DiscreteDomain之后,您可以获得范围内所有日期的ContiguousSet 。
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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.