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

问题描述

来自DateTimeFormatter javadoc

如果字母数少于四个(但不小于两个),则符号 根据SignStyle.norMAL仅输出负数年。除此以外, 如果超过焊盘宽度,则输出符号 SignStyle.EXCEEDS_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工作中看到最后一句话

解决方法

要查询的句子中的否则是指字母计数为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的文档说:

…负值将始终输出'-'符号。

文档链接: SignStyle.EXCEEDS_PAD

,

如果字母数少于四个(但不小于两个),则符号 根据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

我在uu中使用了formatter1(字母数为2),因此它没有显示负号。但是,如果字母数少于四个,但不少于两个,则需要提供足够的填充,例如在-1年中,您至少需要填充2(即pp),其中一个用于填充-,另一个用于填充1。如果您提供的填充数较少,则将获得DateTimeException;如果您提供的填充数超过2,则将得到-1之前的空格。

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

,

此模式"ppppuuuu"定义了padWidth,共4个,适用于以下格式uuuu,该格式适用SignStyle.EXCEEDS_PAD(根据javadoc for DateTimeFormatBuilder)。

也就是说,由于当前的-,总是打印SignStyle

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

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

因此,仅在使用uu格式时才打印标志。

为避免出现负数例外,填充应超过位数,例如"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]