Как напечатать знак года в DateTimeFormatter, когда количество букв четыре?
Из
DateTimeFormatter
javadoc:
Если количество букв меньше четырех (но не двух), то знак выводится только для отрицательных лет согласно SignStyle.NORMAL. В противном случае знак выводится, если ширина контактной площадки превышена, согласно SignStyle.EXCEEDS_PAD.
Насколько я понимаю, если ширина панели не превышена и количество букв равно четырем, знак минус (для отрицательных лет) не должен печататься во время форматирования.
Поэтому я написал такой фрагмент кода (полагая, что не могу использовать '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.
3 ответа
В противном случае в предложении вы спрашиваете о относится к ситуации, когда подсчет букв 4 или больше. Как ни странно, ширина пэда здесь не имеет ничего общего с буквой узора.
p
для набивки. Это относится к количеству печатаемых цифр. Это относится к первому предложению абзаца . Количество букв определяет минимальную ширину поля, ниже которой используется заполнение.
Итак, чтобы убедиться в этом, используйте 4 или более шаблонных букв и используйте год, который состоит из большего количества цифр, чем количество шаблонных букв. Работает как с
u
,
y
и
Y
.
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
Этот образец
"ppppuuuu"
определяет
padWidth
из 4 применено к следующему формату
uuuu
, который применяется
SignStyle.EXCEEDS_PAD
(согласно javadoc для
DateTimeFormatBuilder
).
Это
-
всегда печатается из-за текущего
SignStyle
.
Таким образом, когда форматтер пытается напечатать год с отрицательным знаком, он использует 4 цифры и знак, таким образом превышая доступный
padWidth
.
Точно так же знак всегда печатается при использовании
u
или же
uuu
шаблоны, потому что
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]
Если количество букв меньше четырех (но не двух), то знак выводится только для отрицательных лет согласно 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
и поэтому не имеет отрицательного знака. Однако, если количество букв меньше четырех, а не двух, вам необходимо предоставить достаточное количество отступов, например, для года,
-1
, вам нужно заполнить как минимум
2
(т.е.
pp
), один для
-
знак и один для
1
. Если вы предоставите меньшее количество отступов, вы получите
DateTimeException
и если вы предоставите больше, чем
2
обивка, вы получите место перед
-1
.
Таким образом, в случае формата
uuuu
, вам нужен отступ не менее
5
(т.е.
ppppp
) за отрицательный год, один за
-
и
4
годами (0001
) т.е. вам нужно использовать
DateTimeFormatter.ofPattern("pppppuuuu")
избежать
DateTimeException
.