Convert dd-mm-yy date to yyyy-mm-dd in Java

Asked

Viewed 1,061 times

-6

I am receiving via form:

28-set-2018

and I need to save in the bank

2019-09-29 00:00:00

2 answers

3


Depends: the field in the database is as string (varchar)?

Because dates are usually saved in databases in a field with the specific type (date, datetime, timestamp, etc). If this is the case, there should be no concern about the format saved.

Your concern, in this case, would be to just convert the string 28-set-2018 for a date and save it directly to the bank.

If you are using Java >= 8, you can use the API java.time:

Locale locale = new Locale("pt", "BR");
DateTimeFormatter parser = DateTimeFormatter.ofPattern("dd-MMM-uuuu", locale);
LocalDate date = LocalDate.parse("28-set-2018", parser);

The java.util.Locale is important because the month is in Portuguese, and if you do not inform it, the locale will be used default from JVM (which may be another language), so it is best to use the correct locale.

The problem is that only from JDBC 4.2 it is possible to save the classes of the java.time directly at the bank, using setObject:

preparedStatement.setObject(1, date);

Check that the driver of the database you are using is already compatible with JDBC 4.2. And if so, check the respective field type, as in java.time there are several different classes to represent dates and times (example in Postresql - see if and how your bank is mapping these types).

In your case, as you are wanting to save time too, so you need a LocalDateTime with the set time for midnight (the two forms below are equivalent):

// use atStartOfDay (seta horário para meia-noite)
LocalDateTime datetime = date.atStartOfDay();

// Ou passe o valor do horário explicitamente
LocalDateTime datetime = date.atTime(0, 0);

In this case, pass the LocalDateTime for setObject. If you need other types (like ZonedDateTime, which also considers the time zone), see this question which has more details on the java.time and its types. See also the oracle tutorial.

I say this because dates have no format. They only have values (day, month, year, etc). When a date type, datetime, timestamp, etc., is saved in the database, these values are saved. The formats only serve to visualize the values in an intelligible way: the strings 28-set-2018 and 2018-09-28 are only different representations (formats) for the same value (same date).


But if you need one String in that specific format (and not a date, datetime, etc.), just create another DateTimeFormatter:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
String dataFormatada = datetime.format(fmt); // 2018-09-28 00:00:00

Attention to difference between H and h: uppercase represents the hours of the day (values from 0 to 23) and lowercase represents the "AM/PM time" (values from 1 to 12) - see difference here. I mean, midnight will be printed as 00:00:00 use HH:mm:ss, and how 12:00:00 use hh:mm:ss (since midnight can also be written as 12 AM).


If your driver is not compatible with JDBC 4.2, there is no way, you should record a java.sql.Date. In this case, just convert the LocalDate that we obtained above:

import java.sql.Date;

// valueOf fica em java.sql.Date, não confundir com java.util.Date
Date sqlDate = Date.valueOf(date);

But in your case, as you need the time, then convert the LocalDateTime for a java.sql.Timestamp:

Timestamp timestamp = Timestamp.valueOf(datetime);

Then you can save these objects directly in the database, using the specific methods (setDate, setTimestamp, etc.).

Remember that these classes take the date/time in the default JVM Timezone and convert to a timestamp (which is the value stored internally by these classes).


Java <= 7

For Java <= 7, you can use Threeten Backport, which has virtually the same functionalities as the java.time. The difference is that they are in the package org.threeten.bp, but the names and methods are the same.

Another difference is how to convert to java.sql.Date and java.sql.Timestamp. Like the methods valueOf(LocalDate) and valueOf(LocalDateTime) only added in Java 8, backport created the class org.threeten.bp.DateTimeUtils to make the conversions (see in the documentation).


I don’t have Java 8 and I don’t want to use another API

In this case, the way is to use one java.text.SimpleDateFormat to generate a java.util.Date, and then use java.util.Calendar to set the time for midnight:

Locale locale = new Locale("pt", "BR");
SimpleDateFormat sdfInput = new SimpleDateFormat("dd-MMM-yyyy", locale);
// converter String para java.util.Date
Date data = sdfInput.parse("28-set-2018");

// setar horário para meia-noite
Calendar cal = Calendar.getInstance();
cal.setTime(data);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

// obter o novo valor do java.util.Date (com horário igual a meia-noite)
data = cal.getTime();

// criar java.sql.Date ou java.sql.Timestamp
java.sql.Date d = new java.sql.Date(cal.getTimeInMillis());
Timestamp ts = new Timestamp(cal.getTimeInMillis());

Again: if the field in the database is a date (the type is date, datetime, timestamp, etc), save the java.util.Date/java.sql.Date/java.sql.Timestamp directly. But if you need a string in another format, just create another SimpleDateFormat:

SimpleDateFormat sdfOutput = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dataFormatada = sdfOutput.format(cal.getTime()); // 2018-09-28 00:00:00

Note: in this specific case, setting the date to midnight would not be necessary, because SimpleDateFormat already does this when the time fields are not present. Anyway, I leave the code as reference if you need to change to other values.


Note regarding the name of the month

A lot of location information were changed in JDK 8 and in JDK 9, as discussed here.

And for JDK 11, more changes were also made regarding the location. That is, it may be that, depending on the locale, the Strings resulting are different - details can be found in the Openjdk Bug System.

This means that depending on the Java version, can be that he can’t interpret the month in lower case (set). In this case, just create a DateTimeFormatter case insensitive:

Locale locale = new Locale("pt", "BR");
DateTimeFormatter parser = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .appendPattern("dd-MMM-uuuu")
    .toFormatter(locale);

And there is still another alternative, if the time should always be midnight. You can use the method parseDefaulting to set default values for the time, if this is not present in String entry. Just pass a java.time.temporal.ChronoField corresponding to the field and its value:

DateTimeFormatter parser = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .appendPattern("dd-MMM-uuuu")
    // setar hora e minuto para zero
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .toFormatter(new Locale("pt", "BR"));
LocalDateTime datetime = LocalDateTime.parse("28-set-2018", parser);

When setting time and minute to zero, seconds and fractions of a second will also be set automatically to zero (if the time is not in the input).

With this, you can do Parsing directly to LocalDateTime. As the String only has day, month and year, the time will be automatically set to midnight and from there you use the date as you need.

0

Something like this should work, just be aware of the month of your date.. it must be abbreviated in English (jan, Feb, mar, Apr, may, jun, jul, Aug, Sep, Oct, nov, Dec)

DateTimeFormatter formatterInput = DateTimeFormatter.ofPattern("dd-MMM-yyyy");
DateTimeFormatter formatterOutput = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");

//entrada
String date = "28-set-2018";

//criando objeto data a partir da sua string
LocalDateTime localDate = LocalDateTime.parse(date, formatter);

//saída 2019-09-29 00:00:00
localDate.format(formatterOutput);

If you want to use the months in Portuguese, use:

Locale locale = new Locale("pt", "BR");
DateTimeFormatter formatterInput = DateTimeFormatter.ofPattern("dd-MMM-yyyy", locale);
  • I get Cell dates and convert to String

  • String date = Row.getCell(5);

  • If the entrance is only day, month and year, make one parse directly to a LocalDateTime make a mistake. Another detail is that hh prints midnight as 12 - to have 00, use HH- see here. And "must be abbreviated in English" is only valid if the locale default of the JVM for English. In my case the default is pt_BR and works without having to set the locale (although it is recommended to set a specific one to not depend on the configuration default jvm)

Browser other questions tagged

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