当前位置: 首页 > 知识库问答 >
问题:

本地日期。parse(String,formatter)返回错误的格式[重复]

韦望
2023-03-14

我必须在DB中查询日期,然后使用LocalDate和格式化程序以不同的格式可视化。问题是,无论我尝试了多少种不同的格式,查询都会以JDBC默认格式(yyyy-mm-dd)可视化。请注意,日期存储在日期字段中(如01-GEN-20)。典型输出为:日期:2019-03-12

String q5= "select to_char(dataord, 'dd/mm/yyyy') as DATAORD\r\n" + 
            "from orders" ;
    executeQuery.query5(q5);

public static void query5(String query) throws SQLException {
        Statement stmt =conn.createStatement();
        ResultSet rs = stmt.executeQuery(query);

        while(rs.next()) {
            
            String dataord = rs.getString("DATAORD");
            
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.ITALY);
            LocalDate ld = LocalDate.parse(dataord,formatter);
            
            System.out.println("Date: " + ld);
            
            
        }
    }

共有3个答案

卫鸿朗
2023-03-14

如果不指定格式,您将始终获得相同的输出,因为System.out.println显示LocalDate#toString()

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String dataord = "20/06/2020";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy", Locale.ITALY);
        LocalDate ld = LocalDate.parse(dataord, formatter);

        System.out.println("Date: " + ld);// Will display LocalDate#toString()

        // Display in specified formats
        System.out.println("Date: " + ld.format(DateTimeFormatter.BASIC_ISO_DATE));
        System.out.println("Date: " + ld.format(DateTimeFormatter.ofPattern("EEE MMM dd yyyy")));
        System.out.println("Date: " + ld.format(formatter));
    }
}

输出:

Date: 2020-06-20
Date: 20200620
Date: Sat Jun 20 2020
Date: 20/06/2020
仇炜
2023-03-14

您正在将数据库中的日期转换为字符串(“to_char”),然后在Java中将该字符串转换为日期,但您想打印它,因此它使用默认格式将日期转换为字符串。

销售订单日期-

我建议您使用“to_char”获取所需的格式,或者只获取一个日期,然后使用SimpleDataformat将其转换为所需格式的字符串。

张勇
2023-03-14

正如其他人指出的,您的行System.out.println("Date:"ld);隐式调用LocalDate::toString而不使用您的DateTimeForware对象。因此您的自定义格式模式永远不会应用。

生成文本时应用格式化程序。不要调用LocalDate::toString,而是调用LocalDate::fogat

String output = ld.format( formatter ) ;
System.out.println( "output: " + output ) ;

20/06/2020

你说:

查询以JDBC默认格式(yyyy-mm-dd)可视化。

不,没有“JDBC默认格式”这样的东西。由LocalDate::toString生成的文本是标准ISO 8601格式,YYYY-MM-DD。这与JDBC无关。

您的代码还有其他问题。请继续阅读。

假设数据库列的类型类似于SQL标准类型DATE,请使用符合JDBC 4.2或更高版本的JDBC驱动程序将值检索为LocalDate对象。停止从文本的角度思考。考虑智能对象,而不是哑字符串

LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;

同样,将适当的对象发送到数据库,而不仅仅是文本。将准备好的语句与代码一起使用 占位符。

myPreparedStatement.setObject( … , localDate ) ;  // Send object to database, to be written into row in table.

只有稍后才应该考虑格式化数据以呈现给用户。通常最好将数据的检索与数据的格式化/呈现分开。首先将您的数据收集到对象中,然后生成文本以进行呈现。

将数据收集到对象中更加容易和简单,即将到来的记录功能在Java14中预览,并在Java15中到达。构造函数,getter方法,toString等于

record Order ( UUID id , String description , LocalDate whenPlaced ) {} // That is all the code you need. Constructor, getter methods, `toString`, `equals` & `hashCode`, and so on are all synthesized automatically behind the scenes.

生成标准ISO 8601格式的文本,表示对象内的值。请注意,LocalDate对象没有文本,没有“格式”。这样的对象知道如何解析文本,并且知道如何生成文本,但它本身并不是文本。

String output = localDate.toString() ;

让java.time在生成文本时自动本地化。

Locale locale = Locale.CANADA_FRENCH ;  // or Locale.US, Locale.ITALY, etc.
DateTimeFormatter f = 
    DateTimeFormatter
    .ofLocalizedDate( FormatStyle.MEDIUM )
    .withLocale( locale ) ;
String output = localDate.format( f ) ;  // Generate text representing the value of this object, while automatically localizing.

或者,如果您坚持,请指定您自己的自定义格式模式。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu" ) ;
String output = localDate.format( f ) ;

下面是完整示例的源代码。

本例使用H2数据库引擎。我们选择在JVM关闭时消失的内存中数据库。

首先,建立一个数据源对象。

// Establish `DataSource`.
org.h2.jdbcx.JdbcDataSource dataSource = new JdbcDataSource();
// Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
dataSource.setURL( "jdbc:h2:mem:pstmt_localdate_example_db;DB_CLOSE_DELAY=-1" );
dataSource.setUser( "scott" );
dataSource.setPassword( "tiger" );

在第一次连接时,隐式创建数据库。该名称来自上述数据源的URL字段。然后,我们执行SQL来创建表order。我们使用尾随下划线来避免命名冲突,因为SQL标准promise永远不会以这种方式命名关键字。

顺便说一句,当文本块功能出现在Java 15中(在Java 14中预览)时,在Java中嵌入SQL代码会容易得多。

// Create database implicitly upon connection, and create first table.
try (
        Connection conn = dataSource.getConnection() ;
        Statement stmt = conn.createStatement() ;
)
{
    String sql =
            "DROP TABLE IF EXISTS order_ ; \n "
                    +
                    "CREATE TABLE IF NOT EXISTS \n" +
                    "  order_ \n" +
                    "  ( \n" +
                    "      pkey_ UUID NOT NULL DEFAULT RANDOM_UUID() PRIMARY KEY , \n" +
                    "      description_ VARCHAR NOT NULL , \n" +
                    "      when_placed_ DATE NOT NULL \n" +
                    "  ) \n" +
                    ";";
    System.out.println( "sql = \n" + sql );
    stmt.execute( sql );
}
catch ( SQLException e )
{
    e.printStackTrace();
}

我们插入一行。

// Insert row.
try (
        Connection conn = dataSource.getConnection() ;
        Statement stmt = conn.createStatement() ;
)
{
    String sql = "INSERT INTO order_ ( description_ , when_placed_ ) \n";
    sql += "VALUES (  ? , ?  ) \n";
    sql += ";";
    System.out.println( "sql = " + sql );
    try (
            PreparedStatement pstmt = conn.prepareStatement( sql , Statement.RETURN_GENERATED_KEYS ) ;
    )
    {

        pstmt.setString( 1 , "blah" );
        pstmt.setObject( 2 , LocalDate.now( ZoneId.of( "America/Montreal" ) ) );
        pstmt.executeUpdate();

        ResultSet rs = pstmt.getGeneratedKeys();
        System.out.println( "INFO - Reporting generated keys." );
        while ( rs.next() )
        {
            UUID uuid = rs.getObject( 1 , UUID.class );
            System.out.println( "generated keys: " + uuid );
        }
    }
}
catch ( SQLException e )
{
    e.printStackTrace();
}

将行转储到控制台。如果您进一步查看这段代码,您将看到我们如何使用自动本地化生成文本。我们使用自定义格式化程序生成文本。我建议通过硬编码的自定义格式进行本地化。

// Dump all rows.
try (
        Connection conn = dataSource.getConnection() ;
        Statement stmt = conn.createStatement() ;
)
{
    System.out.println( "INFO - Reporting all rows in table `order_`." );
    String sql = "SELECT * FROM order_ ; ";
    System.out.println( "sql = " + sql );
    try ( ResultSet rs = stmt.executeQuery( sql ) ; )
    {
        while ( rs.next() )
        {
            UUID pkey = rs.getObject( "pkey_" , UUID.class );
            String description = rs.getString( "description_" );
            LocalDate whenPlaced = rs.getObject( "when_placed_" , LocalDate.class );

            // Dump to console.
            System.out.println( "-----------------" );

            System.out.println( "pkey = " + pkey );
            System.out.println( "description = " + description );
            System.out.println( "whenPlaced = " + whenPlaced );  // Standard ISO 8601 format.

            // Localized.
            Locale locale = new Locale( "fr" , "DZ" );  // French language, Algeria culture.
            DateTimeFormatter formatterLocalized = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( locale );
            String outputLocalized = whenPlaced.format( formatterLocalized );
            System.out.println( "whenPlaced (localized): " + outputLocalized );

            // Custom format.
            DateTimeFormatter formatterCustom = DateTimeFormatter.ofPattern( "dd/MM/uuuu" );
            String outputCustom = whenPlaced.format( formatterCustom );
            System.out.println( "whenPlaced (custom-format): " + outputCustom );

            System.out.println( "-----------------" );
        }
    }
}
catch ( SQLException e )
{
    e.printStackTrace();
}

运行时。

-----------------
pkey = a4388a40-738b-44bd-b01a-2c487c7e08bf
description = blah
whenPlaced = 2020-06-20
whenPlaced (localized): 20/06/2020
whenPlaced (custom-format): 20/06/2020
-----------------

顺便说一句,养成用分号终止SQL语句的习惯。在某些情况下,您可以忽略它,但在其他情况下会导致问题。

 类似资料:
  • 问题内容: 我有一个关于Spring + Thymeleaf日期格式的问题。我有一个简单的实体与领域。我想以表单形式从用户那里获取此日期并将其保存到MySQL数据库。我收到这样的错误: 无法将类型java.lang.String的属性值转换为属性日期所需的类型java.time.LocalDate;嵌套异常是org.springframework.core.convert.ConversionFa

  • 因此,我有一个类“Person”,它包含一个具有4个参数(3个字符串和1个本地日期)的构造函数和一个重写的toString方法,该方法将输出写入控制台(它还将LocalDate变量转换为字符串)。以下是代码: 现在,在main方法中,我创建了3个具有不同参数的不同对象,并将它们全部添加到ArrayList中,如下所示: 程序运行良好,我得到以下格式的输出: 现在,我希望这个日期显示为“1968年1

  • 问题内容: 我在解析我的代码中的平面文件后,试图转换作为文件存在于平面文件中的String 值。 我已经写了代码来做到这一点,但是当我格式化日期时,它总是给我一个指定日期超过1天的日期,有时它会加5:30。 以下是该代码: 上面的输出是 您能告诉我这里是什么问题吗?我在课堂上使用的模式有问题吗?还是代码有问题?我已经为此挠了很久。 问题答案: 您的系统时区不同。输出显示IST-或印度标准时间,与P

  • 问题内容: 代码: 输出: 我正在尝试将字符串转换为NSDate数据类型,但没有获得正确的值。我尝试了许多解决方案,但未返回正确的值。我需要yyyy-MM- dd格式(2016-04-02)与我的输入“ 2016-04-02”相同。如果有人可以帮上忙,那真是太好了。提前致谢 问题答案: 从字符串转换为NSDate时,如果未将时区设置为格式化程序,则将获得本地时区中日期的NSDate。我想您的时区是

  • 问题内容: 所以我正在做一个基本的星期选择器,您可以在其中选择星期数和年份,并从星期开始点获取相应的日期。 基本测试方案 您可以看到,我将通缉年份设置为2015,将通缉周设置为15,但是得到的结果是:“ 2014-12-31 23:00:00 +0000” …那真的让我垂涎三尺。无论我选择哪个星期和一年,它总是会在12月关闭。 预先感谢您的帮助。 问题答案: 与以下产品配合使用: 更新 斯威夫特3

  • 我有一个String日期,格式如下 我想将此字符串转换为以下格式的日期,以便在下面的Sqlite db查询中使用它 但是date是以下格式返回日期