首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure:为JDBC创建日期时间对象

Clojure:为JDBC创建日期时间对象
EN

Stack Overflow用户
提问于 2019-12-25 21:40:16
回答 1查看 748关注 0票数 0

我用一个列创建了我的PostgreSQL表:

代码语言:javascript
复制
  updated_at timestamp(0) with time zone 

我正在使用clojure.java-time,但是我不能创建一个字符串(或者应该是一个对象?)若要设置当前日期时间,请执行以下操作。我试过:

代码语言:javascript
复制
 (time/format "yyyy-MM-dd HH:ss" (time/local-date-time))    

用那根绳子我试过:

代码语言:javascript
复制
(db/update-answer! {:updated_at "2019-12-25 14:08", :id 102, :answer "Foo"} 

但是JDBC告诉我"updated_at“字段没有有效的类型。据我所知,JDBC仍然使用旧的java来处理日期和时区,而不是JDK 8中的新的。因此,总之,我不知道如何使用clojure.java-time为Postgresql时间戳列创建有效的字符串或对象。

有人建议我扩展JDBC协议,我正在阅读它,但现在我只是在寻找一种方法来创建一个有效的对象并完成这个更新。

更新

在遵循此页之后,我可以将格式提供给Instant:

代码语言:javascript
复制
(ns zentaur.hiccup.helpers-view
  (:require [clojure.tools.logging :as log]
        [java-time :as jt])
 (:import [java.time ZoneId]))

(defn format-date [date]
 (log/info (str ">>> DATE >>>>> " date "und type >>> " (type date)))
 (jt/format "yyyy-MM-dd HH:mm" (.atZone date  (ZoneId/systemDefault))))
EN

回答 1

Stack Overflow用户

发布于 2019-12-26 05:38:03

(Java语法,而不是Clojure)

tl;dr

使用对象,而不是字符串。在Java中使用java.time类,而不是遗留的日期-时间类。

代码语言:javascript
复制
myPreparedStatement
.setObject(
    … , 
    OffsetDateTime.now()
)

更好的做法是使用触发器自动完成此操作。

总之,我不知道如何创建…使用clojure.java-time对Postgresql时间戳列有效的对象。

调用OffsetDateTime.now()以获得保存当前时刻的java.time.OffsetDateTime对象。

使用类型的数据库列,而不是TIMESTAMP (TIMESTAMP WITHOUT TIME ZONE的缩写)。

矩量

设置当前日期-时间。

如果要跟踪时间线上的特定点和时刻,则使用错误的数据类型。

您使用的是TIMESTAMP,它是TIMESTAMP WITHOUT TIME ZONE的缩写。这种类型缺乏时区概念或与世界协调时相抵消的概念.所以这种类型无法追踪瞬间。我建议您今后避免使用此类型名称的短版本,以使您的SQL更加清晰。见Postgres医生

您应该将您的列定义为TIMESTAMP WITH TIME ZONE。Postgres通过保存UTC中所看到的时刻来处理这种类型。输入中提供的任何时区或偏移量都用于调整以适应UTC。同样,当检索到时,您的值总是以UTC为单位,偏移量为零小时-分钟-秒。

要小心将某些时区动态应用于检索值的中间件和工具。这种云很重要,造成了价值存储在那个时区的错觉。该值实际上存储在UTC中,总是存储在Postgres中的UTC中。

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

但是我不能创建一个字符串(或者应该是一个对象?)若要设置当前日期时间,请执行以下操作。

别。

您应该在Java和Postgres之间交换对象,而不仅仅是字符串。这避免了上面提到的时区注入问题.

从JDBC4.2开始,您可以与数据库交换现代java.time对象。永远不要使用遗留类型,如CalendarGregorianCalendarjava.util.Datejava.sql.Datejava.sql.Timestamp等等。这些类存在严重的缺陷,是由不懂日期时间处理的人设计的。他们在采用JSR 310时就被取代了。

将当前时刻捕获为OffsetDateTime。您的JDBC驱动程序可能支持Instant & ZonedDateTime,但这些类型是可选的,如上面的图表所示。相反,JDBC需要对OffsetDateTime的支持。

代码语言:javascript
复制
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

在上面的代码中明确使用ZoneOffset.UTC并不是严格要求的。如果省略,JVM当前的默认偏移量将被隐式应用。您的JDBC驱动程序和/或Postgres将像前面所讨论的那样适应UTC。为了调试/日志记录,我自己的首选是指定UTC,这样我就可以看到值,因为它最终将存储在数据库中。

以及检索。

代码语言:javascript
复制
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

默认值

如果您只是在每次更新行时记录该时刻,则不需要在SQL中这样做。我建议您在更新表中的行时编写一个要调用的触发器。然后,无论更新行的机制如何,都保证将写入该值。在编写SQL语句时,不必担心。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59482025

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档