前些日子,一個專案因為使用者分散在不同的國家中,所以有一個需求是必需要自動判斷使用者所在的時區,將時間轉換成當地時間,有找到幾個方案,其中使用IP address database是比較簡單的,有很多公司有推出IP對應的國家、地區、時區,大部分都要錢,不然就是免費版本的資料量不多,當好有找到一家完全免費的IpInfoDB,本篇分享如何用此資料庫完成時區轉換。
資料庫下載頁:http://ipinfodb.com/ip_database.php
有City與Country二種資料庫,像台灣這小地方,不同的城市都是相同的時區,但像美國或加拿大這些地大的國家,不同的城市有不同的時區,所以如果只下載Country的資料庫,沒有辦法得知正確的時區,而他City又分Small或Complete二種,如果只是測試下載Small應該足夠,因為我覺得Select時一個table比較省事,所以我用One DataTables格式。
時區下載頁:http://ipinfodb.com/timezonedatabase.php
格式有 SQL、CSV二種,SQL是MySql的格式,不是標準的SQL,如果你的資料庫引擎不是MySql,請不要下載,而我是用MS SQL所以我下載CSV檔。
二個壓縮檔解開,裡面共有6個檔案
- ip_group_country.csv 不新增 IP對應的國家,因為City資料表就包含國家資訊了,所以用不到這個資料表。
- ip_group_city.csv 新增 IP對應的城市,包含的國家資訊與座標。
- iso3166_countries.csv 不新增 縮寫對應的國家,如TW=Taiwan,資訊在City中包含。
- fips_regions.csv 新增 Federal Information Processing Standards(聯邦資料處理標準)地區代碼,城市對應的時區。
- timezones.csv 選項 時區的名稱,如Asia/Taipei,轉換時區用不到,不過可以用來顯示資訊。
- timezones_data.csv 新增 時區對應的UTC Offset。
我是用MS SQL的Import and Export Wizard來完成資料的匯入,在匯入過程中有遇到一些小問題,各位要注意。
1.檔案的換行是{LF}。
2.文字有用雙引號"分隔。
3.第一行是資料欄。
匯入時預設的格式為String,有三個資料欄一定要轉換,不然計算會出錯。
- ip_group_city.csv的ip_start(bigint)。
- timezones.csv的start(bigint)、gmtoff(int)。
注:因為ip_start是無符號int,MS SQL沒有這種格式,所以用bigint。
資料格式說明
ip_group_city
ip_start ip的Int格式,你可以打開小算盤(Win7),來算一下值是什麼意思了。
latitude、longitude是經緯度。
查詢時只要取出比目前IP大的第一筆就可以了,SQL如下
fips_regions.csv
timezones_data.csv
- CST Central Standard Time - 美國中部標準時間
- Central Daylight Time - 美國夏令時間,要有加減一小時,還沒完全搞懂,所以此範例沒有判斷此。
Select取start最大的一筆就可以了。
範例
這是一個IP的測試範例,包含了受測IP、所在地、時區等資訊。
1.首先要取得IP
//如果有參數使用參數
}
//ip沒有正負號,所以用uint
uint ipInt = (uint.Parse(temp[0]) << 24) + (uint.Parse(temp[1]) << 16) + (uint.Parse(temp[2]) << 8) + uint.Parse(temp[3]);
//時區資料
var timezoneData = ipInfo.timezones_datas
.Where(x => x.timezone == region.timezone)
.OrderByDescending(x => x.start)
.First();
4.顯示資訊
, city.latitude, city.longitude));
結語
使用這個方案,有幾個缺點就是
- IP的地區如果變動不會知道,如果是買的,可能還有售後服務,免費的要資料是最新的可能有點難。
- VPN資料必需手動自行建立。