1

I have a spring boot application with a receipt entity here I have a LocalDateTime date defined like this:

@Nullable
@Column(name = "date_time")
private LocalDateTime dateTime;

Before saving my entity I am trying to convert the current system date to this format:

dd.MM.yyyy HH:mm:ss

But I am getting a DateTimeParseExcetion with this text:

java.time.format.DateTimeParseException: Text '26.12.2022 13:25:30' could not be parsed at index 0

This is how my code looks:

 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss", Locale.ROOT);
    LocalDateTime now = LocalDateTime.now();
    log.debug("REST request to save Receipt : {}", receiptDTO);
    if (receiptDTO.getId() != null) {
        throw new BadRequestAlertException("A new receipt cannot already have an ID", ENTITY_NAME, "idexists");
    }
    Optional<User> currentUser = userService.getUserWithAuthoritiesByLogin(SecurityContextHolder.getContext().getAuthentication().getName());
    receiptDTO.setDateTime(LocalDateTime.parse(dtf.format(now)));
    currentUser.ifPresent(user -> receiptDTO.setUser(this.UserMapper.userToUserDTO(user)));
    ReceiptDTO result = receiptService.save(receiptDTO);

UPDATE :

DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss", Locale.ROOT);
        LocalDateTime now = LocalDateTime.now();
        String formattedCurrentTime = dateFormat.format(now);
        LocalDateTime localdatetime = LocalDateTime.parse(formattedCurrentTime, dateFormat);
        log.debug("REST request to save Receipt : {}", receiptDTO);
        if (receiptDTO.getId() != null) {
            throw new BadRequestAlertException("A new receipt cannot already have an ID", ENTITY_NAME, "idexists");
        }
        Optional<User> currentUser = userService.getUserWithAuthoritiesByLogin(SecurityContextHolder.getContext().getAuthentication().getName());
        receiptDTO.setDateTime(localdatetime);

UPDATE 2:

COMPLETE METHOD:

   @PostMapping("/receipts")
    public ResponseEntity<ReceiptDTO> createReceipt(@RequestBody ReceiptDTO receiptDTO) throws URISyntaxException {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss", Locale.ENGLISH);
        LocalDateTime now = LocalDateTime.now();
        String formattedCurrentTime = now.format(formatter);
        log.debug("REST request to save Receipt : {}", receiptDTO);
        if (receiptDTO.getId() != null) {
            throw new BadRequestAlertException("A new receipt cannot already have an ID", ENTITY_NAME, "idexists");
        }
        receiptDTO.setDateTime(now);
        Optional<User> currentUser = userService.getUserWithAuthoritiesByLogin(SecurityContextHolder.getContext().getAuthentication().getName());
        currentUser.ifPresent(user -> receiptDTO.setUser(this.UserMapper.userToUserDTO(user)));
        ReceiptDTO result = receiptService.save(receiptDTO);
        return ResponseEntity
            .created(new URI("/api/receipts/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, result.getId().toString()))
            .body(result);
    }
natyus
  • 577
  • 1
  • 4
  • 19
  • The error is occurring because `LocalDateTime.parse(CharSequence text)` doesn't accept this date format. You have to do `LocalDateTime.parse(dtf.format(now), dtf)` which which makes no sense to me. Your goal is simply to save the date to the database? Which database are you using? – Matheus Dec 26 '22 at 12:49
  • A `LocalDateTime` can not be stored in a specific format. It is supposed to hold the information about the date and time units, and not the format. You can get a custom textual representation by formatting it in your custom pattern. If you like you can store this string (which does not make sense) but you can never store a `LocalDateTime` in a specific format. – Arvind Kumar Avinash Dec 26 '22 at 13:35

3 Answers3

2

You seem to be confused between the LocalDateTime instance and its textual representation. A LocalDateTime (or any date-time type) is supposed to hold the information about the date-time units (e.g. year, month, day, hour, minute etc.) - how you print it in textual form depends on how you format it. The default textual representation is as returned by LocalDateTime#toString e.g.

class Main {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now); // This prints the value of now.toString()

        // An example of textual representation in a custom format
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss", Locale.GERMAN);
        String formatted = now.format(formatter);
        System.out.println(formatted);
    }
}

Output:

2022-12-26T13:20:24.257472
26.12.2022 13:20:24

A LocalDateTime does not hold any format. As shown above, you can get a custom textual representation by formatting it in your custom pattern. If you like, you can store this string (which does not make sense) in a database column of text type, or set it into a String variable, but you can never store or set a LocalDateTime in a specific format.

The following line in your code does not make sense, and has also caused the error:

receiptDTO.setDateTime(LocalDateTime.parse(dtf.format(now)));

You should have written it simply as

receiptDTO.setDateTime(now);

The reason for the error is that LocalDateTime#parse(CharSequence text) has been implemented to parse a date-time string which is already in ISO 8601 format (e.g. 2022-12-26T13:25) whereas the dtf.format(now) in your code returns a string which is not in ISO 8601 format.

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

You don't really need to write your own code to format your LocalDateTime. You can declare it with the following annotation:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy HH:mm:ss")
@Nullable
@Column(name = "date_time")
private LocalDateTime dateTime;

For more details look here: Spring Data JPA - ZonedDateTime format for json serialization (Look at the accepted answer)

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36
0

From LocalDateTime's javadoc:

A date-time without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30.

From LocalDateTime's toString()

Outputs this date-time as a String, such as 2007-12-03T10:15:30. The output will be one of the following ISO-8601 formats: (...)

The LocalDateTime will always output date times in the ISO-8601 format.

It's not clear what you're trying to do, but, as far as I can see, your goal is simply to save the data in the database. If that's the case, just save the date the way it is and then format at retrieval for presentation. Is this a limitation of your database (does the database only accept dates in the dd.MM.yyyy HH:mm:ss format)? If that's not the case, then there's no sense in formating the date before persisting. Date formats are mainly used for presentation and application input purposes.

Matheus
  • 3,058
  • 7
  • 16
  • 37
  • I want to actually use this format just to display but thought if I save them this way I would not have to format them on each get but directly save them correctly – natyus Dec 26 '22 at 14:46
  • @natyus You cannot. A LocalDateTime is not stored in a format you define. Instead, usually the RDBMS retrieves date-time in a specific format (e.g.: [MySQL uses the `YYYY-MM-DD hh:mm:ss`](https://dev.mysql.com/doc/refman/8.0/en/datetime.html)). If you want to store in a specific format, then your column must be of type varchar and then you're able to store them as strings. But, by doing so, you lose the date-time features of the RDBMS (comparing using BETWEEN, adding days, months etc) -- not a good idea imho. Just store the way it's supposed to be and format on retrieval and you'll be fine. – Matheus Dec 26 '22 at 17:13
  • Thanks I did just like you guys told me I format it in the frontend with angular pipes thanks to everyone – natyus Dec 27 '22 at 15:25