获取当前date和星期开始的星期开始和结束date

如果可能的话,我宁愿在下面的情况下使用joda或非joda解决scheme

比方说,如果我的一周从02/05/2012开始,并且给定的当前date是2011年2月22日。 我需要计算给定当前date的周开始和结束date。 所以我的解决scheme应该有一周开始为02/19和周末在02/25。 为了简单起见,我已经把我的一周从2011年2月5日开始,但可能是任何一天,我的一周总是有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()); } 

试试这个(伪代码):

 // 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; 

请注意,我们减去了整数等date值来显示algorithm。 你必须正确编写你的java代码。

定义一周

如果您使用的是date时间对象,则应该定义一个星期,但不包括星期结束后的第一天。 如此图所示。

显示(> =第1天开始)和(第8天开始)

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

原因是因为在逻辑上,新一天的前一天的最后一刻,是一秒钟的一小部分,是无限可分的。 您可能会认为使用“.999”会在几毫秒内处理这个问题,但是在编写Java 8中的新的java.time。*类时,您会错误地使用毫秒级分辨率而不是毫秒。 您可能会认为使用“.999999999”来处理这种情况,但是当处理来自许多数据库(如使用微秒分辨率的Postgres“.999999”)的date时间值时,您会错误的。

在第三方开源Joda-Time库中,这个Half-Open逻辑是Interval类的工作原理。 开始是包容性的,结局是排他性的。 这很好地工作。 同样,在DateTime上调用plusWeeks(1)可以在一天中的第一个时刻添加一个星期,为您提供第八天后的第一个时刻(请参见下面的示例)。

时区

问题和其他答案忽略了时区的问题。 如果你没有指定,你会得到默认的时区。 通常最好指定一个时区,使用适当的时区名称 (不是3个字母的代码)。

乔达时间

避免与Java捆绑在一起的java.util.Date&Calendar类。 他们是非常麻烦的。

下面是使用Joda-Time 2.3的一些示例代码。

CAVEAT :我没有彻底地testing下面的代码。 只是我第一次采取一个粗略的草案。 可能是有缺陷的。

标准周(周一至周日)

Joda-Time库是围绕ISO 8601标准build立的。 该标准定义一周的第一天为星期一,最后一天为星期天。

如果那符合你一个星期的定义,那么得到开始和结束是容易的。

更新作为下面讨论的替代方法,请参阅SpaceTrucker这个非常聪明,非常简单的单线解决scheme 。

因为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 

要查看date时间是否在该时间间隔内,请调用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 

一周的第一天取决于国家。 是什么让计算脆弱,是一个可能打破年份边界,以及周数( 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 ,似乎只是给出相同的对象,因此最后你有相同的date。 (至lessJava 7)。

  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;