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

后端 未结 17 1536
走了就别回头了
走了就别回头了 2020-11-21 04:38

Given the latitude and longitude of a location, how does one know what time zone is in effect in that location?

In most cases, we are looking for an IANA/Olson time z

相关标签:
17条回答
  • 2020-11-21 04:50

    It's indeed important to recognize that this a more complicated problem than most would suspect. In practice many of us are also willing to accept a working set of code that works for "as many cases as possible", where at least its fatal issues can be identified and minimized collectively. So I post this with all of that and the spirit of the OP in mind. Finally, for practical value to others who are trying to convert GPS to timezone with the end goal of having a location-sensitive time object (and more importantly to help advance the quality of average implementations with time objects that follow from this wiki) here is what I generated in Python (please feel free to edit):

    import pytz
    from datetime import datetime
    from tzwhere import tzwhere
    
    def timezoned_unixtime(latitude, longitude, dt):
        tzw = tzwhere.tzwhere()
        timezone_str = tzw.tzNameAt(latitude, longitude)
        timezone = pytz.timezone(timezone_str)
        timezone_aware_datetime = timezone.localize(dt, is_dst=None)
        unix_time = (timezone_aware_datetime - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
        return unix_time
    
    dt = datetime(year=2017, month=1, day=17, hour=12, minute=0, second=0)
    print timezoned_unixtime(latitude=40.747854, longitude=-74.004733, dt=dt)
    
    0 讨论(0)
  • 2020-11-21 04:52

    From Guppy:

    import geocoders
    g = geocoders.GoogleV3()
    place, (lat, lng) = g.geocode('Fairbanks')
    print place, (lat, lng)
    Fairbanks, AK, USA (64.8377778, -147.7163889)
    timezone = g.timezone((lat, lng))
    print timezone.dst
    

    Bound method America/Anchorage.dst of DstTzInfo

    America/Anchorage' LMT-1 day, 14:00:00 STD

    0 讨论(0)
  • 2020-11-21 04:53

    Try this code for use Google Time Zone API from Java with current NTP Time Client and correct UTC_Datetime_from_timestamp convert:

    String get_xml_server_reponse(String server_url){
    
        URL xml_server = null;
    
        String xmltext = "";
    
        InputStream input;
    
    
        try {
            xml_server = new URL(server_url);
    
    
            try {
                input = xml_server.openConnection().getInputStream();
    
    
                final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                final StringBuilder sBuf = new StringBuilder();
    
                String line = null;
                try {
                    while ((line = reader.readLine()) != null) 
                    {
                        sBuf.append(line);
                    }
                   } 
                catch (IOException e) 
                  {
                        Log.e(e.getMessage(), "XML parser, stream2string 1");
                  } 
                finally {
                    try {
                        input.close();
                        }
                    catch (IOException e) 
                    {
                        Log.e(e.getMessage(), "XML parser, stream2string 2");
                    }
                }
    
                xmltext =  sBuf.toString();
    
            } catch (IOException e1) {
    
                    e1.printStackTrace();
                }
    
    
            } catch (MalformedURLException e1) {
    
              e1.printStackTrace();
            }
    
         return  xmltext;
    
      }     
    
    
     private String get_UTC_Datetime_from_timestamp(long timeStamp){
    
        try{
    
            Calendar cal = Calendar.getInstance();
            TimeZone tz = cal.getTimeZone();
    
            int tzt = tz.getOffset(System.currentTimeMillis());
    
            timeStamp -= tzt;
    
            // DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.getDefault());
            DateFormat sdf = new SimpleDateFormat();
            Date netDate = (new Date(timeStamp));
            return sdf.format(netDate);
        }
        catch(Exception ex){
            return "";
         }
        } 
    
     class NTP_UTC_Time
     {
         private static final String TAG = "SntpClient";
    
         private static final int RECEIVE_TIME_OFFSET = 32;
         private static final int TRANSMIT_TIME_OFFSET = 40;
         private static final int NTP_PACKET_SIZE = 48;
    
         private static final int NTP_PORT = 123;
         private static final int NTP_MODE_CLIENT = 3;
         private static final int NTP_VERSION = 3;
    
         // Number of seconds between Jan 1, 1900 and Jan 1, 1970
         // 70 years plus 17 leap days
         private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;
    
         private long mNtpTime;
    
         public boolean requestTime(String host, int timeout) {
             try {
                 DatagramSocket socket = new DatagramSocket();
                 socket.setSoTimeout(timeout);
                 InetAddress address = InetAddress.getByName(host);
                 byte[] buffer = new byte[NTP_PACKET_SIZE];
                 DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);
    
                 buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);
    
                 writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
    
                 socket.send(request);
    
                 // read the response
                 DatagramPacket response = new DatagramPacket(buffer, buffer.length);
                 socket.receive(response);          
                 socket.close();
    
                 mNtpTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);            
             } catch (Exception e) {
               //  if (Config.LOGD) Log.d(TAG, "request time failed: " + e);
                 return false;
             }
    
             return true;
         }
    
    
         public long getNtpTime() {
             return mNtpTime;
         }
    
    
         /**
          * Reads an unsigned 32 bit big endian number from the given offset in the buffer.
          */
         private long read32(byte[] buffer, int offset) {
             byte b0 = buffer[offset];
             byte b1 = buffer[offset+1];
             byte b2 = buffer[offset+2];
             byte b3 = buffer[offset+3];
    
             // convert signed bytes to unsigned values
             int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
             int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
             int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
             int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);
    
             return ((long)i0 << 24) + ((long)i1 << 16) + ((long)i2 << 8) + (long)i3;
         }
    
         /**
          * Reads the NTP time stamp at the given offset in the buffer and returns 
          * it as a system time (milliseconds since January 1, 1970).
          */    
         private long readTimeStamp(byte[] buffer, int offset) {
             long seconds = read32(buffer, offset);
             long fraction = read32(buffer, offset + 4);
             return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L);        
         }
    
         /**
          * Writes 0 as NTP starttime stamp in the buffer. --> Then NTP returns Time OFFSET since 1900
          */    
         private void writeTimeStamp(byte[] buffer, int offset) {        
             int ofs =  offset++;
    
             for (int i=ofs;i<(ofs+8);i++)
               buffer[i] = (byte)(0);             
         }
    
     }
    
     String get_time_zone_time(GeoPoint gp){
    
            String erg = "";
            String raw_offset = "";
            String dst_offset = "";
    
            double Longitude = gp.getLongitudeE6()/1E6;
            double Latitude = gp.getLatitudeE6()/1E6;
    
    
    
            long tsLong = 0; // System.currentTimeMillis()/1000;
    
            NTP_UTC_Time client = new NTP_UTC_Time();
    
            if (client.requestTime("pool.ntp.org", 2000)) {              
              tsLong = client.getNtpTime();
            }
    
            if (tsLong != 0)
            {
    
            tsLong = tsLong  / 1000;
    
            // https://maps.googleapis.com/maps/api/timezone/xml?location=39.6034810,-119.6822510&timestamp=1331161200&sensor=false
    
            String request = "https://maps.googleapis.com/maps/api/timezone/xml?location="+Latitude+","+ Longitude+ "&timestamp="+tsLong +"&sensor=false";
    
            String xmltext = get_xml_server_reponse(request);
    
            if(xmltext.compareTo("")!= 0)
            {
    
             int startpos = xmltext.indexOf("<TimeZoneResponse");
             xmltext = xmltext.substring(startpos);
    
    
    
            XmlPullParser parser;
            try {
                parser = XmlPullParserFactory.newInstance().newPullParser();
    
    
                 parser.setInput(new StringReader (xmltext));
    
                 int eventType = parser.getEventType();  
    
                 String tagName = "";
    
    
                 while(eventType != XmlPullParser.END_DOCUMENT) {
                     switch(eventType) {
    
                         case XmlPullParser.START_TAG:
    
                               tagName = parser.getName();
    
                             break;
    
    
                         case XmlPullParser.TEXT :
    
    
                            if  (tagName.equalsIgnoreCase("raw_offset"))
                              if(raw_offset.compareTo("")== 0)                               
                                raw_offset = parser.getText();  
    
                            if  (tagName.equalsIgnoreCase("dst_offset"))
                              if(dst_offset.compareTo("")== 0)
                                dst_offset = parser.getText();  
    
    
                            break;   
    
                     }
    
                     try {
                            eventType = parser.next();
                        } catch (IOException e) {
    
                            e.printStackTrace();
                        }
    
                    }
    
                    } catch (XmlPullParserException e) {
    
                        e.printStackTrace();
                        erg += e.toString();
                    }
    
            }      
    
            int ro = 0;
            if(raw_offset.compareTo("")!= 0)
            { 
                float rof = str_to_float(raw_offset);
                ro = (int)rof;
            }
    
            int dof = 0;
            if(dst_offset.compareTo("")!= 0)
            { 
                float doff = str_to_float(dst_offset);
                dof = (int)doff;
            }
    
            tsLong = (tsLong + ro + dof) * 1000;
    
    
    
            erg = get_UTC_Datetime_from_timestamp(tsLong);
            }
    
    
      return erg;
    
    }
    

    And use it with:

    GeoPoint gp = new GeoPoint(39.6034810,-119.6822510);
    String Current_TimeZone_Time = get_time_zone_time(gp);
    
    0 讨论(0)
  • 2020-11-21 04:56

    If you prefer to avoid a web service, you can retrieve that information from the browser like this:

    var d = new Date();
    var usertime = d.toLocaleString();
    
    //some browsers / OSs provide the timezone name in their local string
    var tzsregex = /\b(ACDT|ACST|ACT|ADT|AEDT|AEST|AFT|AKDT|AKST|AMST|AMT|ART|AST|AWDT|AWST|AZOST|AZT|BDT|BIOT|BIT|BOT|BRT|BST|BTT|CAT|CCT|CDT|CEDT|CEST|CET|CHADT|CHAST|CIST|CKT|CLST|CLT|COST|COT|CST|CT|CVT|CXT|CHST|DFT|EAST|EAT|ECT|EDT|EEDT|EEST|EET|EST|FJT|FKST|FKT|GALT|GET|GFT|GILT|GIT|GMT|GST|GYT|HADT|HAEC|HAST|HKT|HMT|HST|ICT|IDT|IRKT|IRST|IST|JST|KRAT|KST|LHST|LINT|MART|MAGT|MDT|MET|MEST|MIT|MSD|MSK|MST|MUT|MYT|NDT|NFT|NPT|NST|NT|NZDT|NZST|OMST|PDT|PETT|PHOT|PKT|PST|RET|SAMT|SAST|SBT|SCT|SGT|SLT|SST|TAHT|THA|UYST|UYT|VET|VLAT|WAT|WEDT|WEST|WET|WST|YAKT|YEKT)\b/gi;
    
    //in other browsers the timezone needs to be estimated based on the offset
    var timezonenames = {"UTC+0":"GMT","UTC+1":"CET","UTC+2":"EET","UTC+3":"EEDT","UTC+3.5":"IRST","UTC+4":"MSD","UTC+4.5":"AFT","UTC+5":"PKT","UTC+5.5":"IST","UTC+6":"BST","UTC+6.5":"MST","UTC+7":"THA","UTC+8":"AWST","UTC+9":"AWDT","UTC+9.5":"ACST","UTC+10":"AEST","UTC+10.5":"ACDT","UTC+11":"AEDT","UTC+11.5":"NFT","UTC+12":"NZST","UTC-1":"AZOST","UTC-2":"GST","UTC-3":"BRT","UTC-3.5":"NST","UTC-4":"CLT","UTC-4.5":"VET","UTC-5":"EST","UTC-6":"CST","UTC-7":"MST","UTC-8":"PST","UTC-9":"AKST","UTC-9.5":"MIT","UTC-10":"HST","UTC-11":"SST","UTC-12":"BIT"};
    
    var timezone = usertime.match(tzsregex);
    if (timezone) {
        timezone = timezone[timezone.length-1];
    } else {
        var offset = -1*d.getTimezoneOffset()/60;
        offset = "UTC" + (offset >= 0 ? "+" + offset : offset);
        timezone = timezonenames[offset];
    }
    
    //there are 3 variables can use to see the timezone
    // usertime - full date
    // offset - UTC offset time
    // timezone - country
    
    console.log('Full Date: ' + usertime);
    console.log('UTC Offset: ' + offset);
    console.log('Country Code Timezone: ' + timezone);
    

    In my current case it is printing:

    Full Date: ‎27‎/‎01‎/‎2014‎ ‎16‎:‎53‎:‎37 UTC Offset: UTC-3 Country Code Timezone: BRT

    Hope it can be helpful.

    0 讨论(0)
  • 2020-11-21 04:57

    For those of us using Javascript and looking to get a timezone from a zip code via Google APIs, here is one method.

    1. Fetch the lat/lng via geolocation
    2. fetch the timezone by pass that into the timezone API.
      • Using Luxon here for timezone conversion.

    Note: my understanding is that zipcodes are not unique across countries, so this is likely best suited for use in the USA.

    const googleMapsClient; // instantiate your client here
    const zipcode = '90210'
    const myDateThatNeedsTZAdjustment; // define your date that needs adjusting
    // fetch lat/lng from google api by zipcode
    const geocodeResponse = await googleMapsClient.geocode({ address: zipcode }).asPromise();
    if (geocodeResponse.json.status === 'OK') {
      lat = geocodeResponse.json.results[0].geometry.location.lat;
      lng = geocodeResponse.json.results[0].geometry.location.lng;
    } else {
      console.log('Geocode was not successful for the following reason: ' + status);
    }
    
    // prepare lat/lng and timestamp of profile created_at to fetch time zone
    const location = `${lat},${lng}`;
    const timestamp = new Date().valueOf() / 1000;
    const timezoneResponse = await googleMapsClient
      .timezone({ location: location, timestamp: timestamp })
      .asPromise();
    
    const timeZoneId = timezoneResponse.json.timeZoneId;
    // adjust by setting timezone
    const timezoneAdjustedDate = DateTime.fromJSDate(
      myDateThatNeedsTZAdjustment
    ).setZone(timeZoneId);
    
    0 讨论(0)
  • 2020-11-21 04:58

    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

    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.

    0 讨论(0)
提交回复
热议问题