有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

SQL日期的Java日期模式(ISO 9075)

我试图解析一个SQL日期字符串(ISO 9075),它使用微秒(!)而不是毫秒,例如

2010-11-22 08:08:08.123456

然而,SimpleDataFormat拒绝识别像“yyyy-MM-dd HH:MM:ss.SSSSSS”和“yyy-MM-dd HH:MM:ss.SSS”这样的模式也不起作用

我使用的代码如下所示:

String dateString = "2010-11-22 08:08:08.123456";
String pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS";

try
{
    format = new SimpleDateFormat(pattern);
    format.setLenient(false);
    position.setIndex(0);
    Date date1 = format.parse(dateString, position);
    System.out.println("Date 1: " + date1);
    Date date2 = format.parse(dateString);
    System.out.println("Date 2: " + date1);
}
catch (Exception e) // Should not happen
{
    e.printStackTrace();
}

我使用的两种模式(“.SSS”或“.SSSSSS”)中的任何一种,date1都是打印机null,而date2会导致解析异常(java.text.ParseException:不可解析的日期)


共 (3) 个答案

  1. # 1 楼答案

    tl;博士

    插入/更新

    myPreparedStatement.setObject( 
        … , 
        Instant.parse( "2010-11-22 08:08:08.123456".replace( " " , "T" ) + "Z" ) 
    ) ;
    

    检索

    LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
    String output = ldt.toString().replace( "T" , " " ) ;  // Remove the standard ISO 8601 format’s use of `T` in the middle with the SQL-style SPACE.
    

    爪哇。时间

    Java 8带来了新的java.time package,以取代臭名昭著的麻烦的旧java。util。日期日历和SimpleDateFormat类。这些旧的遗留类的分辨率仅限于毫秒,而输入字符串的分辨率为微秒。不能将小数点后六位塞进限制为三位的数据类型中

    java中的日期时间值。时间nanosecond分辨率,足够你的微秒。这意味着小数点后一秒最多可保留九位小数

    对于JDBC 4.2及更高版本,直接使用Instant

    解析输入字符串。遵守java中默认使用的ISO 8601格式。时间类,用^ {CD2}}替换中间的空间。你给出的例子必须来自一个列类型TIMESTAMP WITHOUT TIME ZONE,这意味着不是一个特定的时刻,不是时间线上的一个点

    String input = "2010-11-22 08:08:08.123456".replace( " " , "T" ) ;
    LocalDateTime ldt = LocalDateTime.parse( input ) ;
    

    如果这个输入是UTC中的一个时刻,那么添加一个Z。然后你在时间线上有一个特定的时刻。用于TIMESTAMP WITH TIME ZONE的列类型

    String input = "2010-11-22 08:08:08.123456".replace( " " , "T" ) + "Z" ;
    Instant instant = Instant.parse( input ) ;
    

    发送到你的数据库

    myPreparedStatement.setObject( … , instant ) ;
    

    …还有

    Instant instant = myResultSet.getObject( … , Instant.class ) ;
    

    关于java。时间

    java.time框架内置于Java8及更高版本中。这些类取代了麻烦的legacy日期时间类,如^{}^{}、&^{}

    目前位于maintenance modeJoda-Time项目建议迁移到java.time

    要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和解释。规范是JSR 310

    你可以交换java。时间对象直接与数据库连接。使用符合JDBC 4.2或更高版本的JDBC driver。不需要字符串,也不需要java.sql.*

    在哪里可以获得java。时间课

    ThreeTen-Extra项目扩展了java。有额外课程的时间。这个项目是java未来可能增加的一个试验场。时间你可以在这里找到一些有用的类,比如^{}^{}^{}more


    更新:Joda-Time项目现在位于maintenance mode,团队建议迁移到java.time类。将这一部分作为历史保留下来

    乔达时间

    如上所述,应该避免使用java。util。日期日历和SimpleDateFormat类。从Java8开始,您可以选择使用Java。时间或Joda-Time或两者兼而有之,因为它们各自有各自的优势和劣势。Joda Time也适用于早期版本的Java

    可以使用Joda Time解析该字符串

    或者,如果您可以访问java。sql。生成字符串的时间戳,只需将时间戳对象传递给DateTime的构造函数。我还建议传递一个时区,因为DateTime对象知道自己指定的时区

    DateTime dateTime = new DateTime( mySqlTimestamp, DateTimeZone.UTC );
    

    或者

    DateTime dateTime = new DateTime( mySqlTimestamp, DateTimeZone.forID( "Europe/Paris" ) );
    

    Joda Time的分辨率为milliseconds。因此,无论以哪种方式生成日期时间(解析或传递),都会丢失第二个日期时间的更细部分(忽略/截断,不舍入)

  2. # 2 楼答案

    您可能需要调用DateFormat parse,因为我认为它会切断字符串。试试看:

    Date date1 = format.parse(dateString);
    

    另外,不要使用“SSS”。根据规范,只有“SSS”对dateformat有效

    除此之外,我同意切断它或在SQL中解析

    另外,你已经对false设置了宽容,所以它是严格的。因此,字符串变长会导致它失败。也许这就是它返回空值的原因。不确定,必须进行测试

  3. # 3 楼答案

    在解析日期之前,可能会从日期字符串中去掉剩余的小数部分?我有以下几点

        String dateString = "2010-11-22 08:08:08.123456";
        String fraction = dateString.substring(dateString.length() - 3);
        String formatString = dateString.substring(0, dateString.length() - 3);
        String pattern = "yyyy-MM-dd HH:mm:ss.SSS";
        ParsePosition position = new ParsePosition(0);
    
        try
        {
    
            SimpleDateFormat format = new SimpleDateFormat(pattern);
            format.setLenient(false);
            position.setIndex(0);
            Date date1 = format.parse(formatString, position);          
            System.out.println("Date 1: " + date1);
            System.out.println("Date 1 fraction: " + fraction);
            Date date2 = format.parse(formatString);
            System.out.println("Date 2: " + date2);
            System.out.println("Date 2 fraction: " + fraction);
        }
        catch (Exception e) // Should not happen
        {
            e.printStackTrace();
        }
    

    这样,在仍然保留分数的情况下,日期可以解析到毫秒精度