前言
跟異國他鄉的朋友們微信聊天的時候,經常面臨時差的問題。我每次想要確定對方現在是幾點,總是要口算一下,有時忘記具體時差,或者涉及跨天,還得打開瀏覽器查一下,很不方便。有什么方法可以把朋友們所在城市的時間集中起來隨時供自己查看呢?於是想到了微信小程序。找了找市面上的時間小程序,不是功能太雜就是小廣告太多,不滿意。
為什么不自己動手量身打造一個呢?
行動起來。
首先快速明確需求
很簡單:
- 需要展示時間的城市初定:加州、紐約,再加北京做對比
- 需要顯示具體的時分秒,和年月日
- 需要實時變化
- 在其他國家也能正確展示時間
然后創建項目開擼
怎么創建和前期的准備就不在這里展開了,相信不少人都熟悉。如果不熟悉小程序開發的可以參考官網 或者我的另一篇文章如何開發微信小程序
,上面有對如何開發小程序的簡明扼要的的介紹。
關鍵邏輯
這個小程序的核心是時間的處理。如何得到其他地區的時刻信息?
這還不簡單?
先獲取本地時刻,然后加上或者減去另外一個地點與國內(北京時間)的時差(小時),最多再處理一下跨天的情況,不就得到其他地點的時刻了?
我一開始也是這么想的,做完覺得還挺美,准備提交的時候,突然意識到問題:我時差全是基於北京時間計算的,換在其他國家訪問,獲取的本地時間已經不是北京時間了,時差應該變才對,寫死了時差可還行?!發布一個只能在國內使用的雞肋時間工具,可不是我的風格!
搗鼓一陣,新方案出爐:
- 想辦法獲得零時區的時間
- 獲取不同地區與零時區的時差(時區)
- 用零時區的時間加減與零時區的時差(時區),得到各地的絕對時間
1. 獲得零時區的時間
零時區,也叫中時區,位於英國格林威治本初子午線上。該時區的地方時,叫做格林威治時間,也叫世界時。
我們不能直接獲得格林威治時間,但是我們可以獲得本地與格林威治的時間差:
const diff = new Date().getTimezoneOffset() // 單位為分鍾
然后根據本地時間和時間差獲得格林威治時間:
const absTime = new Date().getTime() + diff * 60 * 1000;
2. 查詢各地時區
格林威治本初子午線將地球划分為東西兩個半球,格林威治本初子午線為零時區,往西依次為西一區到西十一區,往東依次為東一區到東十一區,西十二區和東十二區重合成為東西十二區,一共划分了24個時區,每個時區相差正好是1個小時。
北京是東八區,紐約是西五區,加州是西八區。
完整時區地圖:
3. 計算各地的絕對時間
東時區的時刻比零時區快,西時區的時刻比零時區慢,所以東時區為正,西時區為負,所有時間計算記得轉換為毫秒。
let localTime = new Date(absTime + timeZone * 60 * 60 * 1000);
獲取任何時區的絕對時間的完整核心代碼:
/**
* timeZone: 東n區為正,西n區為負, 單位為小時
*/
const getFullTimeInfo = (timeZone, country, spliter) => {
//獲取本地時間與格林威治時間的時間差(注意是分鍾,記得轉換)
const diff = new Date().getTimezoneOffset();
//根據本地時間和時間差獲得格林威治時間
const absTime = new Date().getTime() + diff * 60 * 1000;
//根據格林威治時間和各地時區,得到各地時區的時間
let localTime = new Date(absTime + timeZone * 60 * 60 * 1000)
return {
time: formatTime(localTime, spliter)
};
}
發布
很快,第一版就完成了。
剛開始這個樣子略丑,有點裸奔的趕腳。不過第一版最主要是核心功能,簡陋的界面只是暫時的。
給當地的朋友檢驗確定時間展示正確后,提交代碼、提交審核,2天后收到審核通過的通知(吐槽騰訊的審核效率😓),然后在小程序管理平台點擊發布,哦了。
掃描二維碼,打開小程序,然后收藏。以后要看時間了,微信主界面向下一拉,打開我的時間工具,一眼就看到想要知道的時間信息,確實比之前便捷多了。功能雖然簡單,界面雖然簡陋,但是妥妥滴滿足我的需求。
迭代
用了一陣子,覺得樣式啥的還是得豐富豐富,於是花了一些時間做了一次改版,實時時間以時鍾效果展示,並且修改了布局,順便重構了一下代碼,便於新增地區。
嗯,效果似乎還行~
改BUG
前幾天跟澳洲的朋友聊天,聊着聊着居然發現了我的程序的一個潛在BUG。
那天是4月4日的早晨(北京時間),我跟朋友吐槽我的一個疑惑:查詢悉尼時區為東十區(即與北京相差2小時),但是為啥查詢悉尼時間卻與北京相差3小時(所以我當時程序中是把悉尼作為東十一區來計算的)。朋友說:是的沒錯,我們這里現在在使用夏令時,等夏令時結束就恢復2個小時時差了。然后一查,今年澳洲夏令時將在4月5號凌晨3點結束。。。
也就是說,距離這個BUG發作還有不到一天的時間。。。
馬上打開電腦,改BUG。。。
根據資料,獲得美國和澳大利亞的夏令時規則:
-
美國
每年的3月第二個星期日02:00:00,時鍾向前調整1小時,變為03:00:00,開始夏令時。
每年的11月第一個星期日02:00:00,時鍾向后調整1小時,變為01:00:00,結束夏令時。 -
澳大利亞
每年的10月第一個星期日02:00:00,時鍾向前調整1小時,變為03:00:00,開始夏令時。
每年的4月第一個星期日03:00:00,時鍾向后調整1小時,變為02:00:00,結束夏令時。
關於夏令時,也挺有意思,有空我會另開一個篇幅來專門講述。
將夏令時的判斷邏輯加上:
/**
* timeZone: 東n區為正,西n區為負, 單位為小時
*/
const getFullTimeInfo = (timeZone, country, spliter) => {
//獲取本地時間與格林威治時間的時間差(注意是分鍾,記得轉換)
const diff = new Date().getTimezoneOffset();
//根據本地時間和時間差獲得格林威治時間
const absTime = new Date().getTime() + diff * 60 * 1000;
//根據格林威治時間和各地時區,得到各地時區的時間
let localTime = new Date(absTime + timeZone * 60 * 60 * 1000)
+ // 考慮夏令時
+ // judgeDST是我封裝好的一個判斷夏令時的方法
+ const isDST = judgeDST(localTime, country);
+ if (isDST) {
+ localTime = new Date(absTime + (timeZone + 1) * 60 * 60 * 1000)
+ }
return {
time: formatTime(localTime, spliter).split(':').slice(0,2).join(':'),
isDST
};
}
有了現在的版本:
以后對這個小工具我還會不斷優化,會越來越靈活,比如支持地區選擇,這樣每個人都可以定制自己的時差表了。可以期待一下哦~
最后附上小程序二維碼,掃一掃即可體驗。
--
還是毛爺爺說得好:自己動手豐衣足食。
Happy coding 😃
文章同時發表於公眾號「前端手札」,喜歡的話可以關注一下哦。
本文作者:ChampYin
轉載請注明出處:http://champyin.com/2020/04/08/開發一個時間小程序/