给定一个位置的经度和纬度,如何知道该位置的有效时区?

在大多数情况下,我们正在寻找IANA/Olson时区id,尽管有些服务可能只返回UTC偏移量或其他一些时区标识符。详细信息请阅读时区标签信息。


当前回答

如果你不想使用web服务,你可以像这样从浏览器中检索信息:

var d = new Date();
var usertime = d.toLocaleString();

//some browsers / OSs provide the timezone name in their local string
var tzsregex = /\b(ACDT|ACST|ACT|ADT|AEDT|AEST|AFT|AKDT|AKST|AMST|AMT|ART|AST|AWDT|AWST|AZOST|AZT|BDT|BIOT|BIT|BOT|BRT|BST|BTT|CAT|CCT|CDT|CEDT|CEST|CET|CHADT|CHAST|CIST|CKT|CLST|CLT|COST|COT|CST|CT|CVT|CXT|CHST|DFT|EAST|EAT|ECT|EDT|EEDT|EEST|EET|EST|FJT|FKST|FKT|GALT|GET|GFT|GILT|GIT|GMT|GST|GYT|HADT|HAEC|HAST|HKT|HMT|HST|ICT|IDT|IRKT|IRST|IST|JST|KRAT|KST|LHST|LINT|MART|MAGT|MDT|MET|MEST|MIT|MSD|MSK|MST|MUT|MYT|NDT|NFT|NPT|NST|NT|NZDT|NZST|OMST|PDT|PETT|PHOT|PKT|PST|RET|SAMT|SAST|SBT|SCT|SGT|SLT|SST|TAHT|THA|UYST|UYT|VET|VLAT|WAT|WEDT|WEST|WET|WST|YAKT|YEKT)\b/gi;

//in other browsers the timezone needs to be estimated based on the offset
var timezonenames = {"UTC+0":"GMT","UTC+1":"CET","UTC+2":"EET","UTC+3":"EEDT","UTC+3.5":"IRST","UTC+4":"MSD","UTC+4.5":"AFT","UTC+5":"PKT","UTC+5.5":"IST","UTC+6":"BST","UTC+6.5":"MST","UTC+7":"THA","UTC+8":"AWST","UTC+9":"AWDT","UTC+9.5":"ACST","UTC+10":"AEST","UTC+10.5":"ACDT","UTC+11":"AEDT","UTC+11.5":"NFT","UTC+12":"NZST","UTC-1":"AZOST","UTC-2":"GST","UTC-3":"BRT","UTC-3.5":"NST","UTC-4":"CLT","UTC-4.5":"VET","UTC-5":"EST","UTC-6":"CST","UTC-7":"MST","UTC-8":"PST","UTC-9":"AKST","UTC-9.5":"MIT","UTC-10":"HST","UTC-11":"SST","UTC-12":"BIT"};

var timezone = usertime.match(tzsregex);
if (timezone) {
    timezone = timezone[timezone.length-1];
} else {
    var offset = -1*d.getTimezoneOffset()/60;
    offset = "UTC" + (offset >= 0 ? "+" + offset : offset);
    timezone = timezonenames[offset];
}

//there are 3 variables can use to see the timezone
// usertime - full date
// offset - UTC offset time
// timezone - country

console.log('Full Date: ' + usertime);
console.log('UTC Offset: ' + offset);
console.log('Country Code Timezone: ' + timezone);

在我目前的情况下,它是打印:

日期:“27”/“01”/“2014”:“16”:“53”:“37” UTC偏移量:UTC-3 国家代码时区:BRT

希望对大家有所帮助。

其他回答

node.js的这个解决方案怎么样 https://github.com/mattbornski/tzwhere

和它的Python对等体: https://github.com/pegler/pytzwhere

你可以使用geolocator.js轻松获得时区和更多…

它使用需要密钥的谷歌api。首先你配置geolocator

geolocator.config({
    language: "en",
    google: {
        version: "3",
        key: "YOUR-GOOGLE-API-KEY"
    }
});

获取TimeZone,如果你有坐标:

geolocator.getTimeZone(options, function (err, timezone) {
    console.log(err || timezone);
});

示例输出:

{
    id: "Europe/Paris",
    name: "Central European Standard Time",
    abbr: "CEST",
    dstOffset: 0,
    rawOffset: 3600,
    timestamp: 1455733120
}

定位,然后获得时区和更多

如果没有坐标,可以先定位用户位置。

下面的例子将首先尝试HTML5 Geolocation API来获取坐标。如果失败或被拒绝,它将通过Geo-IP查找获得坐标。最后,它将获得时区和更多…

var options = {
    enableHighAccuracy: true,
    timeout: 6000,
    maximumAge: 0,
    desiredAccuracy: 30,
    fallbackToIP: true, // if HTML5 fails or rejected
    addressLookup: true, // this will get full address information
    timezone: true,
    map: "my-map" // this will even create a map for you
};
geolocator.locate(options, function (err, location) {
    console.log(err || location);
});

示例输出:

{
    coords: {
        latitude: 37.4224764,
        longitude: -122.0842499,
        accuracy: 30,
        altitude: null,
        altitudeAccuracy: null,
        heading: null,
        speed: null
    },
    address: {
        commonName: "",
        street: "Amphitheatre Pkwy",
        route: "Amphitheatre Pkwy",
        streetNumber: "1600",
        neighborhood: "",
        town: "",
        city: "Mountain View",
        region: "Santa Clara County",
        state: "California",
        stateCode: "CA",
        postalCode: "94043",
        country: "United States",
        countryCode: "US"
    },
    formattedAddress: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
    type: "ROOFTOP",
    placeId: "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
    timezone: {
        id: "America/Los_Angeles",
        name: "Pacific Standard Time",
        abbr: "PST",
        dstOffset: 0,
        rawOffset: -28800
    },
    flag: "//cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/flags/4x3/us.svg",
    map: {
        element: HTMLElement,
        instance: Object, // google.maps.Map
        marker: Object, // google.maps.Marker
        infoWindow: Object, // google.maps.InfoWindow
        options: Object // map options
    },
    timestamp: 1456795956380
}

下面是如何使用谷歌的脚本编辑器来获取gsheet中的timezoneName和timeZoneId。

步骤1。获取谷歌的时区API的API键

步骤2。创建一个新的gsheet。在“工具”菜单下单击“脚本编辑器”。添加如下代码:

function getTimezone(lat, long) {  
  var apiKey = 'INSERTAPIKEYHERE'
  var url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' + lat + ',' + long + '&timestamp=1331161200&key=' + apiKey 
  var response = UrlFetchApp.fetch(url);
  var data = JSON.parse(response.getContentText());
  return data["timeZoneName"];
}

步骤3。保存并发布getTimezone()函数,并如上图所示使用它。

时区位置Web服务

谷歌映射时区API 必应地图时区API Azure地图时区API GeoNames时区API TimeZoneDB API AskGeo -商业(但可以说比GeoNames更准确) 地理车库时区API -商业,专注于航海时区。

原始时区边界数据

Timezone Boundary Builder -从OpenStreetMaps地图数据中构建时区形状文件。包括海岸线附近的领海。

以下项目以前是时区边界数据的来源,但不再积极维护。

tz_world -来自Eric Muller的原始shapefile数据 whereonearth-timezone - GeoJSON版本与WOEDB数据合并

时区地理定位离线实现

使用时区边界生成器数据的实现

node-geo-tz - JavaScript library (Node.js only) timespace - JavaScript library tz-lookup-oss - JavaScript library GeoTimeZone - .NET library Geo-Timezone - PHP library timezonefinder - Python library ZoneDetect - C library Timeshape - Java library TimeZoneMap - Java and Android library lutz - R library go-tz - Go library Timezone lookup - Go library docker-timezone-lookup - docker container wrapping node-geo-tz tzf - Go library tzfpy - Python port of tzf library tzf-rs - Rust port of tzf library

使用较旧的tz_world数据的实现

latlong - Go库(也可以阅读这篇文章)。 TimeZoneMapper - Java库 tzwhere - JavaScript/节点库 pytzwhere - Python库 timezone_finder - Ruby库 LatLongToTimeZone - Java和Swift库 现在几点了?-描述PHP和MongoDB的博客文章 rundel/timezone - R库

调用其中一个web服务的库

timezone -调用GeoNames的Ruby宝石 AskGeo有自己的库,用于从Java或。net进行调用 GeoNames拥有几乎所有东西的客户端库

自托管web服务

geo2tz -基于时区查找,可通过Docker image获得

其他的想法

找到最近有R-Tree的城市 用MySQL找到最近的城市

如果您知道其他名单,请更新此名单

此外,请注意,最近的城市方法可能不会产生“正确”的结果,只是一个近似值。

转换到Windows区域

列出的大多数方法都将返回IANA时区id。如果您需要转换为Windows时区,以便与。net中的TimeZoneInfo类一起使用,请使用TimeZoneConverter库。

不要使用zone.tab

tz数据库包含一个名为zone.tab的文件。该文件主要用于显示时区列表,供用户从中选择。它包括每个时区参考点的纬度和经度坐标。这允许创建一个突出显示这些点的地图。例如,查看moment-timezone主页上显示的交互式地图。

虽然使用这些数据从纬度和经度坐标解析时区可能很诱人,但请考虑这些是点,而不是边界。最好的办法是确定最近的点,但在许多情况下,这并不是正确的点。

考虑下面的例子:

                           

这两个方格表示不同的时区,其中每个方格中的黑点是参考位置,例如在zone.tab中可以找到的位置。蓝点表示我们试图为其寻找时区的位置。显然,这个位置位于左侧的橙色区域内,但如果我们只看距离参考点最近的距离,它将解析为右侧的绿色区域。

通过使用纬度和经度得到当前位置下面的时区代码为我工作

String data = null;         
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Location ll = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
double lat = 0,lng = 0;
if(ll!=null){
    lat=ll.getLatitude();
    lng=ll.getLongitude();
}
System.out.println(" Last known location of device  == "+lat+"    "+lng);

InputStream iStream = null; 
HttpURLConnection urlConnection = null;
try{
    timezoneurl = timezoneurl+"location=22.7260783,75.8781553&timestamp=1331161200";                    
    // timezoneurl = timezoneurl+"location="+lat+","+lng+"&timestamp=1331161200";

    URL url = new URL(timezoneurl);                
    // Creating an http connection to communicate with url 
    urlConnection = (HttpURLConnection) url.openConnection(); 

    // Connecting to url 
    urlConnection.connect();                

    // Reading data from url 
    iStream = urlConnection.getInputStream();

    BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

    StringBuffer sb  = new StringBuffer();
    String line = "";
    while( ( line = br.readLine())  != null){
        sb.append(line);
    }
    data = sb.toString();
    br.close();

}catch(Exception e){
    Log.d("Exception while downloading url", e.toString());
}finally{
    try {
        iStream.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    urlConnection.disconnect();
}

try {
    if(data!=null){
        JSONObject jobj=new JSONObject(data);
        timezoneId = jobj.getString("timeZoneId");

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        format.setTimeZone(TimeZone.getTimeZone(timezoneId));

        Calendar cl = Calendar.getInstance(TimeZone.getTimeZone(timezoneId));
        System.out.println("time zone id in android ==  "+timezoneId);

        System.out.println("time zone of  device in android == "+TimeZone.getTimeZone(timezoneId));
        System.out.println("time fo device in android "+cl.getTime());
    }
} catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}