簡體   English   中英

Postgresql:將日期字符串'2016-01-01 00:00:00'轉換為具有特定時區的日期時間

[英]Postgresql: Convert a date string '2016-01-01 00:00:00' to a datetime with specific timezone

我的處境很棘手。 客戶端的數據庫時區已配置為America / Chicago而非UTC。

在該應用中,我們要求客戶輸入有用的日期,而遺憾的是這些日期是“按原樣”存儲的,因此,如果他們在文本輸入中輸入“ 2001-01-01 00:00:00”,則該值將為存儲在數據庫中,而我們忽略了客戶的時區。 我們單獨保存該信息。

表列的類型為TIMEZONETZ。 所以Postgresql會在最后添加美國/芝加哥時區偏移:例如'2001-01-01 00:00:00-02'。 當然,大多數客戶都不在芝加哥。

困難的部分是,即使知道客戶的時區,也很難在數據庫上運行計算,因為日期時間在存儲到數據庫之前沒有經過正確的預處理。

我嘗試的解決方案是找到一種從列值中提取日期時間字符串的方法,並將其重新轉換為具有正確時區的日期。 例如(偽代碼):

// This is psuedo code
SELECT DATETIME((SELECT date_string(mycolumn) FROM mytable),  
TIMEZONE('America/Managua'));

Which would be equivalent in PHP:
$customerInput = '2016-01-01 00:00:00';
$format = 'Y-m-d H:i:s';
$wrongDateStoredInDb = DateTime::createFromFormat($format, $customerInput, new DateTimezone('America/Chicago'));

// In order to fix that date, I'd extract the dateString and create a new DateTime but passing the correct timezone info.

$customerTimezone = new Timezone('America/Bogota');
$customerInput = $wrongDateStoredInDb->format($format); // Assuming we didn't have it already.
$actualDateTime = DateTime::createFromFormat($format, $customerInput, $customerTimezone);

有了這種信息,我就可以使用正確的值在日期范圍上運行計算,例如:

// Pseudo-code
SELECT * FROM myTable WHERE fix_date_time(columnWithInvalidDate, `correctTimezone`)::timestamp > `sometimestamp`;

我已經閱讀了Postgresql文檔,並且嘗試了所有可能的方法,但是似乎沒有任何效果。

任何建議都值得歡迎!

因此,您說您有一個timestamptz列。 那不是存儲為字符串,而是存儲為自該紀元以來的“即時”。 但是,當您執行INSERT並提供一個字符串時,Postgres會在存儲之前將其自動轉換為時間值。 一直假設您提供的字符串是在芝加哥時間,因為這是默認時區。

現在,您想將這些時間重新解釋為位於用戶所在的時區中。 為此,您可以將它們放回字符串中(在芝加哥時間),然后再次以不同的時區對其進行解析。

假設你有這樣的數據:

CREATE TABLE t (id int primary key, ts timestamptz, tz text);

SET TIMEZONE='America/Chicago';
INSERT INTO t
VALUES
(1, '2015-01-01 12:00:00', 'America/Managua'),
(2, '2015-01-01 12:00:00', 'America/Los_Angeles')
;

然后,這將為您提供用戶真正含義的新時代:

SET TIMEZONE='America/Chicago';
SELECT  ts::text::timestamp AT TIME ZONE tz FROM t;

要打破它: ts::text將值字符串化為芝加哥時間,然后我們重新解析它,但是進入一個沒有時區信息的裸timestamp 然后,我們附加一個時區-不是芝加哥時間,而是用戶自己的時區。

從這里你應該能夠處理修復壞行(而不是新行,如果你已經改變了服務器的默認時區)。

需要注意的是,如果用戶輸入時間然后更改了他們的時區,則無法恢復時區,因此這將錯誤地解釋舊時間。

暫無
暫無

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

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