Format Localdate and pass as Parameter

Asked

Viewed 3,235 times

1

I have a Method:

private void tratarIFMandato(String [] d){

         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
         LocalDate dt1 = LocalDate.parse(d[0].trim(), formatter);

         System.out.println(dt1);
 /*
         this.setInicioMandato(dt1);
 */

     }

Receiving a date in the format "dd/MM/yyyy" and it’s returning to me: 1990-03-15

I need to pass the String for a LocalDate for I have a method set who will receive a LocalDate as a parameter and a get that will return me a LocalDate.

The solution I found was to make my method get return a DateTimeFormatter and give a return formatter.format(dt1); inside my get, but accurate that a LocalDate in format dd/MM/yyyy.

How do I return the date in format dd/MM/yyyy?

2 answers

4


If you "return date in format dd/MM/yyyy", it ceases to be a date (a LocalDate) and becomes a String. To better understand, below is a - long - explanation.

Dates have no format

A date is just a concept, an idea: it represents a specific point in the calendar.

The date of "March 15, 1990" represents this: the specific point of the calendar, which occurred several years ago, which we agree to call the 15th of March of the year 1990. To express this idea in text form, I can write it in different ways:

  • 15/03/1990 (a common format in many countries, including Brazil)
  • 3/15/1990 (American format, reversing day and month)
  • 1990-03-15 (the format ISO 8601)
  • 15 March 1990 (in good Portuguese)
  • March 15th, 1990 (in English)
  • 1990 年 3 月 15 日 (in Japanese)
  • and many others...

Note that each of the above formats is different, but all represent the same date (the same numerical values of the day, month and year).


Similarly, in Java we have the class LocalDate, implementing the concept of a specific date (a specific day, month and year), and we have the String, which may contain a text representing a date (any of the above formats, and any other you want).

A LocalDate, by itself, it has no specific format. Internally, this class has only 3 numerical values: the day, month and year.

When you print one LocalDate (be it with System.out.println, with a log API, or even seeing its value in a Debugger), internally is called the method toString(), which returns the day, month and year values formatted in a String. In the case of the API java.time, chose to return this String in the ISO 8601 format (so the date is shown as 1990-03-15).

That is, in doing System.out.println(dt1), you see the return of the method toString(), which returns the date values in a specific format (in a String). But that doesn’t mean that the LocalDate is in that format. In fact, it is not in any format, because it even has a.

Just to illustrate:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");
LocalDate dt1 = LocalDate.parse("15/03/1990", formatter);
System.out.println(dt1); // 1990-03-15

LocalDate dt2 = LocalDate.of(1990, 3, 15);
System.out.println(dt2); // 1990-03-15

System.out.println(dt1.equals(dt2)); // true

The first date (dt1) was created from a String. Like this String represents a date in the "day/month/year" format, I used the DateTimeFormatter with this format and made the parse to obtain the LocalDate. So now dt1 corresponds to "March 15, 1990".

But internally dt1 does not have any format. It has only numeric values (day 15, month 3 and year 1990). dt1 does not know that these values came from a String (who made this match between what was in the String and the numerical values was the DateTimeFormatter).

Of course, when printing dt1, it has to be shown somehow, and your method toString() ends up showing in the ISO 8601 format. But that doesn’t mean dt1 is in that format.

Already dt2 was created using the numerical values directly. It also has only the values, and has no information as to the format. So much so that dt1 and dt2 are equal (correspond to the same date - same point in the calendar - their numerical values of the day, month and year are equal): see in the last line that dt1.equals(dt2) prints true.


Therefore, you must decide what you need at each point of the code.

If the method setInicioMandato gets a LocalDate as a parameter, just pass it directly, without worrying about the format (even because the LocalDate has no format, only the numerical values of the day, month and year).

If you want to show the date in some different format, then it is the case to convert it to String, using a DateTimeFormatter.


Bonus

Just to complement, see what happens if the String has dates such as 31 April or 29 February in non-leap years:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");
LocalDate dt1 = LocalDate.parse("31/04/2019", formatter);
System.out.println(dt1); // 2019-04-30
LocalDate dt2 = LocalDate.parse("29/02/2019", formatter);
System.out.println(dt2); // 2019-02-28

April 31 is invalid as April only has 30 days. But 31/04/2019 was accepted and adjusted for April 30. Already 29/02/2019 (which is also invalid as 2019 is not leap year) was adjusted to 28 February.

If you want to avoid these situations and accept only valid dates, just change the java.time.format.ResolverStyle, using the value STRICT (as suggested in this answer). With this, invalid dates throw an exception:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/uuuu")
    .withResolverStyle(ResolverStyle.STRICT);
LocalDate dt1 = LocalDate.parse("31/04/2019", formatter);

The code above tries to do the Parsing of an invalid date, but due to ResolverStyle.STRICT, he throws an exception:

java.time.format.DateTimeParseException: Text '31/04/2019' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2019, MonthOfYear=4, DayOfMonth=31},ISO of type java.time.format.Parsed

Another detail - you may have noticed - is to use uuuu next year instead of yyyy. In a very concise way, u works both for current years and for dates A.C. (Before Christ), accepting negative years, while y needed era (A.C. or B.C.) to decide whether year is Before or After Christ (in the Parsing we do not see these problems because the era is inferred and for current dates works normally).

Perhaps the use of such old dates is not so common in many applications, but anyway, the use of u instead of y is recommended. For more details, see this question in Stack Overflow.

0

Your code is wrong because when using Localdate Parse, by default the return will be in iso format (yyyy-MM-dd).

The mask you use in the parse method is the mask that is in the variable you reported in the method.

First you perform the parse, perform the necessary operations with the date using the methods of the Localdate Class, only then, if it is necessary you use the Datetimeformatter to change the format to what you want....


LocalDate dt1 = LocalDate.parse("suastringaqui", o formato de sua string aqui);

LocalDate dt1 = LocalDate.parse("15/08/2020", DateTimeFormatter.ofPattern("dd/MM/yyyy"));

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");

System.out.println(dt1.format(formatter));

See the result here: https://ideone.com/pWMdrL

Browser other questions tagged

You are not signed in. Login or sign up in order to post.