给出当前日期和星期开始的周开始和结束日期

use*_*587 0 java date jodatime

如果可能的话,我希望joda或非joda解决方案适用于下面的场景

让我们说如果我的一周从02/05/2012开始,并且给定的当前日期是02/22/2011.我需要计算给定当前日期的周开始日期和结束日期.因此,我的解决方案应该在02/19开始一周,在02/25结束一周.为简单起见,我已将我的周开始时间设置为02/05/2011,但它可能是任何一天,我的周总有7天.

我现有的代码如下,但似乎没有按预期工作.

public Interval getWeekInterval(Date calendarStartDate, Date date)
{
    Calendar sDate = Calendar.getInstance();
    sDate.setTime(getMidnightDate(calendarStartDate));

    Calendar eDate = Calendar.getInstance();
    eDate.setTime(date);

    Calendar weekStartDate = (Calendar) sDate.clone();
    logger.debug("Date:" + sDate.getTime());
    while (sDate.before(eDate)) {
        weekStartDate = sDate;
        sDate.add(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
    }

    return new Interval(weekStartDate.getTime(), sDate.getTime());
}
Run Code Online (Sandbox Code Playgroud)

Bas*_*que 8

定义一周

如果您使用的是日期时间对象,则应将周定义为最多但不包括星期结束后的第一天.如图所示.

时间轴显示(> =第1天开始)和(<第8天开始)

这种方法称为半开放式.这种方法通常用于处理时间跨度.

原因是,从逻辑上讲,新一天前一天的最后一刻可以在几分之一秒内被无限分割.您可能认为使用".999"会处理毫秒,但是当您在Java 8中编写具有纳秒分辨率而非毫秒级的新java.time.*类时,您会犯错误.您可能会认为使用".999999999"会处理这种情况,但是当处理来自许多数据库(如使用微秒分辨率的Postgres,".999999")的日期时间值时,您会被误解.

在第三方开源Joda-Time库中,这个半开放逻辑就是它的Interval类如何工作.开头是包容性的,结尾是独家的.这很好用.同样地,呼叫plusWeeks(1)a DateTime将一周添加到一天中的第一个时刻会给出第8天的第一个时刻(参见下面的示例).

时区

问题和其他答案忽略了时区问题.如果您未指定,则您将获得默认时区.通常最好使用适当的时区名称(不是3个字母的代码)来指定时区.

乔达时间

避免使用Java捆绑的java.util.Date和Calendar类.众所周知,它们很麻烦.

以下是使用Joda-Time 2.3的一些示例代码.

CAVEAT:我没有彻底测试下面的代码.只是我的第一次采访,草稿.可能有缺陷.

标准周(周一至周日)

Joda-Time库是围绕ISO 8601标准构建的.该标准将星期的第一天定义为星期一,最后一天定义为星期日.

如果这符合您对一周的定义,那么开始和结束很容易.

更新作为下面讨论的替代方案,请参阅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 );
Run Code Online (Sandbox Code Playgroud)

转储到控制台......

System.out.println( "now: " + now );
System.out.println( "weekStart: " + weekStart );
System.out.println( "weekEnd: " + weekEnd );
System.out.println( "week: " + week );
Run Code Online (Sandbox Code Playgroud)

跑的时候......

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
Run Code Online (Sandbox Code Playgroud)

要查看日期时间是否落在该间隔内,请调用该contains方法.

boolean weekContainsDate = week.contains( now );
Run Code Online (Sandbox Code Playgroud)

非标准周

如果这不符合您对一周的定义,那么您就可以对该代码进行改动.

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 );
Run Code Online (Sandbox Code Playgroud)

转储到控制台......

System.out.println( "now: " + now );
System.out.println( "weekStart: " + weekStart );
System.out.println( "weekEnd: " + weekEnd );
System.out.println( "week: " + week );
Run Code Online (Sandbox Code Playgroud)

跑的时候......

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
Run Code Online (Sandbox Code Playgroud)