SimpleDateFormat 没有提供我需要的模式

SimpleDateFormat doesn't give me the pattern I need

我在使用 SimpleDateFormat 时遇到问题。我的 HTML 页面中有输入字段,类型为日期。我想将这些值保存到我的数据库中,在那里它们应该被保存为日期。我已经想出如何做到这一点并且它有效。我遇到的唯一问题是日期在数据库中的表示方式。

我希望将它们表示为 dd-MM-yyyy。假设我想将 01-06-2016 显示到我的数据库中。当使用我的代码执行此操作时……它给了我 0006-12-07。奇怪的是……当我将模式更改为 yyyy-MM-dd 时……它确实准确地给出了模式所说的内容:2016-06-01。但反过来就不行了。

String parameter = request.getParameter("instroomdatum");
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
    Date parsed = sdf.parse(parameter);
    java.sql.Date sql = new java.sql.Date(parsed.getTime());
    student.setInstroomdatum(sql);
} catch (ParseException ex) {
    Logger.getLogger(StudentController.class.getName()).log(Level.SEVERE, null, ex);
}

有人可以向我解释这是怎么回事以及如何解决这个问题吗?真烦人。

编辑: 我尝试使用简单的 PrintWriter 对象打印特定日期 01-06-2016 的参数值。它显示 2016-06-01,即使我在上面代码中的模式设置为 dd-MM-yyyy。

您混淆了显示格式与内部表示。

数据库中的日期不会以任何特定显示格式表示,例如YYYY-MM-DD。数据库日期通常以数字形式存储,表示从某个固定起点算起的一定秒数和毫秒数(或纳秒数)。

当您查询数据库并以字符串形式请求 date/time 时动态应用显示格式,但如果您以 Date 对象形式请求它,您将获得内部表示,封装在java.sql.Date中。

由您的 Java 代码根据需要格式化日期。

在您的特定示例中(根据您的评论),您的输入法返回的字符串是 2016-06-01,因此您需要使用模式 yyyy-MM-dd 来解析它。这会将外部表示正确地转换为有效的 Date 对象。

But how should i specifically change this representation to dd-MM-yyyy

一旦您将其设为 Date,您可以立即将 Date 转换回具有不同 SimpleDateFormat 规格的 String

如果您只想将日期格式化为 01-06-2016 格式。试试这个

String parameter = "0006-12-07";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
    Date parsed = sdf.parse(parameter);
    sdf = new SimpleDateFormat("dd-MM-yyyy");
    System.out.println(sdf.format(parsed)); //Prints out your desired format 07-12-0006
    java.sql.Date sql = new java.sql.Date(parsed.getTime());
    student.setInstroomdatum(sql);
} catch (ParseException ex) {
    Logger.getLogger(StudentController.class.getName()).log(Level.SEVERE,null, ex);
}
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

java.sql.Date someDate;

Date anotherDate = format.parse(/*needVariables*/.getOutDate());

someDate = new java.sql.Date(anotherDate.getTime());

为我工作

日期时间 != 字符串

中所述,您必须了解数据库内部或 Java 等语言中的日期值是不同的,与生成的用于表示或传达的字符串不同价值。

内部跟踪日期的方式因数据库和语言而异,实际上是无关紧要的。重要的是提供的接口,您可以通过该接口获取或放置应用程序的值。 另一个 问题是如何将这些值表示为字符串以呈现给您的用户。

Database (internal) ↔ Driver (JDBC) ↔ App (java.time) ↔ Presentation (String)

java.time

此外,问题和其他答案使用的是过时的旧 classes,日期时间 classes 与最早版本的 Java 捆绑在一起。 classes 已被 java.time classes built into Java 8 and later. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

取代

LocalDate

java.time class 中的 LocalDate 表示没有时间和时区的仅日期值。旧的 java.util.Date class,尽管它的名字很不幸,但它同时跟踪日期 一天中的时间。旧的 java.sql.Date 假装 表示仅日期,但实际上,在一个不幸的设计决定中,它从 java.util.Date 扩展,因此它继承了日期和时间-of-day,但 class 文档中指示您假装它不是子 class。 (是的,那是一团糟)

使用 java.time class 执行所有业务逻辑,例如 LocalDate

字符串和 ISO 8601

至于字符串,请使用标准 ISO 8601 格式。对于序列化仅限日期的值,这意味着 YYYY-MM-DD。当 parsing/generating 表示日期时间值的字符串时,java.time classes 默认使用 ISO 8601 格式。

LocalDate localDate = LocalDate.parse( "2016-06-01" );

但尽量坚持使用对象。仅在必须时序列化为字符串。

数据库

获取数据时不需要字符串 to/from 数据库。 JDBC driver 的工作是弄清楚如何移动 Java 对象 to/from 数据库列的数据类型。

使用符合 JDBC 4.2, you should be able to use the getObject and setObject methods on a PreparedStatement 的驱动程序直接处理 java.time 类型。

myPreparedStatement.setObject( 1 , localDate );

如果您的驱动程序不支持,您必须退回到 java.sql.Date class。寻找添加到旧 classes 的新方法,以便与 java.time 类型来回切换。

java.sql.Date sqlDate = java.sql.Date.valueOf( localDate );

另一个方向。

LocalDate localDate = sqlDate.toLocalDate();

生成字符串

根据需要应用一种格式来生成字符串,以便向用户展示。使用DateTimeFormatterclass。您可以定义自己的格式模式。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd-MM-yyyy" );
String output = localDate.format( formatter );  // 01-06-2016

更好的是,让 java.time 本地化到用户 desired/expected Locale 的人类语言和文化规范。

Locale locale = Locale.CANADA_FRENCH;
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT , locale );
String output = localDate.format( formatter );

您将需要使用格式化程序生成一个字符串以呈现给用户,并解析用户的输入。您或您的用户可能希望将数据输入作为三个单独的字段:年、月和月中的某天。

LocalDate localDate = LocalDate.of( 2016 , 6 , 1 );