定义一周
如果您使用日期时间对象,则应将一周定义为一周结束后一天的第一刻,但不包括这一刻。如图所示。
这种方法称为半开放。这种方法通常用于处理时间跨度。
原因是,从逻辑上讲,新一天的前一天的最后一刻在几分之一秒内是无限可分的。您可能认为使用“.999”可以处理几毫秒,但是当您在 Java 8 中编写具有纳秒分辨率而不是毫秒的新 java.time.* 类时,您会误会。您可能认为使用“.999999999”可以处理这种情况,但在处理来自许多使用微秒分辨率的 Postgres 等数据库的日期时间值时,您会误认为“.999999”。
在第三方开源的Joda-Time库中,这个Half-Open逻辑就是它的Interval类的工作原理。开头是包容的,结尾是排他的。这很好。同样,在DateTime 上调用plusWeeks(1) 将一周添加到一天的第一个时刻会为您提供第8 天后的第一个时刻(参见下面的示例)。
时区
问题和其他答案忽略了时区问题。如果您不指定,您将获得默认时区。通常最好使用proper time zone name(不是三字母代码)指定时区。
乔达时间
避免使用 Java 捆绑的 java.util.Date 和 Calendar 类。它们是出了名的麻烦。
这是一些使用 Joda-Time 2.3 的示例代码。
CAVEAT:我没有彻底测试过以下代码。只是我的初稿,草稿。可能有缺陷。
标准周(周一至周日)
Joda-Time 库是围绕ISO 8601 标准构建的。该标准将一周的第一天定义为星期一,最后一天定义为星期日。
如果这符合您对一周的定义,那么开始和结束就很容易了。
更新 作为下面讨论的替代方案,请参阅这个非常聪明且非常简单的单行代码solution by SpaceTrucker。
只需强制执行星期几即可,因为 Joda-Time 假设您需要:
- 星期一比今天早(或相同)。
- 星期日在今天之后(或与今天相同)。
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime now = new DateTime( timeZone );
DateTime weekStart = now.withDayOfWeek( DateTimeConstants.MONDAY ).withTimeAtStartOfDay();
DateTime weekEnd = now.withDayOfWeek(DateTimeConstants.SUNDAY).plusDays( 1 ).withTimeAtStartOfDay();
Interval week = new Interval( weekStart, weekEnd );
转储到控制台…
System.out.println( "now: " + now );
System.out.println( "weekStart: " + weekStart );
System.out.println( "weekEnd: " + weekEnd );
System.out.println( "week: " + week );
运行时……
now: 2014-01-24T06:29:23.043+01:00
weekStart: 2014-01-20T00:00:00.000+01:00
weekEnd: 2014-01-27T00:00:00.000+01:00
week: 2014-01-20T00:00:00.000+01:00/2014-01-27T00:00:00.000+01:00
要查看日期时间是否落在该间隔内,请调用 contains 方法。
boolean weekContainsDate = week.contains( now );
非标准周
如果这不符合您对一周的定义,那么您可以修改该代码。
DateTimeZone timeZone = DateTimeZone.forID( "America/New_York" );
DateTime now = new DateTime( timeZone );
DateTime weekStart = now.withDayOfWeek( DateTimeConstants.SUNDAY ).withTimeAtStartOfDay();
if ( now.isBefore( weekStart )) {
// If we got next Sunday, go back one week to last Sunday.
weekStart = weekStart.minusWeeks( 1 );
}
DateTime weekEnd = weekStart.plusWeeks( 1 );
Interval week = new Interval( weekStart, weekEnd );
转储到控制台…
System.out.println( "now: " + now );
System.out.println( "weekStart: " + weekStart );
System.out.println( "weekEnd: " + weekEnd );
System.out.println( "week: " + week );
运行时……
now: 2014-01-24T00:54:27.092-05:00
weekStart: 2014-01-19T00:00:00.000-05:00
weekEnd: 2014-01-26T00:00:00.000-05:00
week: 2014-01-19T00:00:00.000-05:00/2014-01-26T00:00:00.000-05:00