0

I am getting the JSON responses for the Date time field as follows: /Date(1534291200000)/ and PT12H18M02S

 SELECT     CAST('ClearingDate' AS TIMESTAMP) from testdata;

On using CAST functions or to_timestamp I am getting the following error:

ERROR: invalid input syntax for type timestamp: "/Date(1534291200000)/" SQL state: 22007

How can I convert this to timestamp using postgresql? If not postgresql is there a way to do so in Java?

user3320097
  • 11
  • 1
  • 7
  • You need to cleanup the string, the you can use `to_timestamp()`: https://stackoverflow.com/questions/42219890 –  Sep 04 '18 at 18:08
  • Similar to [Convert Json date to java date](https://stackoverflow.com/questions/24956396/convert-json-date-to-java-date) and other questions. Please search. – Ole V.V. Sep 04 '18 at 18:44

5 Answers5

1

The solution to directly convert it in PostgreSQL:

to_timestamp(CAST(SUBSTRING (CAST(Clearingdate AS varchar), 9, 10) AS NUMERIC))
from date_test;

I finally figured it out. Thanks a lot for all your inputs.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
user3320097
  • 11
  • 1
  • 7
  • It will give incorrect results with a date before September 9, 2001, since there will be fewer digits. In any case thanks for posting the solution. And it will ignore the milliseconds (fraction of second), but in your example that is 0 anyway, so doesn’t make any difference. – Ole V.V. Sep 05 '18 at 07:08
  • Thanks for your response. But the result I have got is '2018-07-31 19:00:00-05' which is greater than Sept 9,2001 also within the correct range for that particular value. – user3320097 Sep 05 '18 at 14:30
  • 2018-07-31 19:00:00-05 is the same point in time as 2018-08-01 00:00:00 UTC, just presented as the date and time at UTC offset -05:00 (that’s what the -05 in the end means). Would that be correct? (Before the mentioned date in 2001 you’d get results that are typically very far off.) – Ole V.V. Sep 05 '18 at 15:41
  • Yes that's right. It would be 2018-08-15 00:00:00 UTC for the epoch value 1534291200000 and '2018-07-31 19:00:00-05' for 1533081600000 which was the expected result. Also, the below post from you using the Java provides the same answer as well. Thanks a lot. – user3320097 Sep 05 '18 at 16:23
  • do you have any idea as to what format is this? PT12H18M02S and how can this be converted wither on postgreSQL or Java? – user3320097 Sep 05 '18 at 16:26
  • Preferably a PostgreSQL solution to convert PT12H18M02S to date time – user3320097 Sep 05 '18 at 16:40
  • `PT12H18M02S` is the ISO 8601 notation for a duration, an amount of time of 12 hours 18 minutes and 2 seconds. I don’t know PostgreSQL and would be surprised if it can parse it. Java’s `Duration` class does, use [`Duration.parse`](https://docs.oracle.com/javase/10/docs/api/java/time/Duration.html#parse(java.lang.CharSequence)). – Ole V.V. Sep 05 '18 at 16:48
  • Surprise, [the PostgreSQL documentation](https://www.postgresql.org/docs/8.4/static/datatype-datetime.html) does mention interval input in ISO 8601 format. So it seems that your DB does understand your format. – Ole V.V. Sep 05 '18 at 16:54
0

use timestamp (import java.sql.Timestamp)

String fromJson = "/Date(1534291200000)/";
String ts = fromJson.substring(6, fromJson.length()-2);
Long tsInMillisSec = Long.parseLong(ts);
Timestamp ts = new Timestamp(tsInMillisSec);
Sayantan Mandal
  • 1,246
  • 14
  • 20
  • Timestamp is not working the json response includes the keyword Date. – user3320097 Sep 04 '18 at 17:42
  • This is the sample output of the response : /Date(1534291200000)/ – user3320097 Sep 04 '18 at 17:44
  • could you add the bit more of the sample json response you are getting? – Sayantan Mandal Sep 04 '18 at 17:50
  • I get a list of dates in the date column as follows: '/Date(1534809600000)/' '/Date(1531785600000)/' '/Date(1534809600000)/' '/Date(1534809600000)/' '/Date(1535328000000)/' '/Date(1534896000000)/' '/Date(1531440000000)/' I need to convert this to a postgresql Timestamp – user3320097 Sep 04 '18 at 17:55
  • Try java substring `String fromJson = "/Date(1534291200000)/"; String ts = fromJson.substring(6, fromJson.length()-2); Long tsInMillisSec = Long.parseLong(ts);` – Sayantan Mandal Sep 04 '18 at 18:00
  • The `Timestamp` class was always poorly designed and only meant for transferring `timestamp` values to and from the database. It is now long outdated and replaced by `Instant` from java.time, the modern Java date and time API, So I suggest you use `Instant.ofEpochMilli()` instead. – Ole V.V. Sep 04 '18 at 18:40
0

Sorry, I don’t know how to do this in PostgreSQL. In Java:

    String timestampString = "/Date(1534291200000)/";
    String millisString = timestampString.replaceFirst("^/Date\\((\\d+)\\)/$", "$1");
    Instant inst = Instant.ofEpochMilli(Long.parseLong(millisString));
    System.out.println(inst);

Output is

2018-08-15T00:00:00Z

I am using a regular expression for validating the syntax of the string and taking out just the substring of digits. This number denoted milliseconds since the epoch. The Instant class from java.time, the modern Java date and time API, is the correct one to use for a timestamp (forget about the outdated Timestamp class, we don’t need it anymore).

If you need to store this back into PostgreSQL:

    PreparedStatement stmt = yourConnection.prepareStatement(
            "insert into your_table(your_timestamp_column) values (?);");
    stmt.setObject(1, inst);

Please modify to your database design and situation.

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

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

java.time

The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.

Instant#ofEpochMilli

The key here is to get an object of Instant out of the milliseconds in the given string. Once you have Instant, you can convert it to other java.time types e.g. ZonedDateTime or even to the legacy java.util.Date.

A note on the regex, \D+: \D specifies a non-digit while + specifies its one or more occurrence(s).

Demo:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String text = "/Date(1534291200000)/";
        // Replace all non-digits i.e. \D+ with a blank string
        Instant instant = Instant.ofEpochMilli(Long.parseLong(text.replaceAll("\\D+", "")));
        System.out.println(instant);

        // Now you can convert Instant to other java.time types e.g. ZonedDateTime
        // ZoneId.systemDefault() returns the time-zone of the JVM. Replace it with the
        // desired time-zone e.g. ZoneId.of("Europe/London")
        ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
        // Print the default format i.e. the value of zdt#toString
        System.out.println(zdt);

        // A custom format
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMMM dd HH:mm:ss uuuu", Locale.ENGLISH);
        String strDateTimeFormatted = zdt.format(dtf);
        System.out.println(strDateTimeFormatted);
    }
}

Output:

2018-08-15T00:00:00Z
2018-08-15T01:00+01:00[Europe/London]
Wed August 15 01:00:00 2018

How to get java.util.Date from an Instant?

You should avoid using java.util.Date but for whatsoever purpose, if you want to get java.util.Date, all you have to do is to use Date#from as shown below:

Date date = Date.from(instant);

What about PT12H18M02S?

You can parse it to java.time.Duration which is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementation.

If you have gone through the above links, you might have already learnt that PT12H18M02S specifies a duration of 12 hours 18 minutes 2 seconds which you add to a date-time object (e.g. zdt obtained above) to get a new date-time.

Duration duration = Duration.parse("PT12H18M02S");
ZonedDateTime zdtUpdated = zdt.plus(duration);
System.out.println(zdtUpdated);

Output:

2018-08-15T13:18:02+01:00[Europe/London]

Learn about the modern date-time API from Trail: Date Time.

How to use java.time types with JDBC?

The PostgreSQL™ JDBC driver implements native support for the Java 8 Date and Time API (JSR-310) using JDBC 4.2.

enter image description here

Note that ZonedDateTime, Instant and OffsetTime / TIME [ WITHOUT TIMEZONE ] are not supported. Also, note that all OffsetDateTime instances will have to be in UTC (have offset 0). This is because the backend stores them as UTC.

OffsetDateTime odt = zdt.withZoneSameInstant(ZoneOffset.UTC).toOffsetDateTime();
PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, odt);
st.executeUpdate();
st.close();
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
-1

This might work:

select cast(cast('{"dtJson":"2020-10-23 13:40:54"}'::json->'dtJson' as varchar) as timestamp);