Convert to Local Time Zone Using Latitude and Longitude

How to get a time zone from a location using latitude and longitude coordinates?

Time Zone Location Web Services

  • Google Maps Time Zone API
  • Bing Maps Time Zone API
  • Azure Maps Time Zone API
  • GeoNames Time Zone API
  • TimeZoneDB API
  • AskGeo - commercial (but arguably more accurate than GeoNames)
  • GeoGarage Time Zone API - commercial, focusing on Nautical time zones.

Raw Time Zone Boundary Data

  • Timezone Boundary Builder - builds time zone shapefiles from OpenStreetMaps map data. Includes territorial waters near coastlines.

The following projects have previously been sources of time zone boundary data, but are no longer actively maintained.

  • tz_world - the original shapefile data from Eric Muller
  • whereonearth-timezone - GeoJSON version with WOEDB data merged in

Time Zone Geolocation Offline Implementations

Implementations that use the Timezone Boundary Builder data

  • node-geo-tz - JavaScript library (Node.js only)
  • timespace - JavaScript library
  • tz-lookup-oss - JavaScript library
  • GeoTimeZone - .NET library
  • Geo-Timezone - PHP library
  • timezonefinder - Python library
  • ZoneDetect - C library
  • Timeshape - Java library
  • TimeZoneMap - Java and Android library
  • lutz - R library
  • go-tz - Go library
  • Timezone lookup - Go library
  • docker-timezone-lookup - docker container wrapping node-geo-tz
  • tzf - Go library
  • tzfpy - Python port of tzf library
  • tzf-rs - Rust port of tzf library

Implementations that use the older tz_world data

  • latlong - Go library (Read this post also.)
  • TimeZoneMapper - Java library
  • tzwhere - JavaScript/Node library
  • pytzwhere - Python library
  • timezone_finder - Ruby library
  • LatLongToTimeZone - Java and Swift libraries
  • What Time is it here? - Blog post describing PHP and MongoDB
  • rundel/timezone - R library

Libraries that call one of the web services

  • timezone - Ruby gem that calls GeoNames
  • AskGeo has its own libraries for calling from Java or .Net
  • GeoNames has client libraries for just about everything

Self-hosted web services

  • geo2tz - based on Timezone lookup, available via Docker image

Other Ideas

  • Find the nearest city with an R-Tree
  • Find the nearest city with MySQL

Please update this list if you know of any others

Also, note that the nearest-city approach may not yield the "correct" result, just an approximation.

Conversion To Windows Zones

Most of the methods listed will return an IANA time zone id. If you need to convert to a Windows time zone for use with the TimeZoneInfo class in .NET, use the TimeZoneConverter library.

Don't use zone.tab

The tz database includes a file called zone.tab. This file is primarily used to present a list of time zones for a user to pick from. It includes the latitude and longitude coordinates for the point of reference for each time zone. This allows a map to be created highlighting these points. For example, see the interactive map shown on the moment-timezone home page.

While it may be tempting to use this data to resolve the time zone from a latitude and longitude coordinates, consider that these are points - not boundaries. The best one could do would be to determine the closest point, which in many cases will not be the correct point.

Consider the following example:

                            Time Zone Example Art

The two squares represent different time zones, where the black dot in each square is the reference location, such as what can be found in zone.tab. The blue dot represents the location we are attempting to find a time zone for. Clearly, this location is within the orange zone on the left, but if we just look at closest distance to the reference point, it will resolve to the greenish zone on the right.

Convert to local time zone from latitude and longitude R

I think this is what you want. I first created a date object. Then, I searched time zones with tz_lookup_coords() as you were trying. Then, I used with_tz(), which gets date-time in a different time zone. Note that new_time is a list as str(dt) indicates.

library(data.table)
library(lutz)
library(purrr)
library(lubridate)

dt[, date := as.POSIXct(date, format = "%Y-%m-%d %H:%M:%S", tz = "GMT")][,
timezone := tz_lookup_coords(lat = lat, lon = long, method = "accurate")][,
new_time := map2(.x = date, .y = timezone,
.f = function(x, y) {with_tz(time = x, tzone = y)})][]

# date lat long timezone new_time
#1: 2018-01-16 22:02:37 -54.5010 -25.0433 Etc/GMT+2 2018-01-16 20:02:37
#2: 2018-01-16 22:54:00 -54.5246 -25.0929 Etc/GMT+2 2018-01-16 20:54:00
#3: 2018-01-16 23:08:38 -54.5285 -25.0832 Etc/GMT+2 2018-01-16 21:08:38

#str(dt)
#Classes ‘data.table’ and 'data.frame': 3 obs. of 5 variables:
# $ date : POSIXct, format: "2018-01-16 22:02:37" "2018-01-16 22:54:00" "2018-01-16 23:08:38"
# $ lat : num -54.5 -54.5 -54.5
# $ long : num -25 -25.1 -25.1
# $ timezone: chr "Etc/GMT+2" "Etc/GMT+2" "Etc/GMT+2"
# $ new_time:List of 3
# ..$ : POSIXct, format: "2018-01-16 20:02:37"
# ..$ : POSIXct, format: "2018-01-16 20:54:00"
# ..$ : POSIXct, format: "2018-01-16 21:08:38"

A bit more help

If you have a data frame, you can use tidyverse approaches too. I used your dt here. I converted it to a data.frame object. The last thin you need is unnest(). Then, you will have time in a column.

setDF(dt) %>% 
mutate(date = as.POSIXct(date, format = "%Y-%m-%d %H:%M:%S", tz = "GMT"),
timezone = tz_lookup_coords(lat = lat, lon = long, method = "accurate"),
new_time = map2(.x = date, .y = timezone,
.f = function(x, y) {with_tz(time = x, tzone = y)})) %>%
unnest(new_time)

date lat long timezone new_time
<dttm> <dbl> <dbl> <chr> <dttm>
1 2018-01-16 22:02:37 -54.5 -25.0 Etc/GMT+2 2018-01-16 20:02:37
2 2018-01-16 22:54:00 -54.5 -25.1 Etc/GMT+2 2018-01-16 20:54:00
3 2018-01-16 23:08:38 -54.5 -25.1 Etc/GMT+2 2018-01-16 21:08:38

> str(foo)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 3 obs. of 5 variables:
$ date : POSIXct, format: "2018-01-16 22:02:37" "2018-01-16 22:54:00" "2018-01-16 23:08:38"
$ lat : num -54.5 -54.5 -54.5
$ long : num -25 -25.1 -25.1
$ timezone: chr "Etc/GMT+2" "Etc/GMT+2" "Etc/GMT+2"
$ new_time: POSIXct, format: "2018-01-16 20:02:37" "2018-01-16 20:54:00" "2018-01-16 21:08:38"

convert to local time zone using latitude and longitude?

lat = 13
long = -2
time1 <- as.POSIXct("2014-02-12 17:00:00", tz = "EST")
# https://developers.google.com/maps/documentation/timezone/
apiurl <- sprintf("https://maps.googleapis.com/maps/api/timezone/%s?location=%s,%s×tamp=%d&sensor=%s",
"xml",
lat,
long,
as.numeric(time1),
"false")
library(XML)
tz <- xmlParse(readLines(apiurl))[["string(//time_zone_id)"]]
as.POSIXct(format(time1, tz=tz))
# [1] "2014-02-12 22:00:00 CET"

or, as suggested by @SymbolixAU, use their googleway package:

res <- googleway::google_timezone(c(lat, long), time1, key = NULL)
as.POSIXct(format(time1, tz=res$timeZoneId))
# [1] "2014-02-12 22:00:00 CET"

Get local time based on coordinates

You can do it using Google api for identifying current timezone.

.Net Fiddle example:

public class Program
{
public static 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);
}

public static void Main()
{
var myDateTime = GetLocalDateTime(33.8323, -117.8803, DateTime.UtcNow);
Console.WriteLine(myDateTime.ToString());
}
}

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

public static class ExtensionMethods
{
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);
}
}

And then you can easily use your GetLocalDateTime(double latitude, double longitude, DateTime utcDate) method as it was shown in the example above:

public static void Main()
{
var myDateTime = GetLocalDateTime(33.8323, -117.8803, DateTime.UtcNow);
Console.WriteLine(myDateTime.ToString());
}

Determine timezone from latitude/longitude without using web services like Geonames.org

I had this problem a while back and did exactly what adam suggested:

  • Download the database of cities from geonames.org
  • convert it to a compact lat/lon -> timezone list
  • use an R-Tree implementation to efficiently lookup the nearest city (or rather, its timezone) to a given coordinate

IIRC it took less than 1 second to populate the R-Tree, and it could then perform thousands of lookups per second (both on a 5 year old PC).

How to get the time zone from latitude and longitude coordinates with BigQuery?

I would start by uploading time zone polygon boundaries.

E.g. you can get them from here https://github.com/evansiroky/timezone-boundary-builder. This project offers shapefile and geojson file formats, you'll need to convert to one of the formats supported by BigQuery, e.g. new-line-delimited geojson, or CSV, and upload to BigQuery. Open source ogr2ogr tool can do this, as well as many proprietary tools.

Once you have the data in BigQuery, you can join the locations with time zone polygons, like

WITH points AS (
SELECT (RAND()-0.5)*90 as latitude, (RAND()-0.5)*180 as longitude
FROM UNNEST(GENERATE_ARRAY(1, 100))
)
SELECT * FROM points p CROSS JOIN time_zones tz
ON ST_Intersects(ST_GeogPoint(p.longitude, p.latitude), tz.geometry)

Timezone lookup from latitude longitude

I looked fairly deeply into this question for a project I am working on. GeoNames.org and EarthTools.com are both good options for many situations but with the following serious flaws:

  • GeoNames.org finds the time zone by searching for the nearest point in their database that contains a time zone field. This often leads to the wrong result near borders. It is also painfully slow, leading to query times on the order of a couple seconds per request. It also doesn't return a valid time zone if there is no item in their database near the query point. GeoNames also restricts the number of queries that can be made per day, making bulk operations difficult.
  • EarthTools.org uses a map and is able to return queries quickly, but it doesn't take into account daylight savings time for most locations, and it returns a raw offset rather than a time zone ID (i.e., they return "GMT-7" instead of "America/Chicago"). Also, I just looked at their page while preparing this post and Google Chrome warned about malware on their site. That is new to me and it may change, but is obviously a cause for concern.

These flaws meant that these existing tools were not suitable for my needs so I rolled my own solution and have published it for general use. You can find it here:

http://www.askgeo.com/

AskGeo is based on a time zone map of the world, so it returns a valid time zone for every valid latitude and longitude. It returns the standard time zone ID (e.g., "America/Los_Angeles") used on Linux and most other operating systems and programming frameworks. It also returns the current offset, taking full account of daylight savings time.

It is extremely easy to use and usage is documented on the main page of the site. The API supports batch queries, so if you need to do a lot of look-ups, please use the batch interface rather than bog down our servers with serial requests. The bulk queries are also much faster, so everybody wins.

When we first launched this, we built it on Google App Engine (GAE) and made it free to all users. This was possible because GAE's prices were so low at that time. Since then, our server load has increased substantially and GAE's prices went way up. Both factors combined led us to switch to Amazon Web Services for hosting and to start charging for commercial use, while keeping the service free for non-profit, non-commercial open source projects, and researchers. For commercial users, we provide 1000 free queries to let potential customers evaluate the API to make sure it meets their needs. See the web site for pricing and terms.

The underlying library was written in Java and due to popular demand, we also released the library under a commercial license. Full documentation of the library and pricing details are on the web site.

I hope this is useful. It certainly was useful for the project I was working on.

C++ How to determine time zone using latitude and longitude

You can use Google Time Zone API or TimeZoneDb.



Related Topics



Leave a reply



Submit