我在資料庫中有記錄,其中列 created_date 保存為沒有時區的時間戳。前端用戶位于 05.30 時區。后端托管在新加坡。因此 created_date 日期值比用戶時間晚 5.30 小時。
我如何正確選擇在給定日期內創建的一組記錄。
例如:如果用戶請求 16-oct-2021 的資料,服務器需要回傳其 created_date 在 2021-10-16 00:00:00 和 2021-10-16 23:59:59:999 之間的資料當地時間是 05.30
我有一個為此撰寫的本機查詢,如下所示,
select * from records rr where rr.created_date at time zone 'utc' at time zone 'Asia/Calcutta' between ?1 and ?2
我使用以下代碼獲取日期 1 和 2,該代碼僅在用戶時區 ( 05.30) 的凌晨 05.30 之后提供所需的資料集
Calendar startDate = (Calendar) Calendar.getInstance();
startDate.set(Calendar.HOUR_OF_DAY, 0);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
startDate.set(Calendar.MILLISECOND, 0);
Calendar endDate = (Calendar) startDate.clone();
endDate.set(Calendar.HOUR_OF_DAY, 23);
endDate.set(Calendar.MINUTE, 59);
endDate.set(Calendar.SECOND, 59);
endDate.set(Calendar.MILLISECOND, 999);
Date fromDate = startDate.getTime();
Date toDate = endDate.getTime();
因此,假設我需要在作為查詢引數傳遞之前將 startDate 和 endDate 轉換為用戶的本地時區,我執行了以下操作,
Calendar startDate = (Calendar) Calendar.getInstance();
startDate.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta")); // convert from server timezone to user's local timezone
startDate.set(Calendar.HOUR_OF_DAY, 0);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
startDate.set(Calendar.MILLISECOND, 0);
Calendar endDate = (Calendar) startDate.clone();
endDate.set(Calendar.HOUR_OF_DAY, 23);
endDate.set(Calendar.MINUTE, 59);
endDate.set(Calendar.SECOND, 59);
endDate.set(Calendar.MILLISECOND, 999);
Date fromDate = startDate.getTime();
Date toDate = endDate.getTime();
這仍然沒有回傳正確的資料集。如果我直接在 pgadmin 上運行以下查詢,我可以獲得結果
select * from records rr where rr.created_date at time zone 'utc' at time zone 'Asia/Calcutta' between '2021-10-16 00:00:00' and '2021-10-16 23:59:59'
如何使用我的代碼獲取相同的資料集?任何幫助將非常感激。TIA
uj5u.com熱心網友回復:
你說:
列 created_date 保存為沒有時區的時間戳
這是記錄時刻的錯誤資料型別。時間軸上的特定點必須寫入該型別的列TIMESTAMP WITH TIME ZONE,而不是WITHOUT。
Postgres 使用隨任何輸入提供的 UTC 偏移量或時區資訊來調整為 UTC。TIMESTAMP WITH TIME ZONEPostgres 中列中的值始終采用 UTC,始終。
你說:
在 pgadmin 上運行以下查詢
不幸的是,包括 pgAdmin 在內的許多工具都具有反功能,它們應用一些默認時區來調整從資料庫中檢索到的值。這給出了值已存盤在特定時區的錯誤錯覺。但正如我所說,TIMESTAMP WITH TIME ZONEPostgres 中列中的值始終采用 UTC,始終如此。我建議始終將 pgAdmin 會話默認時區設定為 UTC。
永遠不要使用Calendar或Date。僅在 JDBC 4.2 或更高版本中使用java.time類。
時區Asia/Calcutta已重命名為Asia/Kolkata。
如果你想要像現代印度那樣一天的開始和結束????:
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
LocalDate today = LocalDate.now( z ) ;
ZonedDateTime start = today.atStartOfDay( z ) ;
ZonedDateTime end = today.plusDays( 1 ).atStartOfDay( z ) ;
我們使用半開放方法來定義時間跨度,通常最適合日期時間作業。
OffsetDateTime在傳遞給您的PreparedStatement,之前轉換為,以使用適合 SQL 的資料型別。
OffsetDateTime startOdt = start.toOffsetDateTime() ;
你寫了:
Calendar startDate = (Calendar) Calendar.getInstance();
無需在這里投射。該方法已經回傳一個Calendar物件,因此強制轉換毫無意義。(而且,永遠不要使用Calendar。)
我在這里已經很簡短了,因為這個話題已經在 Stack Overflow 上多次討論過了。搜索以了解更多資訊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/337010.html
標籤:爪哇 春天 PostgreSQL 弹簧靴 休眠
