July 31 2013

C# - Get time zone and UTC offset from latitude and longitude (GPS coordinates)

I recently set up an Instagram feed for a travel blog and found that the Instagram API only supplies the UTC created date/time of each image, and doesn't supply the user's UTC Offset (as the Twitter API does), so the only thing you have to work with are the latitude and longitude (lat/long) coordinates to find out the timezone and UTC Offset of where the image was posted.

I'm sure I remember searching for a solution to this problem a few times over the years without much luck, there were only ever a few commercial options available and none were cheap, whereas I was looking for a free option. Luckily Google has come to the rescue with the recent release of The Google Time Zone API. It does exactly what I needed, it exposes a REST API that accepts parameters for lat/long coordinates and a timestamp (to determine if it's daylight savings time at the location) and returns the timezone and UTC Offset information for the location, either as JSON or XML.

An example request looks like:

https://maps.googleapis.com/maps/api/timezone/json?location=43.29712312,5.382137115&timestamp=1374868635&sensor=false

and returns the response:

{
   "dstOffset" : 3600.0,
   "rawOffset" : 3600.0,
   "status" : "OK",
   "timeZoneId" : "Europe/Paris",
   "timeZoneName" : "Central European Summer Time"
}

 

UPDATE: A fiddle for the below code can be found at https://dotnetfiddle.net/dMEtfP.

I used the RestSharp library to enable easy access the API, it's available on NuGet. Here's my C# code for getting the timezone info for a location:

public DateTime GetLocalDateTime(double latitude, double longitude, DateTime utcDate)
{
    var client = new RestClient("https://maps.googleapis.com");
    var request = new RestRequest("maps/api/timezone/json", Method.GET);
    request.AddParameter("location", latitude + "," + longitude);
    request.AddParameter("timestamp", utcDate.ToTimestamp());
    request.AddParameter("sensor", "false");
    var response = client.Execute<GoogleTimeZone>(request);

    return utcDate.AddSeconds(response.Data.rawOffset + response.Data.dstOffset);
}

This method is called with lat/long coordinates and the current UTC time like so:

var myDateTime = GetLocalDateTime(33.8323, -117.8803, DateTime.UtcNow);


Here's the code for the GoogleTimeZone class that I used as a wrapper for the JSON response from the Google Time Zone API:

public class GoogleTimeZone 
{
    public double dstOffset { get; set; }
    public double rawOffset { get; set; }
    public string status { get; set; }
    public string timeZoneId { get; set; }
    public string timeZoneName { get; set; }
}

And lastly the extension method for converting a C# DateTime object to a Timestamp:

public static double ToTimestamp(this DateTime date)
{
    DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
    TimeSpan diff = date.ToUniversalTime() - origin;
    return Math.Floor(diff.TotalSeconds);
}

Sponsored by