给定一个位置的经度和纬度,如何知道该位置的有效时区?
在大多数情况下,我们正在寻找IANA/Olson时区id,尽管有些服务可能只返回UTC偏移量或其他一些时区标识符。详细信息请阅读时区标签信息。
给定一个位置的经度和纬度,如何知道该位置的有效时区?
在大多数情况下,我们正在寻找IANA/Olson时区id,尽管有些服务可能只返回UTC偏移量或其他一些时区标识符。详细信息请阅读时区标签信息。
当前回答
https://en.wikipedia.org/wiki/Great-circle_distance
下面是一个使用JSON数据的很好的实现: https://github.com/agap/llttz
public TimeZone nearestTimeZone(Location node) {
double bestDistance = Double.MAX_VALUE;
Location bestGuess = timeZones.get(0);
for (Location current : timeZones.subList(1, timeZones.size())) {
double newDistance = distanceInKilometers(node, current);
if (newDistance < bestDistance) {
bestDistance = newDistance;
bestGuess = current;
}
}
return java.util.TimeZone.getTimeZone(bestGuess.getZone());
}
protected double distanceInKilometers(final double latFrom, final double lonFrom, final double latTo, final double lonTo) {
final double meridianLength = 111.1;
return meridianLength * centralAngle(latFrom, lonFrom, latTo, lonTo);
}
protected double centralAngle(final Location from, final Location to) {
return centralAngle(from.getLatitude(), from.getLongitude(), to.getLatitude(), to.getLongitude());
}
protected double centralAngle(final double latFrom, final double lonFrom, final double latTo, final double lonTo) {
final double latFromRad = toRadians(latFrom),
lonFromRad = toRadians(lonFrom),
latToRad = toRadians(latTo),
lonToRad = toRadians(lonTo);
final double centralAngle = toDegrees(acos(sin(latFromRad) * sin(latToRad) + cos(latFromRad) * cos(latToRad) * cos(lonToRad - lonFromRad)));
return centralAngle <= 180.0 ? centralAngle : (360.0 - centralAngle);
}
protected double distanceInKilometers(final Location from, final Location to) {
return distanceInKilometers(from.getLatitude(), from.getLongitude(), to.getLatitude(), to.getLongitude());
}
}
其他回答
通过使用纬度和经度得到当前位置下面的时区代码为我工作
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×tamp=1331161200";
// timezoneurl = timezoneurl+"location="+lat+","+lng+"×tamp=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();
}
时区位置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中可以找到的位置。蓝点表示我们试图为其寻找时区的位置。显然,这个位置位于左侧的橙色区域内,但如果我们只看距离参考点最近的距离,它将解析为右侧的绿色区域。
你可以使用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
}
https://en.wikipedia.org/wiki/Great-circle_distance
下面是一个使用JSON数据的很好的实现: https://github.com/agap/llttz
public TimeZone nearestTimeZone(Location node) {
double bestDistance = Double.MAX_VALUE;
Location bestGuess = timeZones.get(0);
for (Location current : timeZones.subList(1, timeZones.size())) {
double newDistance = distanceInKilometers(node, current);
if (newDistance < bestDistance) {
bestDistance = newDistance;
bestGuess = current;
}
}
return java.util.TimeZone.getTimeZone(bestGuess.getZone());
}
protected double distanceInKilometers(final double latFrom, final double lonFrom, final double latTo, final double lonTo) {
final double meridianLength = 111.1;
return meridianLength * centralAngle(latFrom, lonFrom, latTo, lonTo);
}
protected double centralAngle(final Location from, final Location to) {
return centralAngle(from.getLatitude(), from.getLongitude(), to.getLatitude(), to.getLongitude());
}
protected double centralAngle(final double latFrom, final double lonFrom, final double latTo, final double lonTo) {
final double latFromRad = toRadians(latFrom),
lonFromRad = toRadians(lonFrom),
latToRad = toRadians(latTo),
lonToRad = toRadians(lonTo);
final double centralAngle = toDegrees(acos(sin(latFromRad) * sin(latToRad) + cos(latFromRad) * cos(latToRad) * cos(lonToRad - lonFromRad)));
return centralAngle <= 180.0 ? centralAngle : (360.0 - centralAngle);
}
protected double distanceInKilometers(final Location from, final Location to) {
return distanceInKilometers(from.getLatitude(), from.getLongitude(), to.getLatitude(), to.getLongitude());
}
}
下面是如何使用谷歌的脚本编辑器来获取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 + '×tamp=1331161200&key=' + apiKey
var response = UrlFetchApp.fetch(url);
var data = JSON.parse(response.getContentText());
return data["timeZoneName"];
}
步骤3。保存并发布getTimezone()函数,并如上图所示使用它。