Get timezone by Country and Region

See the following links

http://johnwsaundersiii.spaces.live.com/blog/cns!600A2BE4A82EA0A6!657.entry

How to get time zone information for country?


Finally, after long research, I've found the solution. It may not be much accurate, but it does not require the dependency of remote service.

I've found that maxmind's database provides mapping file between regions and time zones from Olsen database (aka tz database): http://www.maxmind.com/timezone.txt

The second step was to convert Olsen timezones in .NET timezones. The best suitable solution was found here: https://www.timdavis.com/posts/olson-time-zone-database-to-standard-windows-time-zone-v0-1 So I've edited it a bit and converted it to CSV file to read it from .NET.

Hope it will help somebody.


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

It's been a while since this question was asked, but might help others ..

When you are using a DatabaseReader Object from maxmind API in there has already an attribute location.timeZone you can retrieve it from the object returned by GeoIP Class, check out on API docs from maxmind.

Tags:

C#

Timezone