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:
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
How to Convert Characters into Ascii Code
Error Trying to Read a PDF Using Readpdf from The Tm Package
Aggregating Rows for Multiple Columns in R
How to Read All Files in One Directory into R at Once
Ggplot2 Equivalent of 'Factorization or Categorization' in Googlevis in R
Data.Table Objects Aren't Updated in Rstudio Environment Panel
Do Not Open Rstudio Internal Browser After Knitting
Meaning of Error Using . Shorthand Inside Dplyr Function
How to Efficiently Retrieve Top K-Similar Vectors by Cosine Similarity Using R
Importing an Excel File with Greek Characters into R in The Correct Encoding
How to Give Numbers to Each Group of a Dataframe with Dplyr::Group_By
Customise The Infowindow/Tooltip in R -> Plotly
Cannot Install Rgdal Package in R on Rhel6, Unable to Load Shared Object Rgdal.So
How to Split a Dataframe Column by The First Instance of a Character in Its Values