2016-01-09 44 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