Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I format an integer with a specific set of digits?

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

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 %02d and %03d, 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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading