Come ottenere un fuso orario da una posizione utilizzando le coordinate di latitudine e longitudine?


310

Esistono troppe domande su StackOverflow sulla risoluzione di un fuso orario da una posizione. Questa wiki della comunità è un tentativo di consolidare tutte le risposte valide.

Aggiorna la mia risposta o aggiungi la tua come ritieni opportuno.

La domanda
Data la latitudine e la longitudine di un luogo, come si fa a sapere quale fuso orario è attivo in quel luogo?

Nella maggior parte dei casi, stiamo cercando un ID fuso orario IANA / Olson, sebbene alcuni servizi possano restituire solo un offset UTC o un altro identificatore del fuso orario. Per informazioni dettagliate, leggi le informazioni sui tag del fuso orario .


2
Una cosa che ho notato è la mancanza di qualsiasi requisito di data / ora UTC nel determinare il fuso orario. Ad esempio, un long / lat a Londra non è sufficiente per determinare il tempo il fuso orario è GMT o BST (ora legale britannica / ora legale). Quindi sicuramente per determinare il fuso orario corretto è necessario lat, long e un timestamp UTC.
Michael Waterfall,

4
@MichaelWaterfall - Per determinare se ti trovi in ​​GMT (UTC + 0000) o BST (UTC + 0100) - sì, hai assolutamente ragione. Ma quelli sono offset del fuso orario , non identificatori di fuso orario. Entrambi sono coperti dallo stesso "Europe/London"identificatore di fuso orario del database dei fusi orari IANA.
Matt Johnson-Pint,

Ah va bene, e l'offset dell'ora legale verrà aggiunto (se richiesto) una volta che si esegue il rendering di un'ora con un determinato identificatore del fuso orario?
Michael Waterfall,

@Michael - dipende dall'implementazione specifica, ma di solito sì.
Matt Johnson-Pint,

1
Potrebbe ancora richiedere il timestamp UTC. Ad esempio, la Russia cambia i limiti di fuso orario 4 volte negli ultimi 6 anni. en.wikipedia.org/wiki/Time_in_Russia
Arnial il

Risposte:


422

Servizi Web di localizzazione del fuso orario

Dati di confine di fuso orario non elaborati

  • Timezone Boundary Builder : crea gli shapefile del fuso orario dai dati della mappa OpenStreetMaps. Include acque territoriali vicino alle coste.

I seguenti progetti sono stati in precedenza fonti di dati sui confini del fuso orario, ma non sono più attivamente mantenuti.

Implementazioni offline di geolocalizzazione del fuso orario

Implementazioni che utilizzano i dati di Timezone Boundary Builder

Implementazioni che utilizzano i vecchi dati tz_world

Librerie che chiamano uno dei servizi Web

  • fuso orario - gemma rubino che chiama GeoNames
  • AskGeo ha le sue librerie per le chiamate da Java o .Net
  • GeoNames ha librerie client per quasi tutto

Servizi web ospitati autonomamente

Altre idee

Aggiorna questo elenco se ne conosci altri

Inoltre, si noti che l'approccio della città più vicina potrebbe non produrre il risultato "corretto", ma solo un'approssimazione.

Conversione in zone di Windows

La maggior parte dei metodi elencati restituirà un ID fuso orario IANA. Se è necessario convertire in un fuso orario di Windows per l'uso con la TimeZoneInfoclasse in .NET, utilizzare la libreria TimeZoneConverter .

Non usare zone.tab

Il database tz include un file chiamato zone.tab. Questo file viene utilizzato principalmente per presentare un elenco di fusi orari da cui l'utente può scegliere. Include le coordinate di latitudine e longitudine per il punto di riferimento per ciascun fuso orario. Ciò consente di creare una mappa evidenziando questi punti. Ad esempio, vedere la mappa interattiva mostrata nella home page del fuso orario del momento .

Mentre può essere allettante utilizzare questi dati per risolvere il fuso orario da coordinate di latitudine e longitudine, considera che si tratta di punti, non di confini. Il migliore potrebbe essere quello di determinare il punto più vicino , che in molti casi non sarà il punto corretto.

Considera il seguente esempio:

                            Esempio di fuso orario Art

I due quadrati rappresentano fusi orari diversi, in cui il punto nero in ciascun quadrato è la posizione di riferimento, ad esempio ciò che è possibile trovare in zone.tab. Il punto blu rappresenta la posizione per cui stiamo tentando di trovare un fuso orario. Chiaramente, questa posizione è all'interno della zona arancione a sinistra, ma se osserviamo solo la distanza più vicina al punto di riferimento, si risolverà nella zona verdastra a destra.


1
GeoNames è in realtà perfetto per quello che mi serve. Grazie!
Luca,

1
@Matt Tuttavia, a quanto ho capito, al momento non esiste un database offline che fornisca informazioni sul fuso orario e offset dall'ora UTC in base alle coordinate della posizione?
Martin,

@MattJohnson come posso usare le librerie client di geonames
Erum

Questa è una lista fantastica, grazie! Google sembra la scelta ovvia, ma sono stato sorpreso di scoprire che mi dicono che Londra è in GMT, quando in realtà è in BST al momento. Per New York ha avuto il corretto aggiustamento estivo.
Lewis,

8
Queste nuove tariffe dell'API di Google sono esorbitanti. 200 richieste per $ 1 a partire dal 18/07. Questo è un aumento di 10 volte.
Chris Lukic,


8

Noi di Teleport abbiamo appena iniziato ad aprire le nostre API e uno dei casi d'uso sta anche esponendo le informazioni TZ per le coordinate.

Ad esempio, è possibile richiedere tutte le informazioni TZ disponibili per le coordinate nel modo seguente:

curl -s https://api.teleport.org/api/locations/59.4372,24.7453/?embed=location:nearest-cities/location:nearest-city/city:timezone/tz:offsets-now | jq '._embedded."location:nearest-cities"[0]._embedded."location:nearest-city"._embedded."city:timezone"'

Ciò restituirebbe quanto segue

{
  "_embedded": {
    "tz:offsets-now": {
      "_links": {
        "self": {
          "href": "https://api.teleport.org/api/timezones/iana:Europe%2FTallinn/offsets/?date=2015-09-07T11%3A20%3A09Z"
        }
      },
      "base_offset_min": 120,
      "dst_offset_min": 60,
      "end_time": "2015-10-25T01:00:00Z",
      "short_name": "EEST",
      "total_offset_min": 180,
      "transition_time": "2015-03-29T01:00:00Z"
    }
  },
  "_links": {
    "self": {
      "href": "https://api.teleport.org/api/timezones/iana:Europe%2FTallinn/"
    },
    "tz:offsets": {
      "href": "https://api.teleport.org/api/timezones/iana:Europe%2FTallinn/offsets/{?date}",
      "templated": true
    },
    "tz:offsets-now": {
      "href": "https://api.teleport.org/api/timezones/iana:Europe%2FTallinn/offsets/?date=2015-09-07T11%3A20%3A09Z"
    }
  },
  "iana_name": "Europe/Tallinn"
}

Per l'esempio ho usato ./jq per l'analisi JSON.


2
Grazie per la condivisione. Sta facendo un approccio alla città più vicina o stai usando un approccio point-in-poligono? (Vedi il mio diagramma con i due quadrati sopra.)
Matt Johnson-Pint,

3

Ecco come è possibile utilizzare l'editor di script di Google per ottenere timezoneName e timeZoneId all'interno di un gsheet.

Passaggio 1. Ottieni una chiave API per l'API del fuso orario di Google

Passaggio 2. Creare un nuovo foglio elettronico. Sotto il menu "strumenti" fai clic su "editor di script". Aggiungi il seguente codice:

function getTimezone(lat, long) {  
  var apiKey = 'INSERTAPIKEYHERE'
  var url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' + lat + ',' + long + '&timestamp=1331161200&key=' + apiKey 
  var response = UrlFetchApp.fetch(url);
  var data = JSON.parse(response.getContentText());
  return data["timeZoneName"];
}

Passaggio 3. Salvare e pubblicare la getTimezone()funzione e utilizzarla come mostrato nell'immagine sopra.


2

Puoi utilizzare geolocator.js per ottenere facilmente il fuso orario e altro ...

Utilizza le API di Google che richiedono una chiave. Quindi, prima configura geolocator:

geolocator.config({
    language: "en",
    google: {
        version: "3",
        key: "YOUR-GOOGLE-API-KEY"
    }
});

Ottieni TimeZone se hai le coordinate:

geolocator.getTimeZone(options, function (err, timezone) {
    console.log(err || timezone);
});

Esempio di output:

{
    id: "Europe/Paris",
    name: "Central European Standard Time",
    abbr: "CEST",
    dstOffset: 0,
    rawOffset: 3600,
    timestamp: 1455733120
}

Individua quindi ottieni TimeZone e altro

Se non si hanno le coordinate, è possibile individuare prima la posizione dell'utente.

L'esempio seguente proverà innanzitutto l'API di geolocalizzazione HTML5 per ottenere le coordinate. Se fallisce o rifiuta, otterrà le coordinate tramite la ricerca Geo-IP. Infine, otterrà il fuso orario e altro ancora ...

var options = {
    enableHighAccuracy: true,
    timeout: 6000,
    maximumAge: 0,
    desiredAccuracy: 30,
    fallbackToIP: true, // if HTML5 fails or rejected
    addressLookup: true, // this will get full address information
    timezone: true,
    map: "my-map" // this will even create a map for you
};
geolocator.locate(options, function (err, location) {
    console.log(err || location);
});

Esempio di output:

{
    coords: {
        latitude: 37.4224764,
        longitude: -122.0842499,
        accuracy: 30,
        altitude: null,
        altitudeAccuracy: null,
        heading: null,
        speed: null
    },
    address: {
        commonName: "",
        street: "Amphitheatre Pkwy",
        route: "Amphitheatre Pkwy",
        streetNumber: "1600",
        neighborhood: "",
        town: "",
        city: "Mountain View",
        region: "Santa Clara County",
        state: "California",
        stateCode: "CA",
        postalCode: "94043",
        country: "United States",
        countryCode: "US"
    },
    formattedAddress: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
    type: "ROOFTOP",
    placeId: "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
    timezone: {
        id: "America/Los_Angeles",
        name: "Pacific Standard Time",
        abbr: "PST",
        dstOffset: 0,
        rawOffset: -28800
    },
    flag: "//cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/flags/4x3/us.svg",
    map: {
        element: HTMLElement,
        instance: Object, // google.maps.Map
        marker: Object, // google.maps.Marker
        infoWindow: Object, // google.maps.InfoWindow
        options: Object // map options
    },
    timestamp: 1456795956380
}

1

https://en.wikipedia.org/wiki/Great-circle_distance

Ed ecco una buona implementazione usando i dati JSON: https://github.com/agap/llttz

public TimeZone nearestTimeZone(Location node) {
    double bestDistance = Double.MAX_VALUE;
    Location bestGuess = timeZones.get(0);

    for (Location current : timeZones.subList(1, timeZones.size())) {
        double newDistance = distanceInKilometers(node, current);

        if (newDistance < bestDistance) {
            bestDistance = newDistance;
            bestGuess = current;
        }
    }

    return java.util.TimeZone.getTimeZone(bestGuess.getZone());
}

  protected double distanceInKilometers(final double latFrom, final double lonFrom, final double latTo, final double lonTo) {
        final double meridianLength = 111.1;
        return meridianLength * centralAngle(latFrom, lonFrom, latTo, lonTo);
    }

    protected double centralAngle(final Location from, final Location to) {
        return centralAngle(from.getLatitude(), from.getLongitude(), to.getLatitude(), to.getLongitude());
    }

    protected double centralAngle(final double latFrom, final double lonFrom, final double latTo, final double lonTo) {
        final double latFromRad = toRadians(latFrom),
                lonFromRad = toRadians(lonFrom),
                latToRad   = toRadians(latTo),
                lonToRad   = toRadians(lonTo);

        final double centralAngle = toDegrees(acos(sin(latFromRad) * sin(latToRad) + cos(latFromRad) * cos(latToRad) * cos(lonToRad - lonFromRad)));

        return centralAngle <= 180.0 ? centralAngle : (360.0 - centralAngle);
    }

    protected double distanceInKilometers(final Location from, final Location to) {
        return distanceInKilometers(from.getLatitude(), from.getLongitude(), to.getLatitude(), to.getLongitude());
    }
}

Puoi anche aggiungere del contenuto dai link?
Robert,

1

divulgazione: sono l'autore dell'immagine docker descritta di seguito

Ho avvolto https://github.com/evansiroky/node-geo-tz in un contenitore docker molto semplice

https://hub.docker.com/repository/docker/tobias74/timezone-lookup

È possibile avviare la finestra mobile-contenitore con

docker run -p 80:3000 tobias74/timezone-lookup:latest

Questo espone il servizio di ricerca sul tuo host locale sulla porta 3000. È quindi possibile eseguire una ricerca del fuso orario da

curl "localhost:3000/timezone?latitude=12&longitude=34"

0

Prova questo codice per utilizzare l'API del fuso orario di Google da Java con l'attuale client NTP e la conversione UTC_Datetime_from_timestamp corretta:

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;

}

E usalo con:

GeoPoint gp = new GeoPoint(39.6034810,-119.6822510);
String Current_TimeZone_Time = get_time_zone_time(gp);

1
Sembra un sacco di codice per un compito semplice. Hai un client NTP completo, il che potrebbe essere una buona idea, ma non è necessariamente necessario. Puoi dimagrire un po 'per favore?
Matt Johnson-Pint,

0

Ok ecco la versione breve senza l'ora NTP corretta:

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;

} 


long get_time_zone_time_l(GeoPoint gp){


        String raw_offset = "";
        String dst_offset = "";

        double Longitude = gp.getLongitudeE6()/1E6;
        double Latitude = gp.getLatitudeE6()/1E6;

        long tsLong = System.currentTimeMillis()/1000;


        if (tsLong != 0)
        {

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


        }


  return tsLong;

}

E usalo con:

GeoPoint gp = new GeoPoint(39.6034810,-119.6822510);
long Current_TimeZone_Time_l = get_time_zone_time_l(gp);

0

Se vuoi usare geonames.org, usa questo codice. (Ma a volte geonames.org è molto lento)

String get_time_zone_time_geonames(GeoPoint gp){


        String erg = "";

        double Longitude = gp.getLongitudeE6()/1E6;
        double Latitude = gp.getLatitudeE6()/1E6;



        String request = "http://ws.geonames.org/timezone?lat="+Latitude+"&lng="+ Longitude+ "&style=full";

        URL time_zone_time = null;

        InputStream input;
       // final StringBuilder sBuf = new StringBuilder();


        try {
            time_zone_time = new URL(request);


        try {
            input = time_zone_time.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");
                }
            }




             String xmltext = sBuf.toString();


             int startpos = xmltext.indexOf("<geonames");
             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("time"))
                          erg = parser.getText();  


                    break;   

                }

                try {
                    eventType = parser.next();
                } catch (IOException e) {

                    e.printStackTrace();
                }

            }

            } catch (XmlPullParserException e) {

                e.printStackTrace();
                erg += e.toString();
            }



            } catch (IOException e1) {

                e1.printStackTrace();
            }


            } catch (MalformedURLException e1) {

                e1.printStackTrace();
            }





        return erg;

 }

E usalo con:

GeoPoint gp = new GeoPoint(39.6034810,-119.6822510);
String Current_TimeZone_Time = get_time_zone_time_geonames(gp);

0

Da 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

Metodo associato America/Anchorage.dstdiDstTzInfo

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


Penso che Guppy sia un errore di battitura. Intendi Geopy o qualcos'altro?
Matt Johnson-Pint,

0

È davvero importante riconoscere che questo è un problema più complicato di quanto la maggior parte sospetti. In pratica molti di noi sono anche disposti ad accettare un insieme funzionante di codice che funziona per "il maggior numero possibile di casi", dove almeno i suoi problemi fatali possono essere identificati e minimizzati collettivamente. Quindi pubblicherò questo con tutto ciò e lo spirito dell'OP in mente. Infine, per un valore pratico per gli altri che stanno cercando di convertire il GPS in fuso orario con l'obiettivo finale di avere un oggetto temporale sensibile alla posizione (e, cosa più importante, aiutare a migliorare la qualità delle implementazioni medie con oggetti temporali che seguono da questo wiki) ecco cosa ho generato in Python (non esitate a modificare):

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)

Grazie, ma questo sembra un codice che utilizza pytzwhere che è già elencato nella risposta wiki della community principale. Se intendevi fornire un esempio di come combinare pytzwhere con pytz, potresti voler inviarlo come PR al progetto pytzwhere stesso. Qui stiamo solo cercando soluzioni da lat / lon a tz - di cui pytzwhere è una di queste.
Matt Johnson-Pint,

0
  1. Esistono diverse fonti online che dispongono di dati geojson per fusi orari ( eccone uno , eccone un altro)

  2. Utilizzare una libreria geometrica per creare oggetti poligonali dalle coordinate geojson ( formosa [python], GEOS [c ++], JTS [java], NTS [.net]).

  3. Converti lat / lng in un oggetto punto (comunque la tua libreria lo rappresenta) e controlla se interseca il poligono del fuso orario.

    from shapely.geometry import Polygon, Point
    
    def get_tz_from_lat_lng(lat, lng):
        for tz, geojson in timezones.iteritems():
            coordinates = geojson['features'][0]['geometry']['coordinates']
            polygon = Polygon(coordinates)
            point = Point(lng, lat)
            if polygon.contains(point):
                return tz
    

0

usando latitudine e longitudine ottenere il fuso orario della posizione corrente sotto il codice ha funzionato per me

String data = null;         
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Location ll = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
double lat = 0,lng = 0;
if(ll!=null){
    lat=ll.getLatitude();
    lng=ll.getLongitude();
}
System.out.println(" Last known location of device  == "+lat+"    "+lng);

InputStream iStream = null; 
HttpURLConnection urlConnection = null;
try{
    timezoneurl = timezoneurl+"location=22.7260783,75.8781553&timestamp=1331161200";                    
    // timezoneurl = timezoneurl+"location="+lat+","+lng+"&timestamp=1331161200";

    URL url = new URL(timezoneurl);                
    // Creating an http connection to communicate with url 
    urlConnection = (HttpURLConnection) url.openConnection(); 

    // Connecting to url 
    urlConnection.connect();                

    // Reading data from url 
    iStream = urlConnection.getInputStream();

    BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

    StringBuffer sb  = new StringBuffer();
    String line = "";
    while( ( line = br.readLine())  != null){
        sb.append(line);
    }
    data = sb.toString();
    br.close();

}catch(Exception e){
    Log.d("Exception while downloading url", e.toString());
}finally{
    try {
        iStream.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    urlConnection.disconnect();
}

try {
    if(data!=null){
        JSONObject jobj=new JSONObject(data);
        timezoneId = jobj.getString("timeZoneId");

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        format.setTimeZone(TimeZone.getTimeZone(timezoneId));

        Calendar cl = Calendar.getInstance(TimeZone.getTimeZone(timezoneId));
        System.out.println("time zone id in android ==  "+timezoneId);

        System.out.println("time zone of  device in android == "+TimeZone.getTimeZone(timezoneId));
        System.out.println("time fo device in android "+cl.getTime());
    }
} catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

11
Quale servizio chiami? E volevi davvero condividere le tue chiavi con noi ??
Matt Johnson-Pint,

0

Per quelli di noi che usano Javascript e cercano di ottenere un fuso orario da un codice postale tramite le API di Google , ecco un metodo.

  1. Recupera lat / lng tramite geolocalizzazione
  2. recupera il fuso orario passandolo nell'API del fuso orario .
    • Utilizzando qui Luxon per la conversione del fuso orario.

Nota: la mia comprensione è che i codici postali non sono unici in tutti i paesi, quindi questo è probabilmente il più adatto per l'uso negli Stati Uniti.

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

-2

  function jsonpRequest(url, data)
{
    let params = "";
    for (let key in data)
    {
        if (data.hasOwnProperty(key))
        {
            if (params.length == 0)
            {
                params += "?";
            }
            else
            {
                params += "&";
            }
            let encodedKey = encodeURIComponent(key);
            let encodedValue = encodeURIComponent(data[key]);
            params += encodedKey + "=" + encodedValue;
         }
    }
    let script = document.createElement('script');
    script.src = url + params;
    document.body.appendChild(script);
}

function getLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(showPosition);
  } else {
    x.innerHTML = "Geolocation is not supported by this browser.";
  }
}
let lat_ini=[]; let lon_ini=[];
function showPosition(position) {
  lat_ini= position.coords.latitude;
  lon_ini= position.coords.longitude;
}
////delay time between lines
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
///////
function getGMT()
{
  getfinalGMT()
  getLocation()
  async function sample() {
    await sleep(2000);
let lat_str=lat_ini.toString();
let lng_str=" "+lon_ini.toString();

  let url = "https://api.opencagedata.com/geocode/v1/json";
  let data = {
    callback: "displayGMT",
    q: lat_str + lng_str,
    key: "fac4471073a347019196c1291e6a97d7"
  }
  jsonpRequest(url, data)
}
 sample();
 }
let your_GMT=[];
function displayGMT(data)
{
your_GMT=(Number(data.results[0].annotations.timezone.offset_string))
console.log(your_GMT)
}
/////
function getfinalGMT()
{
let lat=document.getElementById("lat_id").value; let lng=document.getElementById("lng_id").value;
let lat_str=lat.toString();
let lng_str=" "+lng.toString();

  let url = "https://api.opencagedata.com/geocode/v1/json";
  let data = {
    callback: "displayfinalGMT",
    q: lat + lng_str,
    key: "fac4471073a347019196c1291e6a97d7"
  }
  jsonpRequest(url, data)
 }
let final_GMT=[];
function displayfinalGMT(data)
{
final_GMT=(Number(data.results[0].annotations.timezone.offset_string))
console.log(final_GMT)
}
/////clock


const hourHand = document.querySelector('[data-hour-hand]')
const minuteHand = document.querySelector('[data-minute-hand]')
const secondHand = document.querySelector('[data-second-hand]')
  let dif_overall=[];
function setClock() {
   let gmt_diff=Number(your_GMT-final_GMT)/100
   if (gmt_diff>12){
      dif_overall=gmt_diff-12
   }
   else{
     dif_overall=gmt_diff
   }
    console.log(dif_overall)
  const currentDate = new Date()
  const secondsRatio = currentDate.getSeconds() / 60
  const minutesRatio = (secondsRatio + currentDate.getMinutes()) / 60
  const hoursRatio = (minutesRatio + currentDate.getHours() - dif_overall ) / 12
  setRotation(secondHand, secondsRatio)
  setRotation(minuteHand, minutesRatio)
  setRotation(hourHand, hoursRatio)
}

function setRotation(element, rotationRatio) {
  element.style.setProperty('--rotation', rotationRatio * 360)
}
function activate_clock(){
setClock()
setInterval(setClock, 1000)
}
*, *::after, *::before {
  box-sizing: border-box;
}

body {
  background: linear-gradient(to right, hsl(200, 100%, 50%), hsl(175, 100%, 50%));
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  overflow: hidden;
}

.clock {
  width: 200px;
  height: 200px;
  background-color: rgba(255, 255, 255, .8);
  border-radius: 50%;
  border: 2px solid black;
  position: relative;
}

.clock .number {
  --rotation: 0;
  position: absolute;
  width: 100%;
  height: 100%;
  text-align: center;
  transform: rotate(var(--rotation));
  font-size: 1.5rem;
}

.clock .number1 { --rotation: 30deg; }
.clock .number2 { --rotation: 60deg; }
.clock .number3 { --rotation: 90deg; }
.clock .number4 { --rotation: 120deg; }
.clock .number5 { --rotation: 150deg; }
.clock .number6 { --rotation: 180deg; }
.clock .number7 { --rotation: 210deg; }
.clock .number8 { --rotation: 240deg; }
.clock .number9 { --rotation: 270deg; }
.clock .number10 { --rotation: 300deg; }
.clock .number11 { --rotation: 330deg; }

.clock .hand {
  --rotation: 0;
  position: absolute;
  bottom: 50%;
  left: 50%;
  border: 1px solid white;
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  transform-origin: bottom;
  z-index: 10;
  transform: translateX(-50%) rotate(calc(var(--rotation) * 1deg));
}

.clock::after {
  content: '';
  position: absolute;
  background-color: black;
  z-index: 11;
  width: 15px;
  height: 15px;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}

.clock .hand.second {
  width: 3px;
  height: 45%;
  background-color: red;
}

.clock .hand.minute {
  width: 7px;
  height: 40%;
  background-color: black;
}

.clock .hand.hour {
  width: 10px;
  height: 35%;
  background-color: black;
}














/* Background Styles Only */

@import url('https://fonts.googleapis.com/css?family=Raleway');

* {
    font-family: Raleway;
}

.side-links {
  position: absolute;
  top: 15px;
  right: 15px;
}

.side-link {
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  margin-bottom: 10px;
  color: white;
  width: 180px;
  padding: 10px 0;
  border-radius: 10px;
}

.side-link-youtube {
  background-color: red;
}

.side-link-twitter {
  background-color: #1DA1F2;
}

.side-link-github {
  background-color: #6e5494;
}

.side-link-text {
  margin-left: 10px;
  font-size: 18px;
}

.side-link-icon {
  color: white;
  font-size: 30px;
}
   <input type="text" id="lat_id" placeholder="lat"><br><br>
  <input type="text" id="lng_id" placeholder="lng"><br><br>
<button class="text" onClick="getLocation()">Location</button>
<button class="text" onClick="getGMT()"> GMT</button>
<button class="text" onClick="activate_clock()"> Activate</button>
<div class="clock">
  <div class="hand hour" data-hour-hand></div>
  <div class="hand minute" data-minute-hand></div>
  <div class="hand second" data-second-hand></div>
  <div class="number number1">1</div>
  <div class="number number2">2</div>
  <div class="number number3">3</div>
  <div class="number number4">4</div>
  <div class="number number5">5</div>
  <div class="number number6">6</div>
  <div class="number number7">7</div>
  <div class="number number8">8</div>
  <div class="number number9">9</div>
  <div class="number number10">10</div>
  <div class="number number11">11</div>
  <div class="number number12">12</div>
</div>


Ragazzi dovrete copiare e incollare il codice in un nuovo browser poiché lo snippet di codice non ci consentirà di richiedere la posizione dell'utente
Massimo

Spero che lo apprezziate, ragazzi
Massimo

Una volta immessi lat e lng, premi su posizione, GMT quindi attiva l'orologio
Massimo

Non penso davvero che avresti voluto condividere la tua chiave API con opencagedata con noi, vero? Invece di scaricare il codice, potresti semplicemente descrivere questa API.
Matt Johnson-Pint,

Bene, alcune persone hanno solo bisogno di vedere un campione della funzione di richiamata su api per capire meglio
Maximus Su

-3

Se si preferisce evitare un servizio Web, è possibile recuperare tali informazioni dal browser in questo modo:

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

Nel mio caso attuale sta stampando:

Data completa: 27/01/2014 16: 53: 37 Offset UTC : UTC-3 Codice Paese Fuso orario: BRT

Spero possa essere utile.


Mentre apprezzo che tu abbia fatto qualche sforzo in questo, ti preghiamo di realizzare: 1) I fusi orari non sono offset fissi 2) Le abbreviazioni del fuso orario non sono standardizzati o identificatori univoci 3) Questo è già stato fatto, molto più accuratamente, con jsTimeZoneDetect . 4) La tua risposta non corrisponde alla domanda. La domanda era come determinare un fuso orario dalle coordinate di latitudine e longitudine .
Matt Johnson-Pint,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.