2016-03-03 137 views
0

我有一個問題讓我的頭根據日期(沒有時間)存儲和檢索信息並處理多個時區。處理時區和日期

默認情況下,我的應用程序使用UTC,因此創建/更新時間都是UTC,PHP等函數都使用UTC。

我的問題是這樣的:

我允許用戶創建一條新聞,新聞項目有一個日期(沒有時間,只是日期)。

應用程序使用UTC,我的用戶是在悉尼,所以我要做的就是加載窗體時我預填充基礎的jS M Y澳大利亞/悉尼時區的日期字段,這樣它顯示爲今天他。迄今爲止都很好。

當我將記錄保存到數據庫(進入日期字段)時,我使用他們輸入的日期,所以如果他們說2016年3月3日,那麼它會在2016-03-03進入。

當它被再次拉出時,它對它們顯示正常,但是如果我做了一個報告「今天發佈了多少新聞項目?」,在我的報告(cron作業)中它可能正在尋找不同的日期,因爲如果這個人在清晨進入,那麼悉尼2016年3月3日仍然是UTC的2016年3月2日,因此今天會有0。

它出現的解決方案是將日期轉換爲UTC時的日期,但它將如何工作?..因爲它只是一個沒有時間的日期。

2016年3月2日00:00:00 UTC將是2016年3月2日10:00:00悉尼

所以..我不知道如何解決這個他們無需同時輸入一個時間,這似乎多餘的。

回答

0

請務必記住,各國之間的儲蓄時間規則各不相同,例如美國和歐盟。不僅僅是當時鍾改變時,而是跨時區變化的時間。

在過去我強制當地時間12:00(中午)。使用時間值可以使用標準轉換例程。選擇中午讓任何事情遠離任何午夜和儲蓄時間問題,因爲任何一個小時的差錯將仍然在同一天。

0

最簡單的方法是始終使用全面UTC時間戳進行操作。

將傳入的日期直接轉換爲這些,並且只在渲染時轉換回可讀的本地化格式。

這樣你就有一個單一的實體參考點。數據庫中的所有內容都在創建時精確記錄(相對於1970年1月1日 - UTC)。

然後,按照創建的順序排列文章(無論他們的作者發佈在哪裏)變得微不足道。計算在過去24小時內或在特定日期(例如:七天前)添加了多少文章也很容易 - 請注意這些示例不需要日期,只需幾秒鐘。

當「用戶B」添加相對於用戶A的時區的文章時,這還可以很容易地顯示「用戶A」 - 您無需查找用戶B的時區進行轉換。

另外,給你的用戶選擇添加時間到他們的文章,但不要強制它。有一個明智的默認(理想情況下是一個動態的「現在」)。這是更自然的,並應建立報告時,消除吉爾伯特強調的午夜和DST異常。

+0

請小心絕對。任何時候你發現自己說*總是*,記住總有*規則的例外。在這種情況下,「始終使用UTC」的建議已經在互聯網周圍傳播得如此之多以至於人們盲目追蹤並經常遇到陷阱。確實存在UTC以外的時間更適合(或甚至需要)的情況。一個很好的例子是[* scheduling *](http://stackoverflow.com/a/19627330/634824)。你的其他觀點是有效的 - 但請注意這一點。謝謝。 –

+0

謝謝馬特。在任何情況下,我都遇到過多個時區是一個因素,UTC和時間戳是一個很好的方法,節省了很多痛苦。但是,我完全同意你的意思。 – CoderCreative

+0

@CoderCreative當用戶在日曆上選擇2016年3月3日時,您會如何建議我將其轉換爲UTC時間戳?如果他們從一個月前選擇了一個數據,例如2016年2月14日,那麼該數據會變得微不足道。當您包含時間時,它會變得微不足道...... – Wizzard

0

它實際上聽起來像你正在做的事情已經正確。

「今日」和「日期」的概念是壓延概念,涵蓋的域爲民事時間。您可以使用打印的日曆在世界各地飛行,而且您無需爲UTC或時區調整它。日期本身不能以「UTC」。

但是,您可以說在的絕對時間的域中,時區A中的日期不涵蓋時區B覆蓋的相同瞬時時刻。在任何給定時間,都可以是地球上兩種不同的「今天」。

從悉尼用戶的角度來看,3月3日是發佈日期。您可能會在3月2日同時在夏威夷發佈另一位用戶。

當然,您的發佈日期是該項目發佈的民事日期。當您查詢「今天」發佈的所有商品時,這是基於您詢問時所在的公民日期。

如果這不是所需的行爲,那麼更改問題。不要問「今天發佈了什麼」,而是問「過去24小時內發佈了什麼?」爲此,您確實需要存儲完整的基於UTC的日期和時間(不僅僅是日期)。然後你可以從現在的24小時以UTC時間查詢它。

一個有助於的思維練習:如果用戶在UTC時間23:59發帖並且一分鐘後運行查詢,應該怎麼做?它是否應該包括結果 - 或者不?如果當地時間是23:59,您的答案是否會更改,並且您在一分鐘後在同一時區運行查詢?仔細考慮這一點將有助於您確定實際存儲和查詢的內容。

我還會說,在大多數情況下,您確實應該存儲基於UTC的時間戳,但您也可能想要將本地日期(或日期時間)存儲在單獨的字段中。這使您可以執行這兩種查詢。