0

So I have an object ('Task') that has an attribute 'Start Date' which is basically a Timestamp object. So this date is in this format 'YYYY/MM/dd hh:mm:ss:ms'. But for a test case I am authoring, I need this date to be in this format 'YYYY/MM/dd hh:mm'. Also it needs to be a timestamp object as I have to set this value back to the 'Task' object.

I have tried several approaches including the snippet shown below:

SimpleDateFormat formatter = new SimpleDateFormat("YYYY-MM-dd hh:mm");
if (task.getStartDate() != null) {
     String newDate = formatter.format(task.getStartDate());
     Date date = formatter.parse(newDate);
     task.setStartDate(new Timestamp(date.getTime()));
}

I expected the value of the timestamp to be in the format '2018-12-30 09:54' but it resulted in '2018-12-30 09:54:00.0'. So the questions that I have in mind is:

  1. Is there a way to not consider the seconds and millis in the Timestamp object?
  2. If no, then, is the snippet provided an efficient way to update the Timestamp object?
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Dendi_Nim
  • 15
  • 1
  • 1
  • 6
  • 1
    How do you come to the conclusion that the timestamp has a format of '2018-12-30 09:54:00.0'? Timestamps are a wrapper around a milliseconds value (truncated to seconds) + a sub-second nanoseconds fraction. It has no 'format' by itself. Likely you are looking at its default `toString()` rendering. – Mark Rotteveel Sep 12 '19 at 10:36
  • Correct me if I am wrong, but I thought that after specifying DateFormatter it would parse the dates as per the date pattern provided. – Dendi_Nim Sep 12 '19 at 10:47
  • Possible duplicate of [Formatting timestamp in Java](https://stackoverflow.com/questions/23692117/formatting-timestamp-in-java) – Ole V.V. Sep 12 '19 at 10:48
  • The `Timestamp` class is poorly designed and long outdated, and was designed for exchanging timestamps with an SQL database, not for any other purposes. Is there any way you can modify your `Task` object to use an `Instant` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/), instead? It’ll serve you much better. – Ole V.V. Sep 12 '19 at 10:50
  • 1
    Regardless of the answer to my previous question I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated too, the former in particular notoriously troublesome. Instead use `LocalDateTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). Depending on your exact requirements you can convert either an `Instant` or a `LocalDateTime` to a `Timestamp` that you can feed to your `Task` if necessary. – Ole V.V. Sep 12 '19 at 10:52
  • 1
    I think your understanding is wrong. When you print a `Timestamp`thereby implicitly calling its `toString` method, you always get that format, with seconds and at least one decimal on the seconds (more decimals if they are non-zero). It has nothing to do with the format you used for parsing the `Date`. Also a `Date` hasn’t got a format either, and you only passed the millisecond value of the `Date` to your `Timestamp`, so how could a format have been conveyed? – Ole V.V. Sep 12 '19 at 10:57
  • 1
    A date formatter is simply about converting between string and a date. It doesn't have any lasting formatting on the date value. – Mark Rotteveel Sep 12 '19 at 10:58

1 Answers1

0

TL;DR

  1. Avoid the Timestamp class if you can. It’s poorly designed and long outdated.
  2. To answer your questions, no, a Timestamp hasn’t got, as in cannot have a format (the same holds true for its modern replacement, Instant (or LocalDateTime)).
  3. Under all circumstances avoid SimpleDateFormat and Date. The former in particular is notoriously troublesome, and both are long outdated too.

Don’t put a format into your model class

You should not want an Instant nor a Timestamp with a specific format. Good practice in all but the simplest throw-away programs is to keep your user interface apart from your model and your business logic. The value of the Instant object belongs in your model, so keep your Instant or Timestamp there and never let the user see it directly. I hope that it’s clear to you that 2018-12-30 09:54 and 2018-12-30 09:54:00.0 represent the same value, the same Timestamp. Just like 17, 0017 and 0x11 represent the same integer value. When you adhere to what I said, it will never matter which format the Instant has got.

Whenever the user should see the date and time, this happens in the UI, not in the model. Format it into a String and show the string to the user. Similarly if you need a specific format for persistence or exchange with another system, format the Instant into a string for that purpose.

java.time and JDBC 4.2

Also for exchange with your database over JDBC, provided that you’ve got a JDBC 4.2 compliant driver, prefer to use a type from java.time over Timestamp. If the datatype on the database side is timestamp with time zone, very clearly recommended for a timestamp, pass an OffsetDateTime like

   OffsetDateTime dateTime = yourInstant.atOffset(ZoneOffset.UTC);
   yourPreparedStatement.setObject(4, dateTime);

Use setObject, not setTimestamp. Some drivers accept the Instant directly, without conversion to OffsetDateTime. If on the database side you need a mere timestamp (without time zone), use LocalDateTime in Java instead and pass one to setObject in the same way as above.

PS There are errors in your format pattern string

In a format pattern string, uppercase YYYY is for week based year and only useful with a week number. For year use either uuuu or lowercase yyyy. Similarly lowercase hh is for hour within AM or PM from 01 through 12 and only useful with an AM or PM marker. For hour of day from 00 through 23 you need uppercase HH. These errors will give you incorrect dates and times in most cases. Using the wrong case of format pattern letters is a very common mistake. SimpleDateFormat generally doesn’t mind, it just gives incorrect results. The modern DateTimeFormatter does a somewhat better job of notifying you of such errors.

Links

Oracle tutorial: Date Time explaining how to use java.time.

Related questions

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Thanks Mark, Ole for detailed explanation. I have a better understanding on Timestamps now. Looks like I had incorrect expectations. I guessed what caused this confusion is while debugging, it showed the value of the timestamp in '2018-12-30 09:54' pattern. – Dendi_Nim Sep 12 '19 at 12:32