Error: "java.text.Parseexception: Unparseable date: "2018-11-14T12:12"

Asked

Viewed 2,340 times

2

I have the following data insertion interface:inserir a descrição da imagem aqui

The comments below represent attempts to fix the error but none worked.

In HTML the type is datetime-local, in the bank the type was created as datetime and in the class ControladoraJPA created by java directly connected with the table in the database, the attribute came only as Date.

I have the following java method:

public void cadastrarPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException{
    try{
        String conteudo = request.getParameter("content_post");
        String data_cria = request.getParameter("data_criacao");
        String data_public = request.getParameter("data_publicacao");
        String categoria = request.getParameter("categoria");

        //data_cria = data_cria.replace('T', ' ').concat(":00");;
        //data_public = data_cria.replace('T', ' ').concat(":00");

        //DateTimeFormatter formato = DateTimeFormatter.forPattern("dd/MM/yyyy HH:mm:ss");
        //Date date = (Date) formato.parse(data_cria);
        //Date date2 = (Date) formato.parse(data_public);
        //java.sql.Timestamp data1 = java.sql.Timestamp.valueOf(data_cria);
        //java.sql.Timestamp data2 = java.sql.Timestamp.valueOf(data_public);

        //DateFormat formatter = new SimpleDateFormat("MM/dd/yy");
        //Date date = (Date)formatter.parse(data_cria);
        //Date date2 = (Date)formatter.parse(data_public);

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("PROJETO_POSTPU");
        UserJpaController userJpa = new UserJpaController(emf);
        PostJpaController postJpa = new PostJpaController(emf);
        CategoryJpaController categoryJpa = new CategoryJpaController(emf);

        List<Category> listCat = new ArrayList();
        listCat = categoryJpa.findCategoryEntities();
        List<User> listUser = new ArrayList();
        listUser = userJpa.findUserEntities();

        Post post = new Post();
        post.setContent(conteudo);
        post.setCreatedAt(date);
        post.setPublishedAt(date2);
        for(Category c : listCat){
            if(c.getDescription().equals(categoria)){
                post.setIdCategory(c);
                break;
            } else {
                continue;
            }
        }
        for(User u : listUser){
            if(u.getUsername() == userSec){
                post.setIdAuthor(u);
            }
        }
        postJpa.create(post);

        //request.setAttribute("resp", result);
        request.getRequestDispatcher("/feed/feed.jsp").forward(request, response);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • Wouldn’t it be something like DateTimeFormatter.forPattern("yyyy-MM-dd\THH:mm")?

  • @Andersoncarloswoss It actually is yyyy-MM-dd'T'HH:mm (or uuuu-MM-dd'T'HH:mm). Although, for the ISO 8601 format, you don’t even need a DateTimeFormatter (if you’re going to use java.time, of course, because for Date and SimpleDateFormat need), see my answer down below

2 answers

2

First you should format your date, something like:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

This error occurs when the date type you are trying to pass is not as expected

2


DateTimeFormatter is part of the API java.time, which was introduced in Java 8 and is incompatible with the old API (although it is possible to convert between Apis, more about this below). If you look at documentation of the method parse, you will see that he returns a TemporalAccessor. This type is incompatible with Date, therefore the cast doesn’t work.

Already his attempt with SimpleDateFormat does not work because the format used ("MM/dd/yy") does not correspond to String you want to turn into date ("2018-11-14T12:12").

To settle with SimpleDateFormat, simply enter the correct format:

String data = "2018-11-14T12:12";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
// java.util.Date
Date date = sdf.parse(data);
Timestamp ts = new Timestamp(date.getTime());

To learn more about the format, see documentation. No need to change the words T by space, just put it between single quotes ('T') in the builder of SimpleDateFormat, that he will understand that it must be interpreted literally as the letter "T itself".

Also no need to add :00 at the end of your string, to represent the seconds, because if they are omitted, their value is automatically set to zero.

Remembering that the method parse returns a java.util.Date. If you are using java.sql.Date, there is a little more complicated. A documentation says that the timestamp value must be "normalized", setting the time fields to zero. For this we can use the class Calendar:

String data = "2018-11-14T12:12";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
java.util.Date date = sdf.parse(data);

// setar os campos de horário para zero
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
// criar o java.sql.Date
java.sql.Date sqlDate = new java.sql.Date(cal.getTimeInMillis());

As the input string does not have the seconds and milliseconds, they will already be set to zero. So I only needed to set the hours and minutes.


But if you have Java 8 available, you can use the new API as well.

A string 2018-11-14T12:12 is in format ISO 8601, so you don’t even need a DateTimeFormatter to do Parsing. The difference is that in java.time there is various different types of date and you must choose the appropriate class to handle your data.

In this case, the string contains date and time, so the most indicated type is LocalDateTime:

String data = "2018-11-14T12:12";
LocalDateTime dateTime = LocalDateTime.parse(data);

But how to convert to Date? First we need to understand what each class represents.

java.util.Date represents a point in the timeline, a timestamp. A value that corresponds to the amount of milliseconds that have passed since the Unix Epoch - whereas the Unix Epoch is 1970-01-01T00:00Z (January 1, 1970, midnight, in UTC).

That means that the Date represents a different date and time depending on where you are. At this very moment, if I rotate new Date().getTime(), I will have the value of the timestamp equal to 1542192713069. Any computer, anywhere in the world, that ran this at the same instant as me, would have the same value.

Only this same timestamp value corresponds to a different date and time in each place of the world:

  • In São Paulo: November 14, 2018 at 8:51:53.069
  • Tokyo: November 14, 2018 at 19:51:53.069
  • In Samoa: 13 November 2018 at 23:51:53.069

That is, the Date represents only the timestamp 1542192713069, but for translate this value to a date and time, we need to know the Timezone (time zone).

Already java.time.LocalDateTime represents a date and time, but without any notion of Timezone. Therefore, convert a LocalDateTime for Date may result in a different timestamp depending on the chosen Timezone.

SimpleDateFormat uses the Timezone default JVM (unless you configure another, using setTimeZone()), then you can simulate this behavior using ZoneId.systemDefault(). Then just convert to Date or Timestamp, depending on what you need:

String data = "2018-11-14T12:12";
LocalDateTime dateTime = LocalDateTime.parse(data);
// converter para timezone default e em seguida para java.util.Date
java.util.Date date = Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());

// ou converta diretamente para Timestamp
Timestamp ts = Timestamp.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());

In the case of Timestamp, you can also pass the LocalDateTime directly. In this case, the Timezone default JVM will be used internally:

// passar o LocalDateTime diretamente
Timestamp ts = Timestamp.valueOf(dateTime);

And if you need to create a java.sql.Date:

java.sql.Date sqlDate = java.sql.Date.valueOf(dateTime.toLocalDate());

If the bank you are using has a driver compatible with the JDBC 4.2 and it is possible to change the date fields, it is possible to work directly with the java.time, using the methods setObject class java.sql.PreparedStatement and getObject class java.sql.ResultSet:

LocalDateTime dateTime = ...

PreparedStatement ps = ...
// seta o java.time.LocalDateTime
ps.setObject(1, dateTime);

// obter o LocalDateTime do banco
ResultSet rs = ...
LocalDateTime instant = rs.getObject(1, LocalDateTime.class);

Browser other questions tagged

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