-4
 String str = "2017-08-01T15:15:03.313456768+02:00";
 // The following statement gives IllegalArgumentExceptionTimestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
 Timestamp timeStamp = Timestamp.valueOf(str);
 ZonedDateTime zoneddate = ZonedDateTime.parse(str);
 System.out.println("ZonedDate: "+zoneddate);// prints 2017-08-01T15:15:03.313456768+02:00
 Instant inst = zoneddate.toInstant();
 Timestamp newTime = Timestamp.from(inst);
 System.out.println("Timestamp: "+newTime);// prints 2017-08-01 15:15:03.313456768 without Zone

I am missing Zone during Conversion. Can anyone suggest me how do I get Zone in TimeStamp?

  • i red alredy but SimpleDateFormat does not accept 9 digit milliseconds. – user2814979 Aug 16 '17 at 10:25
  • please Show the code you have tried – Jens Aug 16 '17 at 10:28
  • 1
    `SimpleDateFormat` has millisecond precision (only 3 digits after decimal point). For more than 3 digits, you must Java 8 new `java.time` API: https://stackoverflow.com/questions/30135025/java-date-parsing-with-microsecond-or-nanosecond-accuracy –  Aug 16 '17 at 11:51
  • you are true. i used ZonedDateTime to get exact pattern(above mentioned), but i still have to convert it to TimeStamp. – user2814979 Aug 16 '17 at 12:15
  • @jens: updated code – user2814979 Aug 16 '17 at 12:31
  • @Stephen C: do u still think it is duplicate ? – user2814979 Aug 16 '17 at 12:46
  • 1
    The zone is not missing. A `Timestamp` just keeps the number of nanoseconds since `1970-01-01T00:00Z`, it doesn't have a timezone. When you print it, the `toString()` method is implicity called, and this method adjusts the values to the JVM default timezone (check the value of `TimeZone.getDefault()`, you're probably in a zone where the current offset is `+02:00`). The conversion you did is correct, you can check with `zoneddate.toInstant().equals(newTime.toInstant())` (it'll be `true`). And it can also be considered a duplicate of [this](https://stackoverflow.com/q/43259722/7605325) –  Aug 16 '17 at 13:08
  • @Hugo: Yes you are right,both are same, but i have to persist Timestamp in database, it must have to show the zone. How would i get exact format. – user2814979 Aug 16 '17 at 13:28
  • 1
    Each database works differently with timestamp/date types, you must check in the respective documentation how to do it, how to keep timezone information, how to not lose precision, and so on. And you're also mistaking the **value** (number of nanoseconds since `1970-01-01T00:00Z`) with **representation** (show the values of day/month/year/hour/minute/etc in some specific zone). The **value** stored is usually the same (the number of nanoseconds). When showing this **value** to an user, you choose a format (a **representation** of this value). And this format can have zone or not. –  Aug 16 '17 at 13:32
  • 2
    I recommend [this article](https://codeblog.jonskeet.uk/2017/04/23/all-about-java-util-date/) - it talks about `java.util.Date`, but `Timestamp` is similar (actually it extends `Date`), so all concepts apply to both. –  Aug 16 '17 at 13:34

2 Answers2

2

The latest version of this question is this:

Can anyone suggest me how do i get Zone in TimeStamp

The simple answer is that you can't. A Timestamp doesn't include a zone as part of its representation. When you convert generate a Timestamp from a ZonedDateTime you are throwing away the time zone offset.

You can verify this by looking at the source code for the Timestamp class. There is no constructor that allows you to pass in time zone info, and the date / time is represented as UTC. (The getTimezoneOffset() method returns something different ... and the method is deprecated anyway.)

... but i have to persist Timestamp in database, it must have to show the zone.

Then you need to use a different SQL type (or types) to represent the timestamp, and corresponding types on the Java side. Note that some dialects of SQL don't store timezone information in the standard DATE / TIME / TIMESTAMP types.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

The Answer by Stephen C is correct.

Avoid the troublesome old date-time classes such as java.sql.Timestamp. Now supplanted by the java.time classes.

You have a string in standard ISO 8601 format, representing a date-time with an offset-from-UTC but no indication of time zone. So parse as an OffsetDateTime. Move into UTC as a Instant for storage.

Upon retrieval, assign any time zone you wish.

String input = "2017-08-01T15:15:03.313456768+02:00";
OffsetDateTime odt = OffsetDateTime.parse( input ) ;
Instant instant = odt.toInstant() ;  // Adjust into UTC for storage. 
myPreparedStatement.setObject( … , instant ) ;

Retrieve.

Instant instant = myResultSet.getObject( … , Instant.class ) ;
ZoneId z = ZoneId.of( "America/Montreal" ) ;  // or "Europe/Berlin",  "Asia/Kolkata", whatever. 
ZonedDateTime zdt = instant.atZone( z ) ;  // Move from UTC to a time zone.

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154