I am writing a method that will take a java.time.LocalDate
and produce a Julian date variant. The Julian date variant format is as follows:
CYYDDD
Where C
is the century, YY
is the 2 digit year and DDD
is the 3 digit day-of-year. Today (December 8, 2021) translates into 121342.
I'm using a java.util.Formatter
to format the values from the LocalDate
as follows:
private int calculateJDEDate(LocalDate date) {
StringBuilder sb = new StringBuilder();
Formatter fmt = new Formatter(sb);
// Format 2 digit year.
fmt.format("%.2d", date.getYear()).close();
// fmt.format("1%1$.2d%2$.3d", date.getYear(), date.getDayOfYear()).close();
return Integer.parseInt(sb.toString());
}
The getYear()
and getDayOfYear()
methods both return an int value.
When I attempt to run this, I get the following exception:
Exception in thread "main" java.util.IllegalFormatPrecisionException: 2
at java.base/java.util.Formatter$FormatSpecifier.checkInteger(Formatter.java:3138)
at java.base/java.util.Formatter$FormatSpecifier.<init>(Formatter.java:2874)
at java.base/java.util.Formatter.parse(Formatter.java:2713)
at java.base/java.util.Formatter.format(Formatter.java:2655)
at java.base/java.util.Formatter.format(Formatter.java:2609)
at com.fossfloors.f55hubdt.Main.calculateJDEDate(Main.java:104)
at com.fossfloors.f55hubdt.Main.calculateDateData(Main.java:96)
at com.fossfloors.f55hubdt.Main.lambda$0(Main.java:129)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.LongPipeline$1$1.accept(LongPipeline.java:177)
at java.base/java.util.stream.Streams$RangeLongSpliterator.forEachRemaining(Streams.java:228)
at java.base/java.util.Spliterator$OfLong.forEachRemaining(Spliterator.java:763)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEachOrdered(ReferencePipeline.java:502)
at com.fossfloors.f55hubdt.Main.main(Main.java:128)
I don't understand what is wrong. Every example I've found indicates this format is valid.
This is sort of a secondary question, but does the formatter allow for leading characters (like leading zeros)? I can't seem to find information on doing that.
CodePudding user response:
The problem is that %.2d
doesn't make sense, as that specifies the precision of fractional numbers (number of decimals after the point), while integers by definition do not have fractional values. You're probably thinking of d
and d
, but that only specifies the minimum width.
Instead, use java.time.DateTimeFormatter
:
var date = LocalDate.of(2021, 12, 8);
var formatter = DateTimeFormatter.ofPattern("yyDDD");
System.out.println("1" formatter.format(date));
If the century is fixed (always 1), then you can also use pattern "'1'yyDDD"
and do away with the concatenation.