当字母数为四时,如何在 DateTimeFormatter 中打印年号?

How to print year sign in DateTimeFormatter when the count of letters is four?

来自 DateTimeFormatter javadoc:

If the count of letters is less than four (but not two), then the sign is only output for negative years as per SignStyle.NORMAL. Otherwise, the sign is output if the pad width is exceeded, as per SignStyle.EXCEEDS_PAD.

据我了解,如果不超过 pad 宽度且字母数为 4,则在格式化期间不应打印减号(负数年份)。

所以我写了这样一段代码(考虑到我不能使用'y'因为那样年份总是正数):

    var negativeDate = LocalDate.now().minus(2021, ChronoUnit.YEARS);
    var formatter = DateTimeFormatter.ofPattern("ppppuuuu");
    var text = negativeDate.format(formatter);
    System.out.println("formatted string: " + text);

此代码抛出 DateTimeException:“无法打印,因为 5 个字符的输出超出了填充宽度 4”。

所以我的问题基本上是 如何从 javadoc 作品中看到最后一句话

If the count of letters is less than four (but not two), then the sign is only output for negative years as per SignStyle.NORMAL.

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

public class Main {
    public static void main(String[] args) {
        var negativeDate = LocalDate.now().minus(2021, ChronoUnit.YEARS);
        var formatter1 = DateTimeFormatter.ofPattern("ppuu");
        var formatter2 = DateTimeFormatter.ofPattern("ppu");
        var text1 = negativeDate.format(formatter1);
        var text2 = negativeDate.format(formatter2);
        System.out.println("formatted string: year" + text1);
        System.out.println("formatted string: year" + text2);
    }
}

输出:

formatted string: year01
formatted string: year-1

我在 formatter1 中使用了 uu(字母数为两个),因此它不显示负号。但是,如果字母数少于四个而不是两个,则需要提供足够的填充,例如对于这一年,-1,您至少需要填充 2(即 pp),一个用于 - 符号,一个用于 1。如果您提供的填充数量较少,您将获得 DateTimeException,如果您提供的填充数量超过 2,您将在 -1.

之前获得 space

因此,在格式 uuuu 的情况下,负数年份至少需要 5(即 ppppp)的填充,- 需要一个填充和 4 多年 (0001) 即你需要使用 DateTimeFormatter.ofPattern("pppppuuuu") 来避免 DateTimeException.

此模式 "ppppuuuu" 定义 padWidth of 4 应用于以下格式 uuuu,它应用 SignStyle.EXCEEDS_PAD(根据 javadoc for DateTimeFormatBuilder)。

也就是说,由于当前 SignStyle.

总是打印 -

因此,当格式化程序尝试打印负数年份时,它使用了 4 位数字和一个符号,因此超出了可用 padWidth

类似地,当使用 uuuu 模式时,符号总是 打印,因为在这些情况下应用 SignStyle.NORMAL

因此,只有在使用uu格式时才不会打印标志。

为避免出现负数异常,padding 应超过位数,例如"ppppu""pppppuuuu".

var onlyU = DateTimeFormatter.ofPattern("uuuu");
var padded = DateTimeFormatter.ofPattern("ppppu");
var padded5 = DateTimeFormatter.ofPattern("pppppuuuu");

for (LocalDate d = LocalDate.now().minus(2421, ChronoUnit.YEARS); d.getYear() < 2200; d = d.plus(400, ChronoUnit.YEARS)) {

    try {
        var uuuu  = d.format(onlyU);
        var ppppu = d.format(padded);
        var pppppuuuu = d.format(padded5);

        System.out.printf("formatted year=%5d\tuuuu=[%s] \tppppu=[%s]\tpppppuuuu=[%s]%n", d.getYear(), uuuu, ppppu, pppppuuuu);

    } catch (DateTimeException e) {
        System.out.println("error: " + e);  
    }
}

输出:

formatted year= -401    uuuu=[-0401]    ppppu=[-401]    pppppuuuu=[-0401]
formatted year=   -1    uuuu=[-0001]    ppppu=[  -1]    pppppuuuu=[-0001]
formatted year=  399    uuuu=[0399]     ppppu=[ 399]    pppppuuuu=[ 0399]
formatted year=  799    uuuu=[0799]     ppppu=[ 799]    pppppuuuu=[ 0799]
formatted year= 1199    uuuu=[1199]     ppppu=[1199]    pppppuuuu=[ 1199]
formatted year= 1599    uuuu=[1599]     ppppu=[1599]    pppppuuuu=[ 1599]
formatted year= 1999    uuuu=[1999]     ppppu=[1999]    pppppuuuu=[ 1999]

你问的句子中的Otherwise是指字母数大于或等于4的情况。令人困惑的是,这里的 pad width 与用于填充的模式字母 p 无关。它是指要打印的位数。它指的是段落的第一句话,字母的数量决定了使用填充的最小字段宽度。

因此,要查看该结果,请使用 4 个或更多模式字母,并使用比模式字母数量更多的数字年份。它适用于 uyY.

    DateTimeFormatter uuuu = DateTimeFormatter.ofPattern("uuuu");
    DateTimeFormatter yyyy = DateTimeFormatter.ofPattern("yyyy");
    DateTimeFormatter uppercaseYyyy = DateTimeFormatter.ofPattern("YYYY");
    
    LocalDate ld = LocalDate.of(12345, Month.OCTOBER, 23);
    
    System.out.println(ld.format(uuuu));
    System.out.println(ld.format(yyyy));
    System.out.println(ld.format(uppercaseYyyy));

输出:

+12345
+12345
+12345

无论要打印的字符数是多少,都会打印减号。 SignStyle.EXCEEDS_PAD 的文档说:

… A negative value will always output the '-' sign.

文档 link: SignStyle.EXCEEDS_PAD