Conversion of string with AM/PM date-time, from Oracle database

只谈情不闲聊 提交于 2019-12-01 22:16:13

问题


I have the timestamp in form of 03-AUG-12 08.15.00.000000000 PM -05:00 I am unable to get a String representation in form on yyyy-MM-dd HH:mm:ss.

Here is my code :

public static void convert() {

    String oldstring = "03-AUG-12 08.15.00.000000000 PM -05:00";
    Date date = null;
    try {
        date = new SimpleDateFormat("dd-MMM-yy HH.mm.ss.S aa").parse(oldstring);
    }
    catch (ParseException e) {
        e.printStackTrace();
    }

    String newstring = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    System.out.println(newstring);
}

Basically it is a timestamp with timezone format from the Oracle database.


回答1:


You can't use SimpleDateFormat to parse such a string, at least not without some limitations:

  • A time zone designator like -05:00 (according to ISO 8601) is not supported until Java 7. With Java 7 you can use the XXX pattern to parse it.

  • To parse the month name correctly, you should specify that you require an English locale.

  • The pattern for milliseconds (S) parses an unlimited number of digits. If your string contains "08.15.00.100000000", SimpleDateFormat would parse this as 8:15:00 and 100000000ms, adding almost 28 hours to the expected value. If you are sure that the value is always 0, you can ignore this problem.

If you can accept the last issue and use Java 7, you should be using something like this:

new SimpleDateFormat("dd-MMM-yy hh.mm.ss.S aa XXX", Locale.ENGLISH)




回答2:


Change this line like this:

        date = new SimpleDateFormat("dd-MMM-yy hh.mm.ss.S aa").parse(oldstring);

You need to use the lowercase h which parses the AM/PM hours 1-12.




回答3:


tl;dr

DateTimeFormatter f = new DateTimeFormatterBuilder ().parseCaseInsensitive ().appendPattern ( "dd-MMM-yy hh.mm.ss.SSSSSSSSS a ZZZZZ" ).toFormatter ().withLocale ( Locale.US );
OffsetDateTime odt = OffsetDateTime.parse ( "03-AUG-12 08.15.00.000000000 PM -05:00" , f );

Objects, not strings

You mentioned Oracle. When retrieving data from a database, use objects rather than strings. Ask your ResultSet for a java.sql.Timestamp object.

java.sql.Timestamp ts = myResultSet.getTimestamp( … );

Convert from the troublesome old date-time class to the modern java.time type. Look to new methods added on the old classes to facilitate conversion to/from java.time.

Instant instant = ts.toInstant();

Or preferably, if using JDBC 4.2 or later, and using Java 8 or later, you may be able to retrieve an java.time.Instant via the ResultSet::getObject method.

But if you must parse a string, read on.

Avoid old date-time classes

The old date-time classes bundled with the earliest versions of Java are troublesome and confusing. Now supplanted by the java.time classes.

Nanoseconds

That bunch of zeros must represent a fraction of a second with nanosecond resolution, up to nine digits of a decimal fraction. The old date-time classes can handle only milliseconds, but fortunately the modern java.time classes can indeed handle a resolution up to nanoseconds.

Using java.time

Define a formatting pattern to parse the given input. By the way, your data’s format is less than optimal; in the future, use ISO 8601 standard formats for strings that represent date-time values.

We use a “builder” in order to specify case-insensitive parsing. Proper abbreviation for a name of month in English is initial-cap, Aug, but your input uses all-caps.

String pattern = "dd-MMM-yy hh.mm.ss.SSSSSSSSS a ZZZZZ";
DateTimeFormatterBuilder fb = new DateTimeFormatterBuilder ().parseCaseInsensitive ().appendPattern ( pattern );

Tell the builder to instantiate our formatter. The Locale to determines (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.

Locale l = Locale.US;
DateTimeFormatter f = fb.toFormatter ().withLocale ( l );

Finally, parse the string as an OffsetDateTime object.

String input = "03-AUG-12 08.15.00.000000000 PM -05:00";
OffsetDateTime odt = OffsetDateTime.parse ( input , f );

Dump to console. Note how our 8 PM is transformed into the 24-hour clock value of 20 hours.

System.out.println ( "input: " + input + " | odt.toString(): " + odt );

input: 03-AUG-12 08.15.00.000000000 PM -05:00 | odt.toString(): 2012-08-03T20:15-05:00

A time zone is an offset-from-UTC plus a set of rules for handling anomalies such as Daylight Saving Time (DST). If desired, apply a ZoneId to get a ZonedDateTime.

ZoneId z = ZoneId.of( “America/Montreal” );
ZonedDateTime zdt = odt.atZoneSameInstant( z );

About java.time

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

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

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

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

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.



来源:https://stackoverflow.com/questions/10452210/conversion-of-string-with-am-pm-date-time-from-oracle-database

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!