java sql date timetl;博士java.time关于 java.time

2022-09-03 04:39:30

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

但是我把对象做成这样:Date2007-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());

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


答案 1

java.sql.Date表示日期,而不是日期和时间。从文档中

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

如果要存储日期和时间,则应查找另一种类型 - 例如java.sql.Timestamp。编辑:这并不意味着你使用TIMESTAMP列类型 - 正如paulsm4在评论中所说的那样,这是另一回事。但是,据我所知,JDBC仅支持:

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

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

编辑:经过更多的研究,看起来你可能想使用该类型,但使用特殊的驱动程序参数 - 至少如果您使用的是Microsoft驱动程序。有关更多信息,请参阅这些有关配置 JDBC 的文档java.sql.Time


答案 2

tl;博士

您可能会感到困惑,因为不理解这是一种带有时间的日期类型,而其子类假装是仅日期类,但实际上将其时间设置为零。血腥可怕的设计。完全避免这两个类。仅使用 java.time 类。java.util.Datejava.sql.Date

对于数据库中的纯日期列,请将该列定义为 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

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

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

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

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

解析。

LocalDateTime ldt = LocalDateTime.parse( input ) ;

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

标准 SQL 确实为此类值提供了数据类型 。TIMESTAMP WITHOUT TIME ZONE

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

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

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

myPreparedStatement.setObject( … , ldt ) ;

和检索。

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

如果尝试使用仅日期值,请使用 SQL 标准类型和 Java 类。DATELocalDate

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

如何获取数据库中秒的值

不确定你所说的“秒值”是什么意思。

也许您想要从 UTC 中 1970 年第一个时刻的纪元参考中算出秒数。

long secondsSinceEpoch = ldt.toEpochSecond() ;

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

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

LocalTime lt = ldt.toLocalTime() ;

如果要将一天中的时间设置为零,则可能需要一个仅日期值。如果是这样,请将该类用于不带时间且不带时区的日期值。LocalDate

LocalDate ld = ldt.toLocalDate() :

如果您确实想要该日期的第一个时刻,请调用LocalDate::atStartOfDay

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

小心:如果您试图跟踪实际时刻,时间轴上的特定点,那么上面的所有这些代码都是错误的。搜索堆栈溢出以了解 、 和 类。搜索堆栈溢出和 dba.StackExchange.com 以了解 SQL 标准类型 。InstantZoneIdZonedDateTimeTIMESTAMP WITH TIME ZONE


关于 java.time

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

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

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

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过其他类扩展了 java.time。这个项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter