【问题标题】:Date.toString() - sql vs util datesDate.toString() - sql vs util 日期
【发布时间】:2012-01-04 18:45:34
【问题描述】:

我需要从 Date 对象中删除时间。这是我的尝试,

代码:

System.out.println("date " + dbDate);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
System.out.println("formatter.format(dbDate) " + formatter.format(dbDate));
System.out.println("final " + formatter.parse(formatter.format(dbDate)));

输出:

date 2011-12-03 23:59:59.0
formatter.format(dbDate) 2011-12-03
final Sat Dec 03 00:00:00 IST 2011

我想在2011-12-03 中显示最后的日期。但转换后toString()Date 格式不同。我错过了一些东西。请帮忙。

更新:

在我的应用程序中,我有两种不同的方法来获取dbDateEXPIRY_DATE 列的类型为 DATE

第一个查询使用dbDate = (java.util.Date) rs.getDate("EXPIRY_DATE");

对于这个dbDateSystem.out.println("date " + dbDate); 给出date 2011-12-03

第二次查询使用dbDate = rs.getTimestamp("EXPIRY_DATE");

对于这个dbDateSystem.out.println("date " + dbDate); 给出date 2011-12-03 23:59:59.0

这是我的问题。因为我认为toString() 有问题,所以我没有提到完整的问题。

解决方案:

我没有选择避免java.sql.Date,因为我的应用程序方法有多种用途。 我尝试了以下方法并成功了,

dbDate = new java.sql.Date(dbDate.getTime());

【问题讨论】:

  • 我不得不使用 java.sql.Timestamp 来获取时间。感谢您提供解决方案。

标签: java date jdbc simpledateformat


【解决方案1】:

如果您想要删除Date 对象的时间部分:

如果您只想获得一个String 表示,而没有Date 对象的时间部分:

  • 您必须使用SimpleDateFormat.format()。你不能让Date.toString() 返回一个不同的值,它总是使用那个模式。看看它的source code

【讨论】:

  • 但我认为上述格式和解析删除了时间。我唯一的问题是toString () 部分。但是关于toString() 部分的信息很有用。谢谢。
  • 确实,格式化和解析也是一种去除时间的正确方式。如果您已经以所需的格式获得了Date.toString(),我仍然不明白您为什么要使用它。要实现这一点,您始终可以继承 Date,并覆盖 toString() 以使用给定的格式。
【解决方案2】:

我需要从日期对象中删除时间

你不能。 java.util.Date 对象包含日期和时间。它的toString() 也在a fixed format 中。如果您想在没有时间的情况下将其表示给人类,那么您需要将其转换为String,就像您已经做的那样。或者,如果您打算在没有时间的情况下将其存储在数据库中(正如变量名称 dbDate 中的 db 部分所建议的那样),那么您需要将其转换为 java.sql.Date

preparedStatement.setDate(1, new java.sql.Date(dbDate.getTime()));
// ...

更新根据您的更新,ResultSet#getDate() 返回java.sql.Date 的实例,而不是java.util.Date(但它是java.util.Date 的子类,这就是不必要的演员表起作用的原因;请注意,转换与转换不同,真正的转换是new java.util.Date(dbDate.getTime()))。正如您在java.sql.DatetoString() 方法的the javadoc 中看到的,它确实是yyyy-MM-dd 格式。

因此,您的具体问题是您将java.sql.Datejava.util.Date 混淆了,并且您误解了java.util.Date 的内部工作原理并被toString() 方法误导。一切都按预期进行。

相关:

【讨论】:

  • 非常感谢 Balus 提供的宝贵信息。但我无法更改那些rs.gets,因为它们是已在很多地方使用的现有方法。所以我正在检查 utilsql 的日期转换。
  • 在模型中使用java.sql 是一种不好的做法。我不明白你为什么担心日期中的时间部分。每当您想向人们表示日期时,只需使用SimpleDateFormat 将其以所需格式 转换为String。这正是它的用途。你永远不应该使用toString() 来向人类表示日期。
  • 我明白了。但我不给 UI。我需要将其发送到不允许更改的 Web 服务方法,例如格式化和设置。这就是为什么要尝试这个。
【解决方案3】:

当你最后一次调用formatter.parse() 时,你会得到一个Date 对象;然后连接对Date.toString() 进行隐式调用:此调用返回的格式是JVM 中设置的语言环境的默认格式。 您必须了解的是Date 对象不知道字符串表示,在内部它只是 inte 的聚合

【讨论】:

    【解决方案4】:

    遇到和我相同问题的人也遇到过类似的问题,我写这篇文章:

    问题是从数据库中获取并传递给 Web 客户端的日期值格式为 yyyy-mm-dd,但在第一个条目的应用程序中没有数据库值,因此我们创建日期对象并将值传递给 Web给我们时间戳值的客户端。将传递给 Web 客户端的值必须是日期格式,所以 SimpleDateFormat 对我来说不是一个好选择 所以从这篇文章中我了解了java.sql.date 和 java.util.date 的区别,然后将第一个对象创建为

    Date date = new java.sql.Date(1430454600000L); 
    

    toString 方法提供yyyy-mm-dd 值。

    【讨论】:

      【解决方案5】:

      java.time

      Answer by BalusC 是正确的:您不能从定义为保存日期和时间的类对象中删除时间。

      此外,您正在使用麻烦的旧类(java.util.Datejava.sql.Date),它们现在已经过时,被 java.time 类所取代。

      相反,对仅日期值使用仅日期类。 LocalDate 类表示没有时间和时区的仅日期值。 java.sql.Date 假装做同样的事情,但实际上由于从java.util.Date 继承的设计决策非常糟糕,因此确实需要时间。避免使用java.sql.Date,而只使用java.time.LocalDate

      您显然是从java.util.Date 对象开始的。这表示 UTC 时间线上的一个点,分辨率以毫秒为单位。因此,使用它来确定日期需要一个时区。 LocalDate 类表示没有时间和时区的仅日期值。

      时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,Paris France 中午夜后几分钟是新的一天,而 Montréal Québec 中仍然是“昨天”。

      如果没有指定时区,JVM 会隐式应用其当前的默认时区。该默认值可能随时更改,因此您的结果可能会有所不同。最好将您想要/预期的时区明确指定为参数。

      continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

      ZoneId z = ZoneId.of( "America/Montreal" ) ;  
      

      如果你想使用 JVM 当前的默认时区,请求它并作为参数传递。如果省略,则隐式应用 JVM 的当前默认值。最好是明确的,因为默认值可能会在任何时候在运行时被 JVM 中任何应用程序的任何线程中的任何代码更改。

      ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.
      

      要从您的 java.util.Date 获取仅日期值,首先转换为它的 java.time 替换,Instant。要来回转换,请调用添加到旧类的新方法。

      Instant instant = myJavaUtilDate.toInstant() ;
      

      根据定义,该值采用 UTC。应用您想要的时区 (ZoneId) 以生成 ZonedDateTime

      ZonedDateTime zdt = instant.atZone( z ) ;
      

      最后,从ZonedDateTime 中提取您想要的LocalDate 对象。

      LocalDate ld = zdt.toLocalDate() ;
      

      从 JDBC 4.2 及更高版本开始,您可以直接与数据库交换 java.time 类。所以不需要使用java.sql 类如java.sql.Datejava.sql.Timestamp

      myPreparedStatement.setObject( … , ld ) ;
      

      检索。

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

      关于java.time

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

      Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

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

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

      从哪里获得 java.time 类?

      • Java SE 8Java SE 9 及更高版本
        • 内置。
        • 标准 Java API 的一部分,带有捆绑实现。
        • Java 9 添加了一些小功能和修复。
      • Java SE 6Java SE 7
        • 大部分 java.time 功能都在ThreeTen-Backport 中向后移植到 Java 6 和 7。
      • Android
        • java.time 类的 Android 捆绑包实现的更高版本。
        • 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…

      ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-11
        • 1970-01-01
        • 2016-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多