Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get timezone by Country and Region

Tags:

timezone

c#

I'm developing an newsletter sending application on C#/.NET platform. I've recently added the module to retrieve the country and region of a recipient by his IP address using maxmind.com database.

For example, I can get the following info for some sample IP address:

Country Code: DE
Country Name: Germany   
Region Name:  Hessen 
City:         Frankfurt Am Main
Latitude:     50.1167
Longitude:    8.6833 

What I need now is to get the user's time zone using this information.

I know there are some GeoIp databases that provide also the time zone, but I need to use this concrete GeoIp database. Also, javascript's approach to determine time offset can't be used here.

May be I can get somehow the timezone using country and region name?

like image 974
VirusX Avatar asked Nov 02 '11 08:11

VirusX


1 Answers

Some countries have more as one timezone for example Russia.

In my solution i use NodaTime you can use your longitude information from maxmind to find the best match.

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);

Calculate distance of geo coordinates

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;
    }
}
like image 175
live2 Avatar answered Oct 24 '22 15:10

live2