即时toString prepends plus

nit*_*712 16 java tostring java-8 java-time

我们的数据存储区中的记录具有有效和到期时间.此信息使用字符串表示形式存储Instant.

有些记录永远不会过期.但由于到期日的值是强制性的,我们决定存储字符串表示Instant.MAX.

到现在为止还挺好.我们有搜索用例来返回在输入时间范围内有效的所有记录[s,e].我们查询数据存储区并返回[Si, Ei]满足条件的所有此类记录Si < s && e < Ei请注意,此处将比较字符串表示形式.

现在的问题是,+它被预先添加到字符串表示中Instant.MAX.这是失败的条件e < Ei,因为ASCII('+') < ASCII(digit).

我已经写了一段代码知道之后second,+开始得到前提:

Long e = Instant.now().getEpochSecond()*1000;
for (int i = 0; i < 5; i++) {
    System.out.println(e + "->" + Instant.ofEpochMilli(e));
    e *= 10;
}
Run Code Online (Sandbox Code Playgroud)

打印:

1471925168000->2016-08-23T04:06:08Z
14719251680000->2436-06-07T17:01:20Z
147192516800000->6634-05-07T02:13:20Z
1471925168000000->+48613-06-14T22:13:20Z
14719251680000000->+468404-07-08T06:13:20Z
Run Code Online (Sandbox Code Playgroud)

我可以选择截断+之前持久化的数据存储区.我更感兴趣的是为什么会这样,我们怎么能明确地避免它呢?

And*_*gin 11

你的问题'为什么?'的答案 隐藏在执行中DateTimeFormatterBuilder.InstantPrinterParser.format()(为了简洁我遗漏了不相关的代码):

// use INSTANT_SECONDS, thus this code is not bound by Instant.MAX
Long inSec = context.getValue(INSTANT_SECONDS);
if (inSec >= -SECONDS_0000_TO_1970) {
    // current era
    long zeroSecs = inSec - SECONDS_PER_10000_YEARS + SECONDS_0000_TO_1970;
    long hi = Math.floorDiv(zeroSecs, SECONDS_PER_10000_YEARS) + 1;
    long lo = Math.floorMod(zeroSecs, SECONDS_PER_10000_YEARS);
    LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, 0, ZoneOffset.UTC);
    if (hi > 0) {
         buf.append('+').append(hi);
    }
    buf.append(ldt);
}
Run Code Online (Sandbox Code Playgroud)

如您所见,它检查10000年期间的边界,如果该值超过其中至少一个,则会增加+这些期间的数量.

因此,为防止此类行为,请将最大日期保留在纪元边界内,请勿使用Instant.MAX.