从Oracle数据库转换具有AM / PM日期时间的字符串

时间:2012-05-04 15:57:42

标签: java parsing simpledateformat java.util.date

我有03-AUG-12 08.15.00.000000000 PM -05:00形式的时间戳 我无法在String上的表单中获得yyyy-MM-dd HH:mm:ss代表。

这是我的代码:

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);
}

基本上它是Oracle数据库中带有时区格式的时间戳。

3 个答案:

答案 0 :(得分:4)

你不能使用SimpleDateFormat来解析这样的字符串,至少没有一些限制:

  • 在Java 7之前不支持-05:00(根据ISO 8601)的时区标识符。使用Java 7,您可以使用XXX模式对其进行解析。

  • 要正确解析月份名称,您应指定需要英语区域设置。

  • 毫秒(S)的模式解析无限数量的数字。如果您的字符串包含“08.15.00.100000000”,SimpleDateFormat会将其解析为8:15:00和100000000ms,将预期值增加近28小时。如果您确定该值始终为0,则可以忽略此问题。

如果您可以接受上一期并使用Java 7,那么您应该使用以下内容:

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

答案 1 :(得分:3)

更改此行:

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

您需要使用小写h来解析AM / PM小时1-12。

答案 2 :(得分:1)

TL;博士

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 );

对象,而不是字符串

您提到了Oracle。从数据库检索数据时,请使用对象而不是字符串。向ResultSet询问java.sql.Timestamp对象。

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

从麻烦的旧日期时间类转换为现代java.time类型。查看旧类上添加的新方法,以便于转换为/从java.time转换。

Instant instant = ts.toInstant();

或者最好,如果使用JDBC 4.2或更高版本,并使用Java 8或更高版本,您可以通过java.time.Instant方法检索ResultSet::getObject

但是如果你必须解析一个字符串,请继续阅读。

避免旧的日期时间类

与最早版本的Java捆绑在一起的旧日期时间类很麻烦且令人困惑。现在取代了java.time类。

纳秒

这一串零必须以nanosecond分辨率表示一小部分秒,最多为小数部分的九位数。旧的日期时间类只能处理milliseconds,但幸运的是,现代java.time类确实可以处理高达纳秒的分辨率。

使用java.time

定义格式化模式以解析给定输入。顺便说一句,您的数据格式不是最佳的;将来,对表示日期时间值的字符串使用ISO 8601标准格式。

我们使用“构建器”来指定不区分大小写的解析。英文名称的正确缩写是initial-cap Aug,但您的输入使用全部大写。

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

告诉构建器实例化我们的格式化程序。 Locale确定(a)用于翻译日期名称,月份名称等的人类语言,以及(b)决定缩写,大小写,标点符号等问题的文化规范。

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

最后,将字符串解析为OffsetDateTime对象。

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

转储到控制台。请注意我们的8 PM如何转换为20小时的24-hour clock值。

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

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

time zoneoffset-from-UTC 加上一组用于处理夏令时(DST)等异常的规则。如果需要,请应用ZoneId获取ZonedDateTime

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

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧日期时间类,例如java.util.Date.Calendar和& java.text.SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。

大部分java.time功能都被反向移植到Java 6& ThreeTen-Backport中的7,并进一步适应Android中的ThreeTenABP(见How to use…)。

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter等。