我正在开发一个在C#/ .NET平台上发送应用程序的简报。我最近添加了模块,使用maxmind.com数据库通过IP地址检索收件人的国家和地区。
例如,我可以获得一些示例IP地址的以下信息:
Country Code: DE
Country Name: Germany
Region Name: Hessen
City: Frankfurt Am Main
Latitude: 50.1167
Longitude: 8.6833
我现在需要的是使用此信息获取用户的时区。
我知道有一些GeoIp数据库也提供了时区,但我需要使用这个具体的GeoIp数据库。此外,这里不能使用javascript确定时间偏移的方法。
可能我可以使用国家和地区名称以某种方式获得时区吗?
答案 0 :(得分:10)
最后,经过长时间的研究,我找到了解决方案。它可能不太准确,但它不需要远程服务的依赖性。
我发现maxmind的数据库提供了来自Olsen数据库(也就是tz数据库)的区域和时区之间的映射文件:http://www.maxmind.com/timezone.txt
第二步是在.NET时区中转换Olsen时区。在这里找到了最合适的解决方案:http://www.timdavis.com.au/data/olson-time-zone-database-to-standard-windows-time-zone-v01/ 所以我对它进行了一些编辑并将其转换为CSV文件以从.NET中读取它。
希望它会对某人有所帮助。
答案 1 :(得分:2)
答案 2 :(得分:1)
自问这个问题以来已经有一段时间了,但可能有助于其他人......
当您使用maxmind API中的DatabaseReader对象时,已经有一个属性location.timeZone
,您可以从GeoIP类返回的对象中检索它,从maxmind查看API docs。
答案 3 :(得分:0)
某些国家(例如俄罗斯)拥有更多的时区。
在我的解决方案中,我使用NodaTime,您可以使用maxmind中的经度信息来找到最佳匹配项。
var countryName = "Russia";
var longitude = 40.332206;
var zones = TzdbDateTimeZoneSource.Default.ZoneLocations.Where(x => x.CountryName == countryName).AsQueryable();
if (!double.IsNaN(longitude))
{
//If a longitude available use the information to order the zones by distance
zones = zones.OrderBy(o => this.Distance(o.Latitude, longitude, o.Latitude, o.Longitude, DistanceUnit.Kilometer));
}
var bestZone = zones.FirstOrDefault();
var dateTimeZone = TzdbDateTimeZoneSource.Default.ForId(bestZone.ZoneId);
var newTime = DateTime.UtcNow.AddSeconds(dateTimeZone.MaxOffset.Seconds);
计算地理坐标的距离
public enum DistanceUnit { StatuteMile, Kilometer, NauticalMile };
private double Distance(double lat1, double lon1, double lat2, double lon2, DistanceUnit unit)
{
double rlat1 = Math.PI * lat1 / 180;
double rlat2 = Math.PI * lat2 / 180;
double theta = lon1 - lon2;
double rtheta = Math.PI * theta / 180;
double dist =
Math.Sin(rlat1) * Math.Sin(rlat2) + Math.Cos(rlat1) *
Math.Cos(rlat2) * Math.Cos(rtheta);
dist = Math.Acos(dist);
dist = dist * 180 / Math.PI;
dist = dist * 60 * 1.1515;
switch (unit)
{
case DistanceUnit.Kilometer:
return dist * 1.609344;
case DistanceUnit.NauticalMile:
return dist * 0.8684;
default:
case DistanceUnit.StatuteMile:
return dist;
}
}