該Answer by Jon Skeet是正確的,應該被接受。你一年中的日曆年與一年中的一週相比令人困惑。
周基年
如果我們是在談論一個星期的標準ISO 8601的定義,這意味着:
- 周是從週一至週日。
- 第#周是包含該日曆年的第一個星期四的一週。
都說第一個星期四是1月2日,這意味着週三的前一天是1,和之前的週一&週二在現有歷年的最後幾天,但在以下爲本週年份。所以你不能將日曆年數字與以周爲基礎的年份數字混在一起。
避免遺留日期時類
此外,您使用的麻煩舊日期時間類,如Calendar
這是現在的傳統,由java.time類取代。
LocalDate
首先獲取當前日期。 LocalDate
類表示沒有時間和不帶時區的僅限日期的值。
時區是在確定的日期是至關重要的。對於任何特定的時刻,日期因地區而異。例如,Paris France午夜後幾分鐘是新的一天,而在Montréal Québec仍然是「昨天」。
在continent/region
的格式指定一個proper time zone name,如America/Montreal
,Africa/Casablanca
,或Pacific/Auckland
。切勿使用3-4字母縮寫,如EST
或IST
,因爲它們是而不是真正的時區,不是標準化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of("America/Montreal");
LocalDate today = LocalDate.now(z);
IsoFields
使用IsoFields
類獲取ISO 8601 week數。並獲取以星期爲基準的年曆的年份編號。
int weekNumber = today.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
int yearNumberOfWeekBasedYear = today.get(IsoFields.WEEK_BASED_YEAR); // Around end/beginning of year, may be different than calendar-year number.
讓我們再具體的例子,2017年的第一天。注意它的日曆年當然是2017年,但因爲它在週日登陸,所以它在以星期爲基準年的2016(不是2017年!)的最後一週(#52)。
LocalDate firstOf2017 = LocalDate.of (2017 , Month.JANUARY , 1);
DayOfWeek firstOf2017DayOfWeek = firstOf2017.getDayOfWeek();
int weekNumber = firstOf2017.get (IsoFields.WEEK_OF_WEEK_BASED_YEAR);
int yearNumberOfWeekBasedYear = firstOf2017.get (IsoFields.WEEK_BASED_YEAR); // Around end/beginning of year, may be different than calendar-year number.
int yearNumberOfCalendarYear = firstOf2017.getYear();
轉儲到控制檯。
System.out.println ("firstOf2017.toString(): " + firstOf2017);
System.out.println ("firstOf2017DayOfWeek.toString(): " + firstOf2017DayOfWeek);
System.out.println ("weekNumber: " + weekNumber);
System.out.println ("yearNumberOfWeekBasedYear: " + yearNumberOfWeekBasedYear);
System.out.println ("yearNumberOfCalendarYear: " + yearNumberOfCalendarYear);
firstOf2017.toString():2017年1月1日
firstOf2017DayOfWeek.toString():星期日
weekNumber:52
yearNumberOfWeekBasedYear:2016
yearNumberOfCalendarYear :2017
本週數學
您可以使用LocalDate
類減去幾周。
LocalDate ld = firstOf2017.minusWeeks(3);
YearWeek
你可能會想在ThreeTen-Extra庫添加到您的項目訪問YearWeek
類。
YearWeek yearWeek = YearWeek.of(2016 , 3); // Week # 3 of week-based year 2016.
通過指定DayOfWeek
枚舉對象來獲取當週的某一天。
LocalDate ld = yearWeek.atDay(DayOfWeek.MONDAY);
2016年1月18日
添加三個星期。
LocalDate threeWeeksLater = ld.plusWeeks(3);
2016年2月8日
獲取新的日期的週數。
YearWeek yearWeek2 = YearWeek.from(threeWeeksLater);
int weekNumber = yearWeek2.getWeek();
int yearNumberOfWeekBasedYear = yearWeek2.getYear();
生成標準ISO 8601字符串表示。
String output = yearWeek2.toString();
2016 W06
關於java.time
的java.time框架是建立在Java 8和更高版本。這些類取代了日期時間類legacy,如java.util.Date
,Calendar
,& SimpleDateFormat
。
Joda-Time項目現在位於maintenance mode,建議遷移到java.time類。請參閱Oracle Tutorial。並搜索堆棧溢出了很多例子和解釋。規格是JSR 310。
從何處獲取java.time類?
的ThreeTen-Extra項目與其他類擴展java.time。這個項目是未來可能增加java.time的一個試驗場。您可以在這裏找到一些有用的類,如Interval
,YearWeek
,YearQuarter
和more。
您是否考慮過使用jodatime?這是一個日期處理庫,它被認爲遠遠優於Java的標準Date和Calendar類。它還有一種方法可以從現有的DateTime中創建一個定義爲「3周」的特定期間的新DateTime。 http://joda-time.sourceforge.net/ – Philipp
我忘了緊張的jodatime ......這是一個偉大的時間庫。 – Nico