2013-07-05 17 views
3

MongoDB的$week operator狀態

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

你說「根據週數,我需要到達周開始日期。」 - 從星期天開始?星期一?或特定於語言環境? – Trisha

+0

@Trisha在這種情況下,我正在將星期日視爲每週的第一天。但通用的解決方案將受到歡迎。我試圖解決的問題特別針對美國區域設置。 – Nasir

+0

我想我在這裏得到了一個很好的答案http://stackoverflow.com/a/30247836/2366413 –

回答

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的驚人數據驅動測試:

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 
} 
+0

謝謝。我還沒有進行測試,但從代碼判斷,它出現在2017年1月1日mongoweek將與日曆周相同,因此所有周都會因爲+1而改變1 - 因此2017年的周將不正確。 (也許,你可以做一個快速檢查,2017年1月1日和2017年1月15日應該足夠了。) – Nasir

+1

我已經爲2017年添加了測試,測試依然通過。 – Trisha

+0

對於您的測試數據 - 2017年1月1日,mongo列應爲1而不是0。由於1月1日是一年中的第一個週日,因此週數爲1(根據mongo規格爲$周)。我期望現在你會看到不同:)。同樣,其他數字應該高於1(僅適用於2017年) – Nasir

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,我強烈建議你使用喬達時間或java.time代替Calendar雖然 - 那麼你可以用LocalDate工作,而是和有一個更理智的時間。