zoukankan      html  css  js  c++  java
  • 自動判斷時區(TimeZone)與時間轉換之IP address database

    前些日子,一個專案因為使用者分散在不同的國家中,所以有一個需求是必需要自動判斷使用者所在的時區,將時間轉換成當地時間,有找到幾個方案,其中使用IP address database是比較簡單的,有很多公司有推出IP對應的國家、地區、時區,大部分都要錢,不然就是免費版本的資料量不多,當好有找到一家完全免費的IpInfoDB,本篇分享如何用此資料庫完成時區轉換。

    新增資料庫

     image

    網址:http://ipinfodb.com/

    資料庫下載頁:http://ipinfodb.com/ip_database.php

    image

    有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.第一行是資料欄。

      image

    匯入時預設的格式為String,有三個資料欄一定要轉換,不然計算會出錯。

    • ip_group_city.csv的ip_start(bigint)。
    • timezones.csv的start(bigint)gmtoff(int)

    注:因為ip_start是無符號int,MS SQL沒有這種格式,所以用bigint。

    image

    資料格式說明

    ip_group_city

    image

    ip_start ip的Int格式,你可以打開小算盤(Win7),來算一下值是什麼意思了。

    image 

    latitude、longitude是經緯度。

    查詢時只要取出比目前IP大的第一筆就可以了,SQL如下

    SELECT TOP 1 * FROM ip_group_city where ip_start <= 1249717604 order by ip_start desc

     

    fips_regions.csv

     image
    從ip_group_city資料表可以取得Country_Code與Region_Code就可以判斷出timezone。
     
     

    timezones_data.csv

    image
    start與gmtoff 的大小是秒數,start是MySql的格式,以1970/1/1時為基準,可以用下列SQL取得正確時間。
    select dateadd(SS,339102000,'1970/1/1') --1980-09-29 19:00:00.000
    abbreviation指是是時間格式
    • CST Central Standard Time - 美國中部標準時間
    • Central Daylight Time - 美國夏令時間,要有加減一小時,還沒完全搞懂,所以此範例沒有判斷此。

    Select取start最大的一筆就可以了。

    範例

    image

    這是一個IP的測試範例,包含了受測IP、所在地、時區等資訊。

    1.首先要取得IP

    string ip;
    if (string.IsNullOrEmpty(this.Request.QueryString["ip"]))
    {
    ip = this.Request.UserHostAddress;//UserHostAddress可以取得用戶IP
    }
    else
    {
    ip = this.Request.QueryString["ip"];//如果有參數使用參數
    }
     
    2.將IP轉成uint
    string[] temp = ip.Split('.');
    //ip沒有正負號,所以用uint
    uint ipInt = (uint.Parse(temp[0]) << 24) + (uint.Parse(temp[1]) << 16) + (uint.Parse(temp[2]) << 8) + uint.Parse(temp[3]);
    3.取得資訊
    //使用Linq取得資訊。
    IPInfoDataContext ipInfo = new IPInfoDataContext();

    //城市資訊
    var city = ipInfo.ip_group_cities
    .Where(x => x.ip_start >= ipInt)
    .OrderBy(x => x.ip_start)
    .First();

    //區域資訊
    var region = ipInfo.fips_regions
    .Where(x => x.country_code == city.country_code && x.code == city.region_code)
    .First();

    //時區名稱
    var timezone = ipInfo.timezones
    .Where(x => x.id == region.timezone)
    .First();

    //時區資料
    var timezoneData = ipInfo.timezones_datas
    .Where(x => x.timezone == region.timezone)
    .OrderByDescending(x => x.start)
    .First();

    4.顯示資訊

    this.ZoneLabel.InnerText = timezone.name;
    this.LocalLabel.InnerText = string.Format("{0}({1})", city.region_name, city.country_name); ;
    this.OffsetLabel.InnerText = (timezoneData.gmtoff / 3600).ToString();
    this.LocalTimeLabel.InnerText = DateTime.UtcNow.AddSeconds((double)timezoneData.gmtoff).ToString();
    this.Map.Attributes.Add("src", string.Format("http://maps.google.com.tw/maps?f=q&source=s_q&q={0}+{1}&z=7&output=embed", city.latitude, city.longitude));

      

    結語

    使用這個方案,有幾個缺點就是

  • 相关阅读:
    springboot与docker
    Docker入门笔记(Centos7)
    记录VUE-CLI项目创建及初始化相关
    centos下安装mysql5.6
    GitLab权限介绍
    属性文件操作之Properties与ResourceBundle
    Shell入门基础
    JavaScript基础的记录
    Java基本排序算法
    解读闭包,这次从ECMAScript词法环境,执行上下文说起
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1763560.html
Copyright © 2011-2022 走看看