简体   繁体   English

Mongodb $ week和Java Calendar.WEEK_OF_YEAR

[英]Mongodb $week and Java Calendar.WEEK_OF_YEAR

Mongodb's $week operator states Mongodb的$周运营商表示

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.

whereas, Java Calendar's DAY_OF_WEEK returns slightly differently (US Locale). 然而,Java Calendar的DAY_OF_WEEK返回略有不同(US Locale)。 For instance, for 2013, mongo's week 1 is actually week 2. 例如,对于2013年,mongo的第1周实际上是第2周。

My question is, adding arbitrary 1 does not solve the problem. 我的问题是,添加任意1并不能解决问题。 Is there a formula I can use to determine which week number to use to get the week start date. 是否有一个公式我可以用来确定用于获取周开始日期的周数。

Scenario: I am running an aggregation in mongo which returns me a week number. 场景:我在mongo中运行聚合,它返回一个星期的数字。 Based on the week number, I need to arrive at week start date. 根据周数,我需要在周开始日期到达。

Would something like the following work always? 总是喜欢以下工作吗? Assume calendar is another instance of Calendar. 假设日历是Calendar的另一个实例。

    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);
    }

I would avoid bringing the Java week-of-year into the picture at all - unless you can persuade MongoDB to stop being so broken, somehow. 除非你能说服MongoDB不再以某种方式破坏它,否则我会避免将Java周年带入图片中。 (That's a really odd definition of week-of-year; I'd normally use the ISO-8601 definition.) (这是一个非常奇怪的周年定义;我通常使用ISO-8601定义。)

If you really need to this with java.util.Calendar , you could probably use something like this (untested): 如果你真的需要使用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);

Note that if the week number is 0, the start of the week could easily be in a calendar year before the current one. 请注意,如果周数为0,则一周的开始可能很容易在当前一周之前的日历年。

If you have any choice in which date/time API you use, I would strongly recommend that you use Joda Time or java.time instead of Calendar though - then you can work with LocalDate instead, and have a much saner time. 如果你有其中的日期/时间API你使用任何选择,我会强烈建议你使用乔达时间或java.time而不是Calendar虽然-那么你就可以工作LocalDate替代,并有一个更理智的时间。

I've written a slightly different method, and tested it against every week in 2013 and 2014, and it seems to work: 我写了一个略有不同的方法,并在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();
}

I'm returning it as a Date for testing purposes, but obviously you can do what you need to it. 我将它作为日期返回测试目的,但显然你可以做你需要的。 It assumes you wanted Sunday as the start of the week, but again you can tweak this to Monday or whatever your requirements are. 它假设您希望星期日作为一周的开始,但您可以再次将其调整为星期一或任何您的要求。

I wrote a Spock test to check it because of Spock's amazing data-driven testing: 我写了一个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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM