Dmitry K
Dmitry K

Reputation: 184

How to test and compare two java.time.format.DateTimeFormatter-s?

How to compare two java.time.format.DateTimeFormatters?

Due to the fact that DateTimeFormatters does not have an overridden 'equals' method.

Test:

import java.time.format.DateTimeFormatter;

DateTimeFormatter.ofPattern("M/dd/yyyy").equals(DateTimeFormatter.ofPattern("M/dd/yyyy"))

Result:

false

This is the behavior of 'Object.equals()' method. Documentation: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

Methods inherited from class java.lang.Object clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

Use case when it needed:

For example my method returns DateTimeFormatter. And I would like to create test to verify that returned DateFormatter is correct.

For example:

DateTimeFormatter expectedFormatter = DateTimeFormatter.ofPattern("my custom format")
DateTimeFormatter actualFormatter = someService.getFormatter()
Assert.assertEquals(actualFormatter, expectedFormatter)

Upvotes: 0

Views: 1070

Answers (2)

JoshDM
JoshDM

Reputation: 5072

There are ways to obtain the original pattern for comparison.

Since DateTimeFormatter is a final class that can't be extended, you could replace all your instances with a wrapper class that creates the instance of DateTimeFormatter in the constructor and access to the generated DateTimeFormatter instance and pass around your custom DataTimeFormatterContainer classes in your code. It's a beast, but it'll do what you are asking.

Of course, this compares exactly the pattern; if two non-identical patterns generate the same result when parsing a date, this will return false.

Barebones proposal; no null checks, accessor methods, or hashcode:

public class DateTimeFormatterContainer() {

    public final String pattern;
    public final DateTimeFormatter formatter;

    public DateTimeFormatterContainer(String pattern) {

        this.pattern = pattern;
        this.formatter = DateTimeFormatter.ofPattern(pattern);
    }

    public boolean equals(DateTimeFormatterContainer that) {

        return this.pattern.equals(that.pattern);
    }
}

Upvotes: 0

Michael
Michael

Reputation: 44150

Probably because determining equality of a formatter is non-trivial, since there are many ways to construct the "same" formatter (in terms of behaviour) via a builder, and is rarely useful.

The JDK developers have finite time. They prioritise the import things. DateTimeFormatter overriding equals in a consistent and idiomatic way is much harder than it might seem, they're better off spending time elsewhere.

In any case, it doesn't help you to know why it doesn't exist. That is the situation you are in, and that is not changing any time soon.

My suggestion is to test the behaviour. Construct some date (or date-time) and see whether both formatters produce the same output.

DateTimeFormatter expectedFormatter = DateTimeFormatter.ofPattern("my custom format")
DateTimeFormatter actualFormatter = someService.getFormatter();

LocalDate someFakeDate = LocalDate.of(2020, 1, 1);
Assert.assertEquals(actualFormatter.format(someFakeDate), expectedFormatter.format(someFakeDate));

Upvotes: 4

Related Questions