2012-11-23 51 views
2

我在Java日曆中遇到了一些問題。當我添加幾個星期日曆時,在某些情況下它不能正常工作。例如。將week_of_yer設置爲3,然後加上-3周;)在大多數情況下效果良好,但在2010年和2016年等效果不佳(今年是53周以後)。它看起來像在JDK錯誤,我認爲他們改變了一年,當週數是52:d一些簡單的代碼:Java日曆錯誤

Calendar calendar = new GregorianCalendar(); 
calendar.set(Calendar.YEAR, 2016); 
calendar.set(Calendar.WEEK_OF_YEAR, 3); 
calendar.add(Calendar.WEEK_OF_YEAR, -3); 
System.out.println("rolled week: " + calendar.get(Calendar.WEEK_OF_YEAR) + " - " + calendar.get(Calendar.YEAR)); 

這段代碼的結果是:熱軋周:53 - 2016年d

應在所有其他情況下,53 - 2015年它的工作原理應該如此。

有沒有人有類似的問題?

+1

您是否考慮過使用jodatime?這是一個日期處理庫,它被認爲遠遠優於Java的標準Date和Calendar類。它還有一種方法可以從現有的DateTime中創建一個定義爲「3周」的特定期間的新DateTime。 http://joda-time.sourceforge.net/ – Philipp

+0

我忘了緊張的jodatime ......這是一個偉大的時間庫。 – Nico

回答

4

問題是您顯示而不是週年。你不需要用日曆進行算術來顯示這一點。基本上你顯示年那是2016年1月1日2016年,但週年(即在該年的周的年計算)是2015年

不幸的是,據正如我所看到的,Java沒有獲取週年的方法。你最好關閉使用Joda Time,它可以讓你做這一切很容易:

import org.joda.time.*; 

public class Test { 
    public static void main(String[] args) throws Exception { 
     LocalDate date = new LocalDate(2016, 1, 1); 
     System.out.println(date); 
     System.out.println(date.getWeekOfWeekyear()); 
     System.out.println(date.getWeekyear()); 
    }  
} 

輸出:

2016-01-01 
53 
2015 
0

喬恩,你是對的。今天我注意到問題出在哪裏,這正是你所說的。我只對週數和年份感興趣,因此在將週數添加到星期幾之前,我將星期幾設置爲星期一。對我來說它有效。

Calendar calendar = new GregorianCalendar(); 
calendar.set(Calendar.YEAR, year); 
calendar.set(Calendar.WEEK_OF_YEAR, week); 
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); 
calendar.add(Calendar.WEEK_OF_YEAR, -51); 
0

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/MontrealAfrica/Casablanca,或Pacific/Auckland。切勿使用3-4字母縮寫,如ESTIST,因爲它們是而不是真正的時區,不是標準化的,甚至不是唯一的(!)。

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,YearQuartermore