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

时间:2012-02-10 22:43:19

标签: 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());
}

4 个答案:

答案 0 :(得分:8)

定义一周

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

Timeline showing ( >= start of day 1 ) and ( < start of day 8 )

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

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

在第三方开源Joda-Time库中,这个半开放逻辑是其Interval类的工作原理。开头是包容性的,结尾是独家的。这很好用。同样地,在plusWeeks(1)上调用DateTime以将一周添加到一天中的第一个时刻会为您提供第8天的第一个时刻(请参阅下面的示例)。

时区

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

约达时间

避免使用java.util.Date&amp;与Java捆绑在一起的日历类。他们是出了名的麻烦。

以下是使用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

答案 1 :(得分:3)

一周的第一天取决于国家。 使计算变得脆弱的是,可以打破年边界和周数(Calendar.WEEK_OF_YEAR)。以下是:

    Calendar currentDate = Calendar.getInstance(Locale.US);
    int firstDayOfWeek = currentDate.getFirstDayOfWeek();

    Calendar startDate = Calendar.getInstance(Locale.US);
    startDate.setTime(currentDate.getTime());
    //while (startDate.get(Calendar.DAY_OF_WEEK) != firstDayOfWeek) {
    //    startDate.add(Calendar.DATE, -1);
    //}
    int days = (startDate.get(Calendar.DAY_OF_WEEK) + 7 - firstDayOfWeek) % 7;
    startDate.add(Calendar.DATE, -days);

    Calendar endDate = Calendar.getInstance(Locale.US);
    endDate.setTime(startDate.getTime());
    endDate.add(Calendar.DATE, 6);

日历中的一个错误会破坏您的代码,clone,似乎只是提供相同的对象,因此最后您有相同的日期。 (至少Java 7)。

答案 2 :(得分:1)

 DateTime sDateTime = new DateTime(startDate); // My calendar start date
 DateTime eDateTime = new DateTime(date); // the date for the week to be determined

 Interval interval = new Interval(sDateTime, sDateTime.plusWeeks(1));
 while(!interval.contains(eDateTime))
 {
    interval = new Interval(interval.getEnd(), interval.getEnd().plusWeeks(1));
 }
 return interval;

答案 3 :(得分:0)

试试这个(伪代码):

// How many days gone after reference date (a known week-start date)
daysGone  = today - referenceDate;

// A new week starts after each 7 days
dayOfWeek = daysGone % 7;

// Now, we know today is which day of the week.
// We can find start & end days of this week with ease
weekStart = today - dayOfWeek;
weekEnd   = weekStart + 6;

现在,我们可以缩短所有这两行:

weekStart = today - ((today - referenceDate) % 7);
weekEnd   = weekStart + 6;

请注意我们减去日期值,如整数来显示算法。你必须正确编写你的java代码。