-1

I am getting datetime Default CURRENT_TIMESTAMP result from MSSQL server database, Now i need to parse this date,time etc. Database result is like 2016-05-14 12:54:01.363

All i need is to traverse this datetime format. As i am doing it below.

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     try
    {
        Date date = format.parse(dateStr);
        SimpleDateFormat todayFormat = new SimpleDateFormat("dd");
        String dateToday = todayFormat.format(date);
        format = dateToday.equals(today) ? new SimpleDateFormat("hh:mm a") : new SimpleDateFormat("dd LLL, hh:mm a");
        String date1 = format.format(date);
        timestamp = date1.toString();
        //
    }
    catch (ParseException e)
    {
        e.printStackTrace();
    }

But I am getting error of:

    java.text.ParseException: Unparseable date: "{"date":"2016-05-14 12:54:01.363000","timezone":"UTC","timezone_type":3}" (at offset 0)

at line 3 .i.e Date date = format.parse(dateStr);

Need help!

  • Please search Stack Overflow before posting. – Basil Bourque May 15 '16 at 04:38
  • @BasilBourque your marking as duplicate does not lead me to my answer because i am getting an error of **Unparseable date: "{"date":"2016-05-14 12:54:01.363000","timezone":"UTC","timezone_type":3}"** not **java.text.ParseException: Unparseable date: "2015-03-26 1624:32:39"**. Please unmark this question as a duplicate. –  May 16 '16 at 14:07
  • [A] You are correct, you Question is not a duplicate of that particular question, so I re-opened. But it is a duplicate of others. [B] Your quoted result in first paragraph is *not* the actual offending. You omitted the extra three zeros at the end, which is the source of your problem. Please edit your Question to be correct. [C] You posted way too much code, irrelevant code. Only the two `format =` and `date = ` lines are relevant. When posting, compose a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – Basil Bourque May 16 '16 at 18:44

2 Answers2

2

The problem depends on how you construct the format variable, and it's good practice to use passed-in pattern rather than default one. In your case (the argument is like "2016-05-14 12:54:01.363", then the format could be like that:

DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date date = format.parse(dateStr);

If your dataStr is returned by a json web service call with the format as indicated in the exception, then you can map the dateStr to the response type, for instance assumed it is called MyDate class.

ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
MyDate myDate = mapper.readValue(dateStr, MyDate.class);
Date date = myDate.getDate();

If you don't know the return type, you can simply map it to a Map class:

Map dateMap = new ObjectMapper().readValue(dateStr, Map.class);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date date = format.parse(dateMap.get("date"));
Simon L
  • 173
  • 1
  • 11
  • i have converted **new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");** to **new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");**. But still getting the same error. Why? –  May 16 '16 at 13:48
  • @Kamran Bhatti - Please make sure the input dateStr is something like "**2016-05-14 12:54:01.363**", but not anything like "**{"date":"2016-05-14 12:54:01.363000","timezone":"UTC","timezone_type":3}**". – Simon L May 16 '16 at 14:51
  • my database column showing me it is just **2016-05-14 12:54:01.363** but dateStr shows me **"{"date":"2016-05-14 12:54:01.363000","timezone":"UTC","timezone_type":3}"** when i get that column in json. i dont know whats the problem –  May 16 '16 at 15:11
  • @Kamran Bhatti - can you post how you get the json string. But it looked like your json response should be mapped to a class type. so you can use the JSON api to map it, I changed my answer to reflect it. – Simon L May 16 '16 at 18:16
  • Thanks for your solution, it helped me too! –  May 17 '16 at 16:40
  • @Kamran Bhatti - if that solves your problem, will you please accept the answer. – Simon L May 17 '16 at 18:06
  • I accepted the answer posted by @basil above. That clarify me more, and yes both answers are applicable. –  May 17 '16 at 19:30
2

Microseconds

Your Question’s text quotes the input string as 2016-05-14 12:54:01.363 but your error message says otherwise, 2016-05-14 12:54:01.363000. Those extra three digits are microseconds.

The old date-time classes such as java.util.Date resolve only to milliseconds (3 digits after the decimal point for fraction of second). So SimpleDateFormat cannot handle such input. Either truncate the input string, or better, use modern date-time classes instead.

java.time

The bigger problem is that you are using old outmoded date-time classes from the earliest versions of Java. Those classes have been supplanted by the java.time framework built into Java 8 and later. Much of that java.time functionality has been back-ported to Java 6 & 7 by the ThreeTen-Backport project, and further adapted to Android by ThreeTenABP. So no reason to wrestle with those old and notoriously troublesome classes.

The java.time classes have much finer granularity, resolving to nanoseconds (9 digits of decimal fraction of second).

In java.time, the Instant class is a moment on the timeline in UTC with resolution of nanoseconds. An Instant is the equivalent of a java.util.Date except with finer resolution.

For more info on converting between old types and java.time types, see my Answer with diagram to another question.

Retrieve date-time values as date-time type

You should be retrieving date-time values from your database as date-time types, not as Strings. If your JDBC driver is complies with JDBC 4.2 (an update to JSR 221, and described here), you may be able to retrieve directly into an OffsetDateTime. You can think of an OffsetDateTime as an Instant plus an offset-from-UTC (a number hours, minutes, and seconds).

java.time.OffsetDateTime odt = resultSet.getObject( 1 );

If not, fall back to using the old java.sql types. For date-time, that means java.sql.Timestamp.

java.sql.Timestamp ts = resultSet.getTimestamp( 1 );

Minimize your use of the old java.sql types as they are part of the mess that is java.util.Date/.Calendar and so on. Immediately convert to java.time. To convert, look for new methods added to the old classes, such as toInstant.

Instant instant = ts.toInstant();

Parsing

If you must parse that input string, the easiest way is to make it comply with the ISO 8601 standard formats. The java.time classes use ISO 8601 formats by default when parsing/generating Strings.

To comply, replace the SPACE in the middle with a T. And, assuming this string does indeed represent a moment in UTC, append a Z. The Z is short for Zulu which means UTC.

String input = "2016-05-14 12:54:01.363000";
String inputModified = input.replace( " " , "T" );
Instant instant = Instant.parse( inputModified );

Time Zone

The Question ignores the crucial issue of time zones.

The best practice is to store date-time values in UTC. The better databases will adjust incoming data into UTC. When retrieved as a java.sql.Timestamp your value is in UTC, and so too when converted to an Instant.

A date and a time-of-day depends on the time zone. Apply a time zone (ZoneId) to your Instant to get a ZonedDateTime.

ZoneId zoneId = zoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Then interrogate to get the day of month and the time that you require.

int dayOfMonth = zdt.getDayOfMonth();

If you want the time-of-day as an object in its own right, use the LocalTime class.

LocalTime localTime = zdt.toLocalTime();

If you really want a String of the time-of-day, use the java.time.format package.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "hh:mm a" );
String output = zdt.format( formatter );

Even better, let java.time do the work of automatically formatting. Note the use of Locale, which determines (a) human language of name of month and such, and (b) cultural norms such as the ordering of the elements like year-month-day. Better to explicitly specify the Locale than implicitly rely on the JVM’s current default Locale which can change at runtime.

DateTimeFormatter timeOfDayFormatter = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT );
timeOfDayFormatter = timeOfDayFormatter.withLocale( Locale.CANADA_FRENCH );
String output = zdt.toLocalTime().format( timeOfDayFormatter );
Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • That's really an awesome explanation I have ever read. I understand everything clearly. But **Instant** is not getting resolve. It says **cannot resolve symbol Instant**. +1 for this kind of explanation. Thanks! –  May 17 '16 at 08:12
  • @KamranBhatti You must import `java.time.Instant` or `java.time.*`. The other classes, `ZoneId`, `ZonedDateTime`, `LocalTime`, `OffsetDateTime`, are also all in the java.time package. The `DateTimeFormatter` class is in the `java.time.format` package. These packages are built into Java 8. Your IDE should be able to figure this out. Verify that your project in the IDE is configured for compiling against Java 8 (not Java 6 or 7). – Basil Bourque May 17 '16 at 08:22
  • I verified and was using Java 7, now I configured it to java 8 as **C:\Program Files\Java\jdk1.8.0_25** but still getting the same error at **Instant** –  May 17 '16 at 10:07
  • Solved the problem, your solution was a great help indeed! thanks Again! –  May 17 '16 at 16:41