Search code examples
javascaladatetimesimpledateformat

Parsing string to Timestamp with 7 decimals, datetime format


I am trying to parse a string and change it to a timestamp. However, I haven't been able to find the right datetime format. The time string that is being passed is this:

2020-07-23T02:46:04.0978382Z The formats that I've found for SimpleDateFormat don't exactly match this string. The closest one I've used, makes it off by minutes and seconds, which doesn't seem right.

I've tried the following formats. Format, and format6 parse it but the timestamp is completely off:

  def timestampTest() :Unit ={
    val timestampString = "2020-07-23T02:46:04.0978382Z" // from actual event
    val format = "yyyy-MM-dd'T'HH:mm:ss.SSS" // parses but makes it off by seconds, min, hour: 2020-07-23 03:02:22.382
    val format1= "yyyy-MM-dd'T'HH:mm:ss.SSSZ" // Cant parse
    val format2= "yyyy-MM-dd'T'HH:mm:ss.SSSX" // cant parse
    val format3= "yyyy-MM-dd'T'HH:mm:ss.SSSXX" // cant parse
    val format4 = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" // cant parse
    val format5 = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ" // cant parse
    val format6 = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS"//  Time is off:  2020-07-23 03:02:22.382

    val dateFormat = new SimpleDateFormat(format)
    
    val x = new Timestamp(dateFormat.parse(timestampString).getTime)
 
    println(timestampString)
    println(x)
  }

Is there a datetime format that supports such string? Or does it look like the string I'm receiving will have be adjusted/trimmed.


Solution

  • Is there a datetime format that supports such string?

    Yes, you can use ZonedDateTime or OffsetDateTime or Instant which parses the date-time string format of your question by default (i.e. without using any DateTimeFormatter.ofPattern explicitly).

    import java.time.Instant;
    import java.time.OffsetDateTime;
    import java.time.ZonedDateTime;
    
    public class Main {
        public static void main(String[] args) {
            ZonedDateTime zdt = ZonedDateTime.parse("2020-07-23T02:46:04.0978382Z");
            System.out.println(zdt);
    
            OffsetDateTime odt = OffsetDateTime.parse("2020-07-23T02:46:04.0978382Z");
            System.out.println(odt);
    
            Instant instant = Instant.parse("2020-07-23T02:46:04.0978382Z");
            System.out.println(instant);
        }
    }
    

    Output:

    2020-07-23T02:46:04.097838200Z
    2020-07-23T02:46:04.097838200Z
    2020-07-23T02:46:04.097838200Z
    

    I suggest you switch from the outdated and error-prone legacy date-time API to the modern date-time API.

    What went wrong with using SimpleDateFormat?

    SimpleDateFormat doesn't support nanoseconds. It supports only up to milliseconds and that's the reason why time was off in your output.

    Can I use OffsetDateTime directly in JDBC?

    Yes, of course. Check this page for more information. Give below is the screenshot of the same (in case the link gets broken in the future):

    enter image description here

    Can I get Timestamp from OffsetDateTime?

    Yes, you can (as shown below) but I do not suggest it as it inherits the horribly designed java.util.Date. As suggested earlier, you can use OffsetDateTime directly with JDBC and you should stick to the modern date-time API.

    import java.sql.Timestamp;
    import java.time.OffsetDateTime;
    import java.time.ZoneOffset;
    
    public class Main {
        public static void main(String[] args) {
            OffsetDateTime odt = OffsetDateTime.parse("2020-07-23T02:46:04.0978382Z");
            System.out.println(odt);
    
            Timestamp ts = Timestamp.valueOf(odt.atZoneSameInstant(ZoneOffset.UTC).toLocalDateTime());
            System.out.println(ts);
        }
    }
    

    Output:

    2020-07-23T02:46:04.097838200Z
    2020-07-23 02:46:04.0978382