3

Mongodb 的$week 运算符状态

Takes a date and returns the week of the year as a number between 0 and 53.

Weeks begin on Sundays, and week 1 begins with the first Sunday of the year. Days 
preceding the first Sunday of the year are in week 0. This behavior is the same as the
 “%U” operator to the strftime standard library function.

然而,Java 日历的 DAY_OF_WEEK 返回略有不同(美国语言环境)。例如,对于 2013 年,mongo 的第 1 周实际上是第 2 周。

我的问题是,添加任意 1 并不能解决问题。是否有一个公式可以用来确定使用哪个周数来获取周开始日期。

场景:我在 mongo 中运行一个聚合,它返回一个周数。根据周数,我需要在周开始日期到达。

像下面这样的东西总是有效吗?假设日历是日历的另一个实例。

    Calendar firstDay = Calendar.getInstance(Locale.US);
    firstDay.set(Calendar.DAY_OF_YEAR, 1);
    int day = firstDay.get(Calendar.DAY_OF_WEEK);
    if (day != Calendar.SUNDAY){
        //both mongo and java calendar start in different weeks so add 1 to reconcile
        calendar.set(Calendar.WEEK_OF_YEAR, number.intValue()+1);
    }
4

2 回答 2

4

我会完全避免将 Java 的一周带入画面——除非你能说服 MongoDB 以某种方式停止如此糟糕。(这是一个非常奇怪的一年中星期的定义;我通常会使用 ISO-8601 定义。)

如果你真的需要这个java.util.Calendar,你可能会使用这样的东西(未经测试):

// You really want to do all of this on a "date" basis, without DST messing
// things up...
Calendar firstDay = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US);
firstDay.set(Calendar.DAY_OF_YEAR, 1);
while (firstDay.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
    firstDay.add(Calendar.DAY, 1);
}

// firstDay is now at the start of week 1 from a mongodb perspective...
// We just need to add the number of weeks.
firstDay.add(Calendar.Day, (mongoWeekNumber - 1) * 7);

请注意,如果周数为 0,则一周的开始很容易在当前日历年之前的日历年中。

如果您对使用的日期/时间 API 有任何选择,我强烈建议您使用 Joda Time 或使用 Joda Timejava.time来代替Calendar- 然后您可以使用它LocalDate,并拥有更清醒的时间。

于 2015-05-15T07:32:00.193 回答
0

我写了一个稍微不同的方法,并在 2013 年和 2014 年每周对其进行测试,它似乎有效:

private Date getStartingSundayDateForMongoWeek(int mongoWeekOfYear, int year) {
    Calendar calendar = Calendar.getInstance(US);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    calendar.setWeekDate(year, mongoWeekOfYear + 1, Calendar.SUNDAY);
    return calendar.getTime();
}

我将它作为日期返回用于测试目的,但显然你可以做你需要的。它假设您希望星期天作为一周的开始,但您可以再次将其调整为星期一或任何您的要求。

由于 Spock 惊人的数据驱动测试,我编写了一个 Spock 测试来检查它:

private static final SimpleDateFormat DATE_FORMAT_SHORT = new SimpleDateFormat("MMM dd yyyy", Locale.US)

@Unroll
def 'determine correct start of week as #startOfWeek from mongo week #mongoWeekOfYear'() {
    expect:
    startOfWeek == getStartingSundayDateForMongoWeek(mongoWeekOfYear, year)

    where:
    //taken from http://www.timeanddate.com/calendar/?year=2013&country=1
    startOfWeek                            | mongoWeekOfYear | year
    DATE_FORMAT_SHORT.parse("Dec 30 2012") | 0               | 2013
    DATE_FORMAT_SHORT.parse("Jan 6  2013") | 1               | 2013
    DATE_FORMAT_SHORT.parse("Jan 13 2013") | 2               | 2013
    DATE_FORMAT_SHORT.parse("Jan 20 2013") | 3               | 2013
    DATE_FORMAT_SHORT.parse("Jan 27 2013") | 4               | 2013
    DATE_FORMAT_SHORT.parse("Feb 3  2013") | 5               | 2013
    DATE_FORMAT_SHORT.parse("Feb 10 2013") | 6               | 2013
    DATE_FORMAT_SHORT.parse("Feb 17 2013") | 7               | 2013
    DATE_FORMAT_SHORT.parse("Feb 24 2013") | 8               | 2013
    DATE_FORMAT_SHORT.parse("Mar 3  2013") | 9               | 2013
    DATE_FORMAT_SHORT.parse("Mar 10 2013") | 10              | 2013
    DATE_FORMAT_SHORT.parse("Mar 17 2013") | 11              | 2013
    DATE_FORMAT_SHORT.parse("Mar 24 2013") | 12              | 2013
    DATE_FORMAT_SHORT.parse("Mar 31 2013") | 13              | 2013
    DATE_FORMAT_SHORT.parse("Apr 7  2013") | 14              | 2013
    DATE_FORMAT_SHORT.parse("Apr 14 2013") | 15              | 2013
    DATE_FORMAT_SHORT.parse("Apr 21 2013") | 16              | 2013
    DATE_FORMAT_SHORT.parse("Apr 28 2013") | 17              | 2013
    DATE_FORMAT_SHORT.parse("May 5  2013") | 18              | 2013
    DATE_FORMAT_SHORT.parse("May 12 2013") | 19              | 2013
    DATE_FORMAT_SHORT.parse("May 19 2013") | 20              | 2013
    DATE_FORMAT_SHORT.parse("May 26 2013") | 21              | 2013
    DATE_FORMAT_SHORT.parse("Jun 2  2013") | 22              | 2013
    DATE_FORMAT_SHORT.parse("Jun 9  2013") | 23              | 2013
    DATE_FORMAT_SHORT.parse("Jun 16 2013") | 24              | 2013
    DATE_FORMAT_SHORT.parse("Jun 23 2013") | 25              | 2013
    DATE_FORMAT_SHORT.parse("Jun 30 2013") | 26              | 2013
    DATE_FORMAT_SHORT.parse("Jul 7  2013") | 27              | 2013
    DATE_FORMAT_SHORT.parse("Jul 14 2013") | 28              | 2013
    DATE_FORMAT_SHORT.parse("Jul 21 2013") | 29              | 2013
    DATE_FORMAT_SHORT.parse("Jul 28 2013") | 30              | 2013
    DATE_FORMAT_SHORT.parse("Aug 4  2013") | 31              | 2013
    DATE_FORMAT_SHORT.parse("Aug 11 2013") | 32              | 2013
    DATE_FORMAT_SHORT.parse("Aug 18 2013") | 33              | 2013
    DATE_FORMAT_SHORT.parse("Aug 25 2013") | 34              | 2013
    DATE_FORMAT_SHORT.parse("Sep 1  2013") | 35              | 2013
    DATE_FORMAT_SHORT.parse("Sep 8  2013") | 36              | 2013
    DATE_FORMAT_SHORT.parse("Sep 15 2013") | 37              | 2013
    DATE_FORMAT_SHORT.parse("Sep 22 2013") | 38              | 2013
    DATE_FORMAT_SHORT.parse("Sep 29 2013") | 39              | 2013
    DATE_FORMAT_SHORT.parse("Oct 6  2013") | 40              | 2013
    DATE_FORMAT_SHORT.parse("Oct 13 2013") | 41              | 2013
    DATE_FORMAT_SHORT.parse("Oct 20 2013") | 42              | 2013
    DATE_FORMAT_SHORT.parse("Oct 27 2013") | 43              | 2013
    DATE_FORMAT_SHORT.parse("Nov 3  2013") | 44              | 2013
    DATE_FORMAT_SHORT.parse("Nov 10 2013") | 45              | 2013
    DATE_FORMAT_SHORT.parse("Nov 17 2013") | 46              | 2013
    DATE_FORMAT_SHORT.parse("Nov 24 2013") | 47              | 2013
    DATE_FORMAT_SHORT.parse("Dec 1  2013") | 48              | 2013
    DATE_FORMAT_SHORT.parse("Dec 8  2013") | 49              | 2013
    DATE_FORMAT_SHORT.parse("Dec 15 2013") | 50              | 2013
    DATE_FORMAT_SHORT.parse("Dec 22 2013") | 51              | 2013
    DATE_FORMAT_SHORT.parse("Dec 29 2013") | 0               | 2014
    DATE_FORMAT_SHORT.parse("Jan 5  2014") | 1               | 2014
    DATE_FORMAT_SHORT.parse("Jan 12 2014") | 2               | 2014
    DATE_FORMAT_SHORT.parse("Jan 19 2014") | 3               | 2014
    DATE_FORMAT_SHORT.parse("Jan 26 2014") | 4               | 2014
    DATE_FORMAT_SHORT.parse("Feb 2 2014")  | 5               | 2014
    DATE_FORMAT_SHORT.parse("Feb 9 2014")  | 6               | 2014
    DATE_FORMAT_SHORT.parse("Feb 16 2014") | 7               | 2014
    DATE_FORMAT_SHORT.parse("Feb 23 2014") | 8               | 2014
    DATE_FORMAT_SHORT.parse("Mar 2 2014")  | 9               | 2014
    DATE_FORMAT_SHORT.parse("Mar 9 2014")  | 10              | 2014
    DATE_FORMAT_SHORT.parse("Mar 16 2014") | 11              | 2014
    DATE_FORMAT_SHORT.parse("Mar 23 2014") | 12              | 2014
    DATE_FORMAT_SHORT.parse("Mar 30 2014") | 13              | 2014
    DATE_FORMAT_SHORT.parse("Apr 6 2014")  | 14              | 2014
    DATE_FORMAT_SHORT.parse("Apr 13 2014") | 15              | 2014
    DATE_FORMAT_SHORT.parse("Apr 20 2014") | 16              | 2014
    DATE_FORMAT_SHORT.parse("Apr 27 2014") | 17              | 2014
    DATE_FORMAT_SHORT.parse("May 4 2014")  | 18              | 2014
    DATE_FORMAT_SHORT.parse("May 11 2014") | 19              | 2014
    DATE_FORMAT_SHORT.parse("May 18 2014") | 20              | 2014
    DATE_FORMAT_SHORT.parse("May 25 2014") | 21              | 2014
    DATE_FORMAT_SHORT.parse("Jun 1 2014")  | 22              | 2014
    DATE_FORMAT_SHORT.parse("Jun 8 2014")  | 23              | 2014
    DATE_FORMAT_SHORT.parse("Jun 15 2014") | 24              | 2014
    DATE_FORMAT_SHORT.parse("Jun 22 2014") | 25              | 2014
    DATE_FORMAT_SHORT.parse("Jun 29 2014") | 26              | 2014
    DATE_FORMAT_SHORT.parse("Jul 6 2014")  | 27              | 2014
    DATE_FORMAT_SHORT.parse("Jul 13 2014") | 28              | 2014
    DATE_FORMAT_SHORT.parse("Jul 20 2014") | 29              | 2014
    DATE_FORMAT_SHORT.parse("Jul 27 2014") | 30              | 2014
    DATE_FORMAT_SHORT.parse("Aug 3 2014")  | 31              | 2014
    DATE_FORMAT_SHORT.parse("Aug 10 2014") | 32              | 2014
    DATE_FORMAT_SHORT.parse("Aug 17 2014") | 33              | 2014
    DATE_FORMAT_SHORT.parse("Aug 24 2014") | 34              | 2014
    DATE_FORMAT_SHORT.parse("Aug 31 2014") | 35              | 2014
    DATE_FORMAT_SHORT.parse("Sep 7 2014")  | 36              | 2014
    DATE_FORMAT_SHORT.parse("Sep 14 2014") | 37              | 2014
    DATE_FORMAT_SHORT.parse("Sep 21 2014") | 38              | 2014
    DATE_FORMAT_SHORT.parse("Sep 28 2014") | 39              | 2014
    DATE_FORMAT_SHORT.parse("Oct 5 2014")  | 40              | 2014
    DATE_FORMAT_SHORT.parse("Oct 12 2014") | 41              | 2014
    DATE_FORMAT_SHORT.parse("Oct 19 2014") | 42              | 2014
    DATE_FORMAT_SHORT.parse("Oct 26 2014") | 43              | 2014
    DATE_FORMAT_SHORT.parse("Nov 2 2014")  | 44              | 2014
    DATE_FORMAT_SHORT.parse("Nov 9 2014")  | 45              | 2014
    DATE_FORMAT_SHORT.parse("Nov 16 2014") | 46              | 2014
    DATE_FORMAT_SHORT.parse("Nov 23 2014") | 47              | 2014
    DATE_FORMAT_SHORT.parse("Nov 30 2014") | 48              | 2014
    DATE_FORMAT_SHORT.parse("Dec 7 2014")  | 49              | 2014
    DATE_FORMAT_SHORT.parse("Dec 14 2014") | 50              | 2014
    DATE_FORMAT_SHORT.parse("Dec 21 2014") | 51              | 2014
    DATE_FORMAT_SHORT.parse("Dec 28 2014") | 0               | 2015

    DATE_FORMAT_SHORT.parse("Jan 1  2017") | 0               | 2017
    DATE_FORMAT_SHORT.parse("Jan 8  2017") | 1               | 2017
    DATE_FORMAT_SHORT.parse("Jan 15 2017") | 2               | 2017
    DATE_FORMAT_SHORT.parse("Jan 22 2017") | 3               | 2017
    DATE_FORMAT_SHORT.parse("Jan 29 2017") | 4               | 2017
    DATE_FORMAT_SHORT.parse("Feb 5  2017") | 5               | 2017
    DATE_FORMAT_SHORT.parse("Feb 12 2017") | 6               | 2017
    DATE_FORMAT_SHORT.parse("Feb 19 2017") | 7               | 2017
    DATE_FORMAT_SHORT.parse("Feb 26 2017") | 8               | 2017
}
于 2013-07-05T11:36:43.950 回答