【问题标题】:java sql date timejava sql日期时间
【发布时间】:2011-12-16 06:25:44
【问题描述】:

当我将 SQL DateTime 插入数据库时​​,我得到 2007-02-07 12:00:00.00

但我制作了这样的Date 对象:2007-02-07 17:29:46.00

如何获取数据库中秒的值。它总是把它改回12:00:00.00

date.setYear(Integer.valueOf(parsedDate[2].replaceAll(" ", "")) - 1900);
date.setMonth(Integer.valueOf(parsedDate[0].replaceAll(" ", "")));
date.setDate(Integer.valueOf(parsedDate[1].replaceAll(" ", "")));
...
java.sql.Date sqlDate = new java.sql.Date(date.getTime());

我应该使用任何格式化程序吗?

【问题讨论】:

  • “日期”(代表某个时间点的数字)与其格式无关(相同数字可以表示为“2007-02-07”或“ 2007-07-02" 或 "2/7/2007"。它也与您的时区无关(相同的数字可以是洛杉矶的“2/7/2007”和伦敦的“2/8/2007”) . 最后一个“日期”(例如“2/7/2007”)与日期时间(例如“2/7/2007 09:15am”)具有不同的值。我猜你可能正在使用“日期”,您的意思是使用“日期时间”。
  • PS:java.util.date 表示“日期”或“日期时间”。 java.sql.date 只是“日期”。对于 MS Sql Server 等数据库,“日期”或“日期时间”与“时间戳”不同。 stackoverflow.com/questions/2305973/…
  • PPS:在 MS Sql Server 中(如果您正在使用),“时间戳”绝对不是日期或日期时间:sqlteam.com/article/timestamps-vs-datetime-data-types。如果您想要一个日期(无论一天中的什么时间),请将您的 SQL 列设为“日期”。如果您想要一天中的时间(与日历日期无关),请将其设为“时间”。在 NO CIRCUMSTANCES 下,使用 SQL Server“时间戳”来保存逻辑时间/日期列。
  • 那么我无法将日期和时间保存在我上面提到的同一列中 2007-02-07 17:29:46.00?我必须将它们分成两列吗?顺便说一句,我使用的是 ms sql server
  • 不!这意味着如果要保存“2007-02-07 17:29”,则应将 MSSQL 中的列定义为“日期时间”。如果您只想保存“2007-02-07”,则应将该列定义为 MSSQL“日期”。 Java 的“java.sql.Date”是仅限日期的。 Java 的“java.util.Date”同时处理日期和日期/时间。并且 MSSQL“时间戳”既不是日期也不是时间——除非你知道你需要它,否则避免使用 MSSQL 时间戳。问:您使用的是 MS Sql Server 吗?或者您使用的是不同的数据库(例如 DB2 或 MySQL)?

标签: java date jdbc


【解决方案1】:

java.sql.Date 表示日期,而不是日期和时间。来自the docs

为了符合 SQL DATE 的定义,由 java.sql.Date 实例包装的毫秒值必须通过在特定时区中将小时、分钟、秒和毫秒设置为零来进行“规范化”。实例已关联。

如果您想存储日期和时间,您应该寻找另一种类型 - 例如java.sql.Timestamp。编辑:这并不是建议您使用 TIMESTAMP 列类型 - 正如 paulsm4 在 cmets 中所说,这是另一回事。但是,据我所知,JDBC 只支持:

  • Date(不,你也想要时间)
  • Time(不,你也想要约会)
  • Timestamp(包括日期和时间,但您不需要 TIMESTAMP SQL 语义)

我会期望使用带有 DATETIME 列的 Java Timestamp 类型来工作,尽管没有 Timestamp 提供的精度级别。

编辑:经过更多研究,您似乎可能想要使用java.sql.Time 类型,但带有特殊的驱动程序参数 - 至少如果您使用的是 Microsoft 驱动程序。有关详细信息,请参阅configuring JDBC 上的这些文档。

【讨论】:

  • 那么如何到达这个日期呢?还有其他选择吗?
  • @elbek:看我的编辑 - 基本上,不要在这里使用Date,使用不同的类型。
  • 如果我做列类型时间戳我不能手动更改它?
  • 当我使用时间戳时出现此错误:无法将显式值插入时间戳列。将 INSERT 与列列表一起使用以排除时间戳列,或将 DEFAULT 插入时间戳列。
  • @elbek:“JDBC 驱动程序专为使用 SQL Server 2005 引入的功能而设计,但它向后兼容 SQL Server 2000,包括 64 位版本。JDBC 驱动程序 3.0 支持SQL Server 2008 中的新日期和时间类型、大型用户定义类型和稀疏列。” (来自 3.0 驱动程序的系统要求。)
【解决方案2】:

tl;博士

您可能会因为不理解 java.util.Date 是一个带时间的日期类型而感到困惑,而它的子类 java.sql.Date 假装是一个仅限日期的类,但实际上有它的时间-day 设置为零。该死的糟糕设计。完全避免这两个类。仅使用 java.time 类。

对于数据库中的仅日期列,将该列定义为 SQL 标准 DATE 类型。

myPreparedStatement.setObject(
    … ,
    LocalDateTime.parse( "2007-02-07 17:29:46.00".replace( " " , "T" ) )
    .toLocalDate()
)

java.time

现代方法使用添加到 Java 8 及更高版本的 java.time 类。

当我将 SQL DateTime 插入数据库时​​,我得到 2007-02-07 12:00:00.00

没有像DateTime 这样的SQL 标准类型,Java 中也没有这样的类。所以我不知道你的意图。

对于输入字符串2007-02-07 17:29:46.00,将其解析为LocalDateTime,因为它缺少任何时区指示符或与UTC 的偏移量。

SQL 风格的格式几乎符合ISO 8601 标准。要完全遵守,请将中间的空格替换为Tjava.time 类在解析/生成字符串时默认使用 ISO 8601 格式。

String input = "2007-02-07 17:29:46.00".replace( " " , "T" ) ;

解析。

LocalDateTime ldt = LocalDateTime.parse( input ) ;

LocalDateTime 是否 代表一个时刻,不是时间轴上的一个点。它代表了大约 26-27 小时范围内的潜在时刻。

标准 SQL 确实为这种值提供了一种数据类型,TIMESTAMP WITHOUT TIME ZONE

智能对象,而不是哑字符串

您的整个方法都是错误的,争论文本并使用旧的日期时间类。相反,交换 java.time 对象。

从 JDBC 4.2 开始,您不再需要使用麻烦的旧 java.sql 类型,例如 java.sql.Datejava.sql.Timestamp。您可以通过setObject/getObject 方法直接与数据库交换 java.time 对象。

myPreparedStatement.setObject( … , ldt ) ;

和检索。

LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

如果您尝试使用仅日期值,请使用 SQL 标准类型 DATE 和 Java 类 LocalDate

LocalDate ld = ldt.toLocalDate() ;
myPreparedStatement.setObject( … , ld ) ;

如何获取数据库中秒的值

不确定您所说的“秒数”是什么意思。

也许您想要从 1970 年 UTC 第一刻的 epoch reference 开始的秒数。

long secondsSinceEpoch = ldt.toEpochSecond() ;

如果您的目标只是实例化 java.sql.Date,请不要打扰。永远不要再使用那个类。但是,仅供参考,您的具体问题可能是该课程使用的糟糕设计的副作用。 java.sql.Date 类继承自 java.util.Date,它是一个带时间的日期类型。 java.sql.Date假装 是仅日期值,但实际上将其时间设置为 00:00:00。更糟糕的是,文档告诉我们忽略它是子类的事实。不要费心去理解它;只需使用 java.time 代替。

如果您尝试单独使用时间,请提取 LocalTime 对象。

LocalTime lt = ldt.toLocalTime() ;

如果您想将时间设置为零,那么您可能需要一个仅限日期的值。如果是这样,请使用 LocalDate 类作为没有时间和时区的日期值。

LocalDate ld = ldt.toLocalDate() :

如果您确实想要当天的第一刻,请致电LocalDate::atStartOfDay

LocalDateTime ldtStart = ldt.toLocalDate().atStartOfDay() ;

注意:如果您试图跟踪实际时刻,时间轴上的特定点,那么上面的所有代码都是错误的。搜索 Stack Overflow 以了解 InstantZoneIdZonedDateTime 类。搜索 Stack Overflow 和 dba.StackExchange.com 以了解 SQL 标准类型 TIMESTAMP WITH TIME ZONE


关于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 类?

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

【讨论】:

  • Re: Joda 建议迁移到java.time,这是他们今天页面上的引用:“请注意,从 Java SE 8 开始,要求用户迁移到 java .time (JSR-310) - JDK 的核心部分,它取代了这个项目。”
猜你喜欢
  • 2012-06-18
  • 1970-01-01
  • 2012-02-14
  • 2016-09-19
  • 2011-03-01
  • 2019-09-06
  • 2014-05-16
  • 2018-09-24
  • 2014-12-03
相关资源
最近更新 更多