12

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?

VirusX
  • 953
  • 1
  • 9
  • 20

4 Answers4

11

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.

Erdogan Kurtur
  • 3,630
  • 21
  • 39
VirusX
  • 953
  • 1
  • 9
  • 20
  • 2
    Remember to accept your answer, as it's [okay to answer your own question](http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/). – Andrew Kozak Nov 03 '11 at 18:04
2

See the following links

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

How to get time zone information for country?

Community
  • 1
  • 1
AjayR
  • 4,169
  • 4
  • 44
  • 78
  • Thanks. Interesting service. I'll try to search for some offline-based approach since we can have more than 1M recipients in future, but this solution is very useful in my situation – VirusX Nov 02 '11 at 09:13
  • @VirusX - If you talking about millions of requests you will be hard pressed to find a free service. Of course Javascript would be free, many ways you could do this, including simply using a http request to a page with javascript page on it under your control. – Security Hound Nov 02 '11 at 11:46
  • @Ramhound - As I mentioned above, javascript can't be used here due to the nature of request. The beacon url is included in `src` parameter of `img` tag. When user opens email message, the request is going to our service. All we have are http headers and ip address of recipient. About millions - generally it doesn't mean millions of requests per minute or hour, but it can definitely be more than few requests per second. So, as I said, I'm trying to find some offline database to do that. – VirusX Nov 02 '11 at 12:45
1

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.

Adriano Rosa
  • 8,303
  • 1
  • 25
  • 25
1

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;
    }
}
live2
  • 3,771
  • 2
  • 37
  • 46