2016-01-09 40 views
3

我的代碼工作得很好。今天,突然我開始這個例外 - org.threeten.bp.DateTimeException: Field DayOfMonth cannot be printed as the value 1872095944 max width is 2 這是我簡單的代碼:怪異org.threeten.bp.DateTimeException拋出?

LocalDateTime date = LocalDateTime.now(); 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd - MM - uuuu"); 
    String sDate = date.format(formatter);//EXCEPTION THROWN HERE 

爲什麼這個問題突然?

編輯

這似乎是一箇中間問題。它有時會崩潰,並且在其他時間運行良好。沒有關於發生什麼的線索。 A

+0

什麼是108795?你的約會? – sasikumar

+0

@sasikumar:實際上它是1872095944.已更新問題。我不確定那是否是日期。你的意思是毫秒吧? – Ashwin

回答

0

api中是否有任何近期更改。我在允許的模式列表中看不到任何選項。

Symbol Meaning      Presentation  Examples 

    ------ -------      ------------  ------- 

    G  era       number/text  1; 01; AD; Anno 
Domini 

    y  year      year    2004; 04 

    D  day-of-year     number   189 

    M  month-of-year    number/text  7; 07; Jul; July; J 

    d  day-of-month    number   10 


    Q  quarter-of-year    number/text  3; 03; Q3 


    Y  week-based-year    year    1996; 96 


    w  week-of-year    number   27 

    W  week-of-month    number   27 

    e  localized day-of-week  number   2; Tue; Tuesday; T 

    E  day-of-week     number/text  2; Tue; Tuesday; T 

    F  week-of-month    number   3 


    a  am-pm-of-day    text    PM 

    h  clock-hour-of-am-pm (1-12) number   12 

    K  hour-of-am-pm (0-11)  number   0 

    k  clock-hour-of-am-pm (1-24) number   0 

    H  hour-of-day (0-23)   number   0 

    m  minute-of-hour    number   30 


    s  second-of-minute   number   55 

    S  fraction-of-second   fraction   978 

    A  milli-of-day    number   1234 

    n  nano-of-second    number   987654321 

    N  nano-of-day     number   1234000000 

    V  time-zone ID    zone-id America/Los_Angeles; Z; -08:30 

    z  time-zone name    zone-name Pacific Standard Time; PST 

    X  zone-offset 'Z' for zero offset-X   Z; -08; -0830; -08:30; -083015; -08:30:15; 

    x  zone-offset     offset-x   +0000; -08; -0830; -08:30; -083015; -08:30:15; 

    Z  zone-offset     offset-Z   +0000; -0800; -08:00; 


    p  pad next     pad modifier  1 

    '  escape for text    delimiter 


    ''  single quote    literal   ' 

[  optional section start 

]  optional section end 

{}  reserved for future use 
+0

我將它改爲'yyyy'。它起初工作。但是,這個問題又一次出現了,同樣的例外。這是一箇中間問題。有時它有效,有時會引發exceptin – Ashwin

+0

是的,你有一個過時的javadoc。實際的人知道你(作爲公理年),看看[Oracle](http://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)。 –

1

這是不太格式化的問題(這裏只是一種症狀),而是如何創造的LocalDateTime實例的問題。根本原因僅僅是LocalDateTime.now()在某些罕見情況下似乎會產生一個完全超出範圍的日期。在3ten-bp的問題跟蹤器上,此問題可能與此issue有關。

LocalDate.ofEpochDay(X)有時會返回一個錯誤的或非法的結果 ,而不是拋出一個異常的X值較大。對於 實例,LocalDate.ofEpochDay(9223371671611556645L)返回日期 ,其中d.getDayOfMonth()爲負值,而不是拋出 DateTimeException。

請記住,該方法now()必須做背景的時代轉換,最後調用LocalDate.ofEpochDay(...)。所以如果你的時鐘在Unix時代以毫秒爲單位產生一個非常規的紀元值,那麼這也會影響到now()。而您的格式化工具只需從LocalDateTime中取得月份中的有效日期即getDayOfMonth()(實際上是通過TemporalAccessor中的字段訪問)。有問題的源代碼:

281  public static LocalDate ofEpochDay(long epochDay) { 
282   long zeroDay = epochDay + DAYS_0000_TO_1970; 
283   // find the march-based year 
284   zeroDay -= 60; // adjust to 0000-03-01 so leap day is at end of four year cycle 
285   long adjust = 0; 
286   if (zeroDay < 0) { 
287    // adjust negative years to positive for calculation 
288    long adjustCycles = (zeroDay + 1)/DAYS_PER_CYCLE - 1; 
289    adjust = adjustCycles * 400; 
290    zeroDay += -adjustCycles * DAYS_PER_CYCLE; 
291   } 
292   long yearEst = (400 * zeroDay + 591)/DAYS_PER_CYCLE; 
293   long doyEst = zeroDay - (365 * yearEst + yearEst/4 - yearEst/100 + yearEst/400); 
294   if (doyEst < 0) { 
295    // fix estimate 
296    yearEst--; 
297    doyEst = zeroDay - (365 * yearEst + yearEst/4 - yearEst/100 + yearEst/400); 
298   } 
299   yearEst += adjust; // reset any negative year 
300   int marchDoy0 = (int) doyEst; 
301 

302   // convert march-based values back to january-based 
303   int marchMonth0 = (marchDoy0 * 5 + 2)/153; 
304   int month = (marchMonth0 + 2) % 12 + 1; 
305   int dom = marchDoy0 - (marchMonth0 * 306 + 5)/10 + 1; 
306   yearEst += marchMonth0/10; 
307 

308   // check year now we are certain it is correct 
309   int year = YEAR.checkValidIntValue(yearEst); 
310   return new LocalDate(year, month, dom); 
311  } 

最有趣,最可疑的是,僅年被驗證,而不是一個月或個月某一天的。的確,看看包含四個部分這一離奇的結果由負字符(???)分隔:

LocalDate d = LocalDate.ofEpochDay(9223371671611556645L); 
System.out.println(d); // -999999999-02-0-30 
System.out.println(d.getDayOfMonth()); // -30 

顯然,庫代碼被打破了一些異國情調可能由生產時代天數你的時鐘不幸。 我也在Java-8中測試了相同的代碼,結果相同。

更新:

到目前爲止所示的LocalDate.ofEpochDay(long)原始代碼肯定是壞還因爲一個事實,即存在於數字/算術溢出不檢查。例如:像Long.MAX_VALUE這樣的輸入會導致表達式epochDay + DAYS_0000_TO_1970溢出並將符號更改爲負值。類似地,當使用表達式400 * zeroDay時,輸入Long.MIN_VALUE將最終溢出。我擔心這不是顯示代碼的唯一問題。作爲比較:格雷戈里爾算法的正確實施將看起來像my own time library

旁註:

通過我的圖書館Time4J幫助我分析給定測試輸入上方將產生每年遠出界在threeten-BP定義,太(範圍爲-999999999至+ 999999999):

PlainDate date = PlainDate.of(9223371671611556645L, EpochDays.UNIX); 
// java.lang.IllegalArgumentException: Year out of range: 25252733927766555 

我不太清楚你能做些什麼來解決問題。

第一件事是記錄您的時鐘產生的所有輸入,將它們與觀察到的3ten-bp的小車行爲相關聯,並且做一些研究爲什麼您的時鐘有時會發瘋。

關於threeten-bp(和Java-8!)中的錯誤,您可以希望threeten-bp-project團隊很快就會修復它(或者說Oracle!)。導致問題的輸入可能是錯誤的,因此您應該最好捕獲異常並將時鐘錯誤(作爲根本原因)的額外消息記錄下來。

+0

我同時發現產生負月數的另一個值是:'9223372036854056247L' –

+0

已在backport中修復 - https://github.com/ThreeTen/threetenbp/issues/39 – JodaStephen