0

I'm trying to convert string timestamp having timezone in it to a timestamp with the same timezone. However, when executing the below code, I'm getting default system timestamp. Can someone help me on this. Below is the code I'm trying.

try {
    Date dt = new Date();
    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    f.setTimeZone(TimeZone.getTimeZone("GMT"));
    String dateString = f.format(dt);
    System.out.println("DateString: "+dateString);
    Date parsedDate = f.parse(dateString);
    System.out.println("ParsedDate: "+parsedDate);
    Timestamp timestamp = new Timestamp(parsedDate.getTime());
    System.out.println("Timestamp: "+timestamp);
    
}catch (Exception e) {
    // TODO: handle exception
}

When executing the above code, I get below result:

DateString: 2021-03-26T06:57:05.982+0000
ParsedDate: Fri Mar 26 12:27:05 IST 2021
Timestamp: 2021-03-26 12:27:05.982

But I have to get output in Timestamp as 2021-03-26T06:57:05.982+0000

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
heman
  • 67
  • 1
  • 9
  • 4
    Read the answers to this: https://stackoverflow.com/questions/2891361/how-to-set-time-zone-of-a-java-util-date . The best advise is to not use java.util.Date if you have to work with time zones. Use the classes in java.time package. – Torben Mar 26 '21 at 07:21
  • Two things to mention here (at least): First of all, consider the comment given by @Torben. Secondly, why are you wondering about your formatted output being different from your unformatted one? You are printing a `Date` with a `SimpleDateFormat` at first, then one without any format and finally you print a `Timestamp`... – deHaar Mar 26 '21 at 07:28
  • I want to get timestamp with timezone in this format 2021-03-26T06:57:05.982+0000 adding +0530 or -0530, here I have to get the time format as yyyy-MM-dd'T'HH:mm:ss.SSSZ with specified timezone. When Im trying to get the output as above it is working but it is in string so want to parse that in a timestamp. so trying to convert that string to timestamp but it is returning the system timestamp rather than mentioned timezone timestamp. – heman Mar 26 '21 at 07:48
  • 3
    a `Timestamp` (assuming `java.sql.Timestamp`) is just an instant in time, there is no time zone involved. You can have its representation given in different time zone. Maybe you need a `ZonedDateTime`, that is a date and time with respective time zone; or even `LocalDateTime` that has no time zone at all –  Mar 26 '21 at 08:00
  • 1
    Related: [Is java.sql.Timestamp timezone specific?](https://stackoverflow.com/questions/14070572/is-java-sql-timestamp-timezone-specific) – Mark Rotteveel Mar 26 '21 at 09:49
  • If you thought you needed a `java.sql.Timestamp` for your SQL database, by all likelihood you don’t. Since JDBC 4.2 for a `timesatamp with time zone` in SQL (recommended for a timestamp) give it an `OffsetDateTime`. For a `timestamp` without time zone in SQL (not really a timestamp), give it a `LocalDateTime`. – Ole V.V. Mar 27 '21 at 11:57
  • You are asking the impossible. A `Timestamp` hasn’t got, as in cannot have a format. A `java.sql.Timestamp` always prints as `2021-03-26 12:27:05.982`, only with more or fewer decimals. Never as `2021-03-26T06:57:05.982+0000`. What made you think that you needed that? – Ole V.V. Mar 27 '21 at 12:00
  • I recommend that you neither use `Date`, `SimpleDateFormat`, `Timezone` nor `Timestamp`. All of those classes are poorly designed and long outdated (`SimpleDateFormat` in particular notoriously troublesome). Instead use `OffsetDateTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Mar 27 '21 at 12:04

2 Answers2

2

Your code using java.time classes:

        ZonedDateTime zdt = ZonedDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
        DateTimeFormatter dfGMT = df.withZone(ZoneId.of("GMT"));
        
        String dateString = dfGMT.format(zdt);
        System.out.println("DateString: "+dateString);
        
        ZonedDateTime parsedDate = ZonedDateTime.parse(dateString,dfGMT);
        System.out.println("ParsedDate: "+ parsedDate);
        Timestamp timestamp = Timestamp.from(parsedDate.toInstant());
        System.out.println("Zoned Timestamp: "+timestamp);
        
        //ignoring zone info from date string
        LocalDateTime ldt = LocalDateTime.from(dfGMT.parse(dateString));
        timestamp = Timestamp.valueOf(ldt);
        System.out.println("Zone stripped GMT timestamp: "+timestamp);
        
        
        ZonedDateTime zdt1 = ldt.atZone(ZoneId.of("GMT"));
        zdt1 = zdt1.withZoneSameInstant(ZoneId.of("America/Chicago"));
        timestamp = Timestamp.valueOf(zdt1.toLocalDateTime());
        System.out.println("Zone stripped CST timestamp: "+timestamp);

Output:

DateString: 2021-03-26T09:10:37.537+0000
ParsedDate: 2021-03-26T09:10:37.537Z[GMT]
Zoned Timestamp: 2021-03-26 14:40:37.537
Zone stripped GMT timestamp: 2021-03-26 09:10:37.537
Zone stripped CST timestamp: 2021-03-26 04:10:37.537
the Hutt
  • 16,980
  • 2
  • 14
  • 44
  • Thanks for the response, here I want to get in Timestamp as 2021-03-26T07:40:55.771+0000 can you help – heman Mar 26 '21 at 07:53
  • java.sql.Timestamp treats time in local time zone. So if you give GMT time to the Timestamp it'll convert it into IST, if your server is in India. What you are asking is to ignore time zone provided with the date string and just use date time in local time zone. – the Hutt Mar 26 '21 at 07:57
  • 1
    For more info refer: https://stackoverflow.com/questions/14070572/is-java-sql-timestamp-timezone-specific – the Hutt Mar 26 '21 at 07:58
  • I've modified the answer. To get the result you want look for `Zone stripped timestamp` output. – the Hutt Mar 26 '21 at 08:07
  • from your above answer I could only get time for GMT only, if I change to CST im not getting result. also is it possible to get the output as 2021-03-26T07:40:55.771+0000 for GMT and 2021-03-26T03:19:10.299-0500 for CST can you help me to get like this. – heman Mar 26 '21 at 08:19
  • 1
    Done! CST is 5 hours behind GMT. – the Hutt Mar 26 '21 at 09:15
  • @heman You are contradicting yourself. The string you are asking for, `2021-03-26T07:40:55.771+0000`, *is* in GMT, denoted by the offset of `+0000` from GMT (or UTC). America/Winnipeg and America/Chicago time zones are at offset -05:00 during summer time (DST), so `+0000` would be plain wrong. – Ole V.V. Mar 27 '21 at 12:11
0

java.time and JDBC 4.2

You don’t need any formatting, parsing nor conversion. To insert the current timestamp into your SQL database:

    OffsetDateTime currentTimestamp = OffsetDateTime.now(ZoneOffset.UTC);
    String sql = "insert into your_table(your_timestamp_with_time_zone_column) values (?);";
    try (PreparedStatement prepStmt = yourDatabaseConnection.prepareStatement(sql)) {
        prepStmt.setObject(1, currentTimestamp);
        prepStmt.executeUpdate();
    }
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161