97

I have an issue while I try to convert a String to a TimeStamp. I have an array that has the date in the format of yyyy-MM-dd and I want to change it to the format of yyyy-MM-dd HH:mm:ss.SSS. So, I use this code:

final String OLD_FORMAT = "yyyy-MM-dd";
final String NEW_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
String oldDateString = createdArray[k];
String newDateString;
                
final DateFormat formatter = new SimpleDateFormat(OLD_FORMAT);
final Date d = formatter.parse(oldDateString);
((SimpleDateFormat) formatter).applyPattern(NEW_FORMAT);
newDateString = formatter.format(d);
System.out.println(newDateString);
                
final Timestamp ts = Timestamp.valueOf(newDateString);
System.out.println(ts);

and I get the following result.

2009-10-20 00:00:00.000

2009-10-20 00:00:00.0

but when I try to simply do

final String text = "2011-10-02 18:48:05.123";
ts = Timestamp.valueOf(text);
System.out.println(ts);

I get the right result:

2011-10-02 18:48:05.123

Do you know what I might be doing wrong?

Thanks for the help.

Sae1962
  • 1,122
  • 15
  • 31
Dimitra Micha
  • 2,089
  • 8
  • 27
  • 31
  • Nothing is wrong. What do you expect in first case? You are creating timestamp from 2009-10-20 date so time part of timestamp is not set. In second case you are creating timestamp from string where time is set. – Piro Sep 20 '13 at 11:23
  • Just use two instances of (Simple)DateFormat, no need to fiddle with `applyPattern()`. – Gyro Gearless Sep 20 '13 at 12:12
  • @GyroGearless I am not sure what do u mean? How is it possible not to ApplyPattern? – Dimitra Micha Sep 20 '13 at 13:27
  • @Piro The wrong issue is that I have 2009-10-20 00:00:00.0 instead of 2009-10-20 00:00:00.000 – Dimitra Micha Sep 20 '13 at 13:27
  • Why do you need three places/zeros? Timestamp uses it's own format and that format is correct and cannot be changed. If you need to print formatted timestamp convert it from Timestamp back to Date and format it. Current answers seems to totally miss what you needed since your question is not obvious – Piro Sep 20 '13 at 13:49
  • @Piro because when I try to use it in mssql `.statement.setTimestamp(19,timestamp);` it gives this error: "During the conversion of a nvarchar data type to a datetime data type of the value is out of range." – Dimitra Micha Sep 20 '13 at 14:02
  • What is data type in MS SQL? If it is TIMESTAMP you are using it wrong. Use DateTime instead! See http://stackoverflow.com/questions/7105093/difference-between-datetime-and-timestamp-in-sqlserver and http://technet.microsoft.com/en-us/library/aa260631%28v=sql.80%29.aspx for more info – Piro Sep 20 '13 at 14:19
  • The data type is datetime and I have read that I should use the timestamp. Isn't it right? – Dimitra Micha Sep 23 '13 at 14:08

11 Answers11

137

Follow these steps for a correct result:

try {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
    Date parsedDate = dateFormat.parse(yourString);
    Timestamp timestamp = new java.sql.Timestamp(parsedDate.getTime());
} catch(Exception e) { //this generic but you can control another types of exception
    // look the origin of excption 
}

Please note that .parse(String) might throw a ParseException.

Andre Kampling
  • 5,476
  • 2
  • 20
  • 47
ZaoTaoBao
  • 2,567
  • 2
  • 20
  • 28
  • I tried what u suggested but it throws an Exception. Could I fix that? – Dimitra Micha Sep 20 '13 at 13:06
  • 4
    This date pattern is dangerous: `hh` will interpret the hour "in am/pm (1-12)". You should use `HH` to get "Hour in day (0-23)" as in the question. – Scolytus Jan 07 '20 at 15:04
27
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Util {
  public static Timestamp convertStringToTimestamp(String strDate) {
    try {
      DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
       // you can change format of date
      Date date = formatter.parse(strDate);
      Timestamp timeStampDate = new Timestamp(date.getTime());

      return timeStampDate;
    } catch (ParseException e) {
      System.out.println("Exception :" + e);
      return null;
    }
  }
}
Tim B
  • 1,983
  • 1
  • 20
  • 21
Harsh
  • 2,893
  • 29
  • 16
  • 3
    I prefer this answer, as it shows the classes used in the code. I kept getting error because I imported **java.sql.Date** instead of **java.util.Date**. – tartaruga_casco_mole May 18 '16 at 06:08
19

I should like to contribute the modern answer. When this question was asked in 2013, using the Timestamp class was right, for example for storing a date-time into your database. Today the class is long outdated. The modern Java date and time API came out with Java 8 in the spring of 2014, three and a half years ago. I recommend you use this instead.

Depending on your situation an exact requirements, there are two natural replacements for Timestamp:

  • Instant is a point on the time-line. For most purposes I would consider it safest to use this. An Instant is independent of time zone and will usually work well even in situations where your client device and your database server run different time zones.
  • LocalDateTime is a date and time of day without time zone, like 2011-10-02 18:48:05.123 (to quote the question).

A modern JDBC driver (JDBC 4.2 or higher) and other modern tools for database access will be happy to store either an Instant or a LocalDateTime into your database column of datatype timestamp. Both classes and the other date-time classes I am using in this answer belong to the modern API known as java.time or JSR-310.

It’s easiest to convert your string to LocalDateTime, so let’s take that first:

    DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS");
    String text = "2011-10-02 18:48:05.123";
    LocalDateTime dateTime = LocalDateTime.parse(text, formatter);
    System.out.println(dateTime);

This prints

2011-10-02T18:48:05.123

If your string was in yyyy-MM-dd format, instead do:

    String text = "2009-10-20";
    LocalDateTime dateTime = LocalDate.parse(text).atStartOfDay();
    System.out.println(dateTime);

This prints

2009-10-20T00:00

Or still better, take the output from LocalDate.parse() and store it into a database column of datatype date.

In both cases the procedure for converting from a LocalDateTime to an Instant is:

    Instant ts = dateTime.atZone(ZoneId.systemDefault()).toInstant();
    System.out.println(ts);

I have specified a conversion using the JVM’s default time zone because this is what the outdated class would have used. This is fragile, though, since the time zone setting may be changed under our feet by other parts of your program or by other programs running in the same JVM. If you can, specify a time zone in the region/city format instead, for example:

    Instant ts = dateTime.atZone(ZoneId.of("Europe/Athens")).toInstant();
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • The answers given were given based on the OP's question. Not what's right or wrong – Ojonugwa Jude Ochalifu Apr 19 '20 at 10:23
  • 3
    You are entirely correct, @OjonugwaJudeOchalifu. Since the question and the answer stays here for the posterity, the question is whether we help future readers the best by letting the answers from 2013 stand alone or by supplementing with an answer that shows the good solution for the future. – Ole V.V. Apr 19 '20 at 10:30
10

The easy way to convert String to java.sql.Timestamp:

Timestamp t = new Timestamp(DateUtil.provideDateFormat().parse("2019-01-14T12:00:00.000Z").getTime());

DateUtil.java:

import java.text.SimpleDateFormat;
import java.util.TimeZone;

public interface DateUtil {

  String ISO_DATE_FORMAT_ZERO_OFFSET = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
  String UTC_TIMEZONE_NAME = "UTC";

  static SimpleDateFormat provideDateFormat() {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(ISO_DATE_FORMAT_ZERO_OFFSET);
    simpleDateFormat.setTimeZone(TimeZone.getTimeZone(UTC_TIMEZONE_NAME));
    return simpleDateFormat;
  }
}
Yuliia Ashomok
  • 8,336
  • 2
  • 60
  • 69
4

Just for the sake of completeness, here is a solution with lambda and method reference:

ISO format?

Description: The following method

  • converts a String with the pattern yyyy-MM-dd into a Timestamp, if a valid input is given,
  • returns a null, if a null value is given,
  • throws a DateTimeParseException, if an invalid input is given

Code:

static Timestamp convertStringToTimestamp(String strDate) {
    return Optional.ofNullable(strDate) // wrap the String into an Optional
                   .map(str -> LocalDate.parse(str).atStartOfDay()) // convert into a LocalDate and fix the hour:minute:sec to 00:00:00
                   .map(Timestamp::valueOf) // convert to Timestamp
                   .orElse(null); // if no value is present, return null
}


Validation: This method can be tested with those unit tests: (with Junit5 and Hamcrest)

@Test
void convertStringToTimestamp_shouldReturnTimestamp_whenValidInput() {
    // given
    String strDate = "2020-01-30";

    // when
    final Timestamp result = convertStringToTimestamp(strDate);

    // then
    final LocalDateTime dateTime = LocalDateTime.ofInstant(result.toInstant(), ZoneId.systemDefault());
    assertThat(dateTime.getYear(), is(2020));
    assertThat(dateTime.getMonthValue(), is(1));
    assertThat(dateTime.getDayOfMonth(), is(30));
}

@Test
void convertStringToTimestamp_shouldReturnTimestamp_whenInvalidInput() {
    // given
    String strDate = "7770-91-30";

    // when, then
    assertThrows(DateTimeParseException.class, () -> convertStringToTimestamp(strDate));
}

@Test
void convertStringToTimestamp_shouldReturnTimestamp_whenNullInput() {
    // when
    final Timestamp result = convertStringToTimestamp(null);

    // then
    assertThat(result, is(nullValue()));
}


Another format?

Usually, the string to parse comes with another format. A way to deal with it is to use a formatter to convert it to another format. Here is an example:

Input: 20200130 11:30

Pattern: yyyyMMdd HH:mm

Output: Timestamp of this input

Code:

static Timestamp convertStringToTimestamp(String strDate) {
    final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm");
    return Optional.ofNullable(strDate) //
                   .map(str -> LocalDateTime.parse(str, formatter))
                   .map(Timestamp::valueOf) //
                   .orElse(null);
}

Test:

@Test
void convertStringToTimestamp_shouldReturnTimestamp_whenValidInput() {
    // given
    String strDate = "20200130 11:30";

    // when
    final Timestamp result = convertStringToTimestamp(strDate);

    // then
    final LocalDateTime dateTime = LocalDateTime.ofInstant(result.toInstant(), ZoneId.systemDefault());
    assertThat(dateTime.getYear(), is(2020));
    assertThat(dateTime.getMonthValue(), is(1));
    assertThat(dateTime.getDayOfMonth(), is(30));
    assertThat(dateTime.getHour(), is(11));
    assertThat(dateTime.getMinute(), is(30));
}
KeyMaker00
  • 6,194
  • 2
  • 50
  • 49
3
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

Date date = formatter.parse(dateString);

Timestamp timestamp = new Timestamp(date.getTime());

System.out.println(timestamp);
Nicomedes E.
  • 1,326
  • 5
  • 18
  • 27
Akshay Misal
  • 683
  • 6
  • 6
2
DateFormat formatter;
formatter = new SimpleDateFormat("dd/MM/yyyy");
Date date = (Date) formatter.parse(str_date);
java.sql.Timestamp timeStampDate = new Timestamp(date.getTime());
Mahesh Narwade
  • 609
  • 6
  • 7
2

This is what I did:

Timestamp timestamp = Timestamp.valueOf(stringValue);

where stringValue can be any format of Date/Time.

סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
Amulya Koppula
  • 150
  • 1
  • 5
  • No, `Timestamp.valueOf()` does not accept just any date and time format. For example not the *old format* in the question, `yyyy-MM-dd`. And I still believe that no one should use the `Timestamp` class anymore. It’s poorly designed, a true hack on top of the already poorly designed `Date` class. It was once used to transfer values to and from SQL databases, but today it’s recommended to use `OffsetDateTime`, `LocalDateTime` or `Instant` instead. – Ole V.V. Feb 15 '21 at 20:10
0

First, convert your date string to date, then convert it to timestamp by using the following set of line:

final Date date = new Date();
final Timestamp timestamp = new Timestamp(date.getTime()); // Instead of date, put your converted date
final Timestamp myTimeStamp = timestamp;
Sae1962
  • 1,122
  • 15
  • 31
KhAn SaAb
  • 5,248
  • 5
  • 31
  • 52
  • 2
    I am not sure how I will put my converted date. I guess my problem starts with `((SimpleDateFormat) formatter).applyPattern(NEW_FORMAT)` ; ? When I use my date, Date d, it still produces wrong result: 2009-10-20 00:00:00.0 – Dimitra Micha Sep 20 '13 at 13:11
0

can you try it once...

String dob="your date String";
String dobis=null;
final DateFormat df = new SimpleDateFormat("yyyy-MMM-dd");
final Calendar c = Calendar.getInstance();
try {
    if(dob!=null && !dob.isEmpty() && dob != "")
    {
    c.setTime(df.parse(dob));
    int month=c.get(Calendar.MONTH);
    month=month+1;
    dobis=c.get(Calendar.YEAR)+"-"+month+"-"+c.get(Calendar.DAY_OF_MONTH);
    }

}
Jens
  • 67,715
  • 15
  • 98
  • 113
Suresh U
  • 463
  • 3
  • 14
  • 8
    `dob != ""` is superfluos and wrong - never compare Strings with `==` or `!=`. And you should not format Dates that way, that is what (Simple)DateFormat is for. – Gyro Gearless Sep 20 '13 at 12:10
0

I'm sure the solution is that your oldDateString is something like "2009-10-20". Obviously this does not contain any time data lower than days. If you format this string with your new formatter where should it get the minutes, seconds and milliseconds from?

So the result is absolutely correct: 2009-10-20 00:00:00.000

What you'll need to solve this, is the original timestamp (incl. time data) before your first formatting.

solver
  • 19
  • 1
  • 1
    This issue is 9 months old, and from the comments it's clear that the actual issue is about the format of the date string, and not about the actual values. – Robby Cornelissen Jun 26 '14 at 08:47