簡體   English   中英

在Java中將unix時間戳轉換為等效於postgres的時間戳

[英]convert a unix timestamp to a postgres equivalent timestamp in java

我在postgres有一個領域

Column     |            Type          
created_at    | timestamp without time zone 

我有一個長時間存儲在Java中的Unix時間戳

long createdAtTime = data.getcreatedAtTime();

我想將其轉換為java中的時間戳,以便可以將activejdbc存儲到postgres中

我嘗試了以下

Date convertedTime = new Date(createdAtTime*1000L);
record.set("created_at", convertedTime);
record.saveIt();

但是我收到以下錯誤:

Can't infer the SQL type to use for an instance of java.util.Date. Use setObject() with an explicit Types value to specify the type to use.

我應該使用其他方式首先轉換日期嗎?

java.sql.Timestamp timestamp = new Timestamp(createdAtTime*1000L); 
record.set("created_at", convertedTime);
record.saveIt();

您嘗試使用java.sql.Date代替util。 它是SQL的本機類型。

不兼容的類型

我在postgres有一個領域……

沒有時區的時間戳…

…和…

我有一個長時間存儲在Java中的Unix時間戳

long createdAtTime = data.getcreatedAtTime();

這是一個矛盾。

SQL標准類型TIMESTAMP WITHOUT TIME ZONE故意沒有任何時區從UTC偏移的指示。 因此,這種類型並不代表那一刻,是不是在時間軸上的一個點。 此類型表示沿全球時區范圍大約26-27小時的潛在時刻。

如果要跟蹤特定時刻,請使用其他SQL標准類型TIMESTAMP WITH TIME ZONE 在Postgres中,此類型的所有值都存儲在UTC中 (偏移量為零)。 如果傳遞的值指示其他偏移量或時區,則Postgres會在存儲前將其值調整為UTC。

從Postgres中的TIMESTAMP WITH TIME ZONE類型的列中檢索值時, 總是在UTC中獲得值 不幸的是,位於您和數據庫之間的一些意圖良好的工具或驅動程序可能會決定動態地將時區應用於該值。 雖然用心良苦,但我認為這是反特征。 這種行為造成了一個時區錯覺,它存儲在數據庫中,而實際上Postgres只存儲這種類型的UTC

日期ConvertedTime =新日期(createdAtTime * 1000L);

java.util.Date類很糟糕,設計欠佳且有缺陷。 切勿使用此類及其兄弟姐妹CalendarSimpleDateFormat等。 這些都是現在的遺留物,幾年前被JSR 310中定義的現代java.time類所取代。

Instant

Instant類接管了java.util.Date 兩種類都代表UTC的時刻,盡管Instant具有比納秒更好的納秒分辨率。

UNIX時間戳記用Java長時間存儲

如果您從1970年1月的UTC 1970-01-01T00:00:00Z的紀元參考開始算起整秒,請轉換為Instant

Instant instant = Instant.ofEpochSecond( 1_539_555_140L ) ;

提示:不要養成以時間為計數點來跟蹤時間的習慣。 這是模棱兩可的(不同的系統使用不同的分辨率和不同的紀元引用),容易出錯,並使調試/日志記錄變得混亂。 使用java.time對象和標准ISO 8601字符串表示日期時間值。

您的JDBC驅動程序可能可以接受Instant

myPreparedStatement.setObject( … , instant ) ;

恢復:

Instant instant = myResultSet.getObject( … , Instant.class ) ;

OffsetDateTime

如果不支持Instant ,請使用convert到OffsetDateTime 需要任何JDBC 4.2或更高版本的驅動程序來支持OffsetDateTime

OffsetDateTime代表具有與UTC的偏移量的日期和時間。 相反, Instant固定在UTC,在java.time框架中用作基本的構建模塊類。 此外, OffsetDateTime具有更靈活的功能,例如與僅使用標准ISO 8601格式的Instant相比,生成各種格式的字符串。

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

恢復:

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

…要么…

Instant instant = myResultSet.getObject( … , OffsetDateTime.class ).toInstant() ;

LocalDateTime

如果您打算表示時刻,例如數據庫類型TIMESTAMP WITHOUT TIME ZONE ,請使用LocalDateTime類。

但是,如果您認為使用這些類型在某種程度上避免了在跟蹤時刻中使用時區的工作,那么您會感到非常誤解。 這是“現在付款或以后付款”的情況:要么現在學習基本的日期時間概念和處理實踐,要么稍后拼命地與失敗數據的可怕混亂打交道。


關於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 ,和更多

我看到您的“數據庫”列將值存儲為沒有時區的時間戳,為什么不嘗試此操作

Timestamp current = Timestamp.from(Instant.now());
record.set("created_at", current);//I don't know if you might need to parse
record.saveIt();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM