如果可能的话,我希望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());
}
答案 0 :(得分:8)
如果您正在使用日期时间对象,则应将周定义为最多但不包括星期结束后的第一天。如图所示。
此方法称为半开放。这种方法通常用于处理时间跨度。
原因是,从逻辑上讲,新一天前一天的最后一刻可以在几分之一秒内被无限分割。您可能认为使用“.999”会处理毫秒,但是当您在Java 8中编写具有纳秒分辨率而不是毫秒级的新java.time。*类时,您会犯错误。您可能认为使用“.999999999”会处理这种情况,但是当您处理许多数据库(如使用微秒分辨率的Postgres,“.999999”)的日期时间值时,您会被误认为。
在第三方开源Joda-Time库中,这个半开放逻辑是其Interval
类的工作原理。开头是包容性的,结尾是独家的。这很好用。同样地,在plusWeeks(1)
上调用DateTime
以将一周添加到一天中的第一个时刻会为您提供第8天的第一个时刻(请参阅下面的示例)。
问题和其他答案忽略了时区问题。如果您未指定,则您将获得默认时区。通常最好使用proper time zone name(不是3个字母的代码)来指定时区。
避免使用java.util.Date&与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代码。