it-swarm.com.de

Bestimmen Sie die Zeitzone aus Breite/Länge, ohne Webdienste wie Geonames.org zu verwenden

gibt es eine Möglichkeit, die Zeitzone des Punktes (lat/lon) ohne Webservices zu bestimmen? Geonames.org ist nicht stabil genug für mich :( Ich brauche das, um in PHP zu arbeiten.

Vielen Dank

49
Jacek Francuz

Ich hatte dieses Problem vor einiger Zeit und tat genau das, was Adam vorgeschlagen hatte:

  • Laden Sie die Datenbank der Städte von geonames.org herunter
  • konvertiere es in eine kompakte lat/lon -> timezone liste
  • verwenden Sie eine R-Tree -Implementierung, um effizient nach der nächstgelegenen Stadt (bzw. ihrer Zeitzone) zu einer bestimmten Koordinate zu suchen

Mit dem IIRC dauerte es weniger als 1 Sekunde, um den R-Tree zu füllen, und er konnte dann Tausende von Suchvorgängen pro Sekunde durchführen (beide auf einem 5 Jahre alten PC).

54

Wie genau müssen Ihre Ergebnisse sein? Wenn eine grobe Schätzung ausreicht, berechnen Sie den Versatz selbst:

offset = direction * longitude * 24 / 360

die Richtung ist 1 für Ost, -1 für West und der Längengrad ist in (-180,180).

Ich bin auf dieses Problem gestoßen, als ich an einem anderen Projekt gearbeitet habe, und habe mich eingehend damit beschäftigt. Ich habe festgestellt, dass alle bestehenden Lösungen in erheblichem Maße fehlen. 

Das Herunterladen der GeoNames-Daten und die Verwendung eines räumlichen Index zum Suchen des nächstgelegenen Punkts ist definitiv eine Option. Sie liefert das korrekte Ergebnis häufig, kann jedoch leicht fehlschlagen, wenn sich ein Abfragepunkt auf der falschen Seite einer Zeit befindet Zonengrenze vom nächstgelegenen Punkt in der Datenbank.

Eine genauere Methode ist die Verwendung einer digitalen Karte der Zeitzonen und das Schreiben von Code, um das Polygon in der Karte zu finden, das einen bestimmten Abfragepunkt enthält. Zum Glück gibt es unter http://efele.net/maps/tz/world/ eine ausgezeichnete Karte der Zeitzonen der Welt. Um eine effiziente Abfrage-Engine zu schreiben, müssen Sie:

  • Analysieren Sie das ESRI-Shapefile-Format in eine nützliche interne Darstellung.
  • Schreiben Sie einen Punkt-in-Polygon-Code, um zu testen, ob sich ein bestimmter Abfragepunkt in einem bestimmten Polygon befindet.
  • Schreiben Sie einen effizienten räumlichen Index auf die Polygondaten, sodass Sie nicht jedes Polygon überprüfen müssen, um das enthaltende zu finden.
  • Behandeln Sie Abfragen, die nicht in einem Polygon enthalten sind (z. B. im Ozean). In solchen Fällen sollten Sie das nächstgelegene Polygon bis zu einer bestimmten Entfernung "einrasten" und zur "natürlichen" Zeitzone (die nur durch die Länge allein bestimmte Zeitzone) auf dem offenen Meer zurückkehren. Dazu benötigen Sie Code, um den Abstand zwischen einem Abfragepunkt und einem Liniensegment eines Polygons zu berechnen (dies ist nicht trivial, da Breitengrad und Längengrad ein nicht-euklidisches Koordinatensystem sind), und Ihr räumlicher Index muss erforderlich sein in der Nähe befindliche Polygone zurückgeben können, nicht nur potentiell Polygone enthalten.

Jeder von ihnen verdient eine eigene Frage-/Antwortseite für den Stapelüberlauf.

Nachdem ich zu dem Schluss gekommen war, dass keine der existierenden Lösungen meine Bedürfnisse erfüllte, schrieb ich meine eigene Lösung und stellte sie hier zur Verfügung:

http://askgeo.com

AskGeo verwendet eine digitale Karte und verfügt über einen stark optimierten räumlichen Index, mit dem auf meinem Computer in einem einzigen Thread mehr als 10.000 Abfragen pro Sekunde ausgeführt werden können. Und es ist fadensicher, so dass sicherlich auch ein höherer Durchsatz möglich ist. Dies ist ein ernstzunehmender Teil des Codes, und die Entwicklung hat lange gedauert. Daher bieten wir ihn unter einer kommerziellen Lizenz an. 

Es ist in Java geschrieben, sodass es in PHP verwendet werden kann:

http://php-Java-bridge.sourceforge.net/doc/how_it_works.php

Wir sind auch offen, um es für eine Belohnung zu portieren. Einzelheiten zu den Preisen und eine ausführliche Dokumentation finden Sie unter http://askgeo.com .

Ich hoffe das ist nützlich. Es war auf jeden Fall nützlich für das Projekt, an dem ich arbeitete.

10
James D

Ich weiß, das ist alt, aber ich habe einige Zeit damit verbracht, nach dieser Antwort zu suchen. Etwas sehr Nützliches gefunden. Google sucht nach Zeitzonen in Long/Lat. Limit von 2.500 pro Tag (oder 100.000 für Geschäftsbenutzer).

https://developers.google.com/maps/documentation/timezone/

8
Jeffrey Vdovjak

Sie sollten in der Lage sein, wenn Sie das Polygon der Zeitzone kennen, um zu sehen, ob sich ein bestimmter Lat/Lon in der Zeitzone befindet.

Weltzeitzoneenter image description here

Breiten Längengrad-Polygondaten -/enter image description here

5
daniellmb

Für Gebiete an Land gibt es einige Shapefile-Karten , die für die Zeitzonen der Datenbank tz (Olson) erstellt wurden. Sie werden nicht so regelmäßig wie die tz-Datenbank selbst aktualisiert, aber sie ist ein guter Ausgangspunkt und scheint für die meisten Zwecke sehr genau zu sein.

5
Tim Parenti

Wie wäre es damit ?

// [email protected]

function get_nearest_timezone($cur_lat, $cur_long, $country_code = '') {
    $timezone_ids = ($country_code) ? DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $country_code)
                                    : DateTimeZone::listIdentifiers();

    if($timezone_ids && is_array($timezone_ids) && isset($timezone_ids[0])) {

        $time_zone = '';
        $tz_distance = 0;

        //only one identifier?
        if (count($timezone_ids) == 1) {
            $time_zone = $timezone_ids[0];
        } else {

            foreach($timezone_ids as $timezone_id) {
                $timezone = new DateTimeZone($timezone_id);
                $location = $timezone->getLocation();
                $tz_lat   = $location['latitude'];
                $tz_long  = $location['longitude'];

                $theta    = $cur_long - $tz_long;
                $distance = (sin(deg2rad($cur_lat)) * sin(deg2rad($tz_lat))) 
                + (cos(deg2rad($cur_lat)) * cos(deg2rad($tz_lat)) * cos(deg2rad($theta)));
                $distance = acos($distance);
                $distance = abs(rad2deg($distance));
                // echo '<br />'.$timezone_id.' '.$distance; 

                if (!$time_zone || $tz_distance > $distance) {
                    $time_zone   = $timezone_id;
                    $tz_distance = $distance;
                } 

            }
        }
        return  $time_zone;
    }
    return 'none?';
}
//timezone for one NY co-ordinate
echo get_nearest_timezone(40.772222,-74.164581) ;
// more faster and accurate if you can pass the country code 
echo get_nearest_timezone(40.772222, -74.164581, 'US') ;
3
j-bin

Ich habe dazu eine kleine Java-Klasse geschrieben. Es könnte leicht in PHP übersetzt werden. Die Datenbank ist in den Code selbst eingebettet. Es ist auf 22km genau.

https://sites.google.com/a/edval.biz/www/mapping-lat-lng-s-to-timezones

Der ganze Code ist im Wesentlichen so:

         if (lng < -139.5) {
          if (lat < 68.5) {
           if (lng < -140.5) {
            return 371;
           } else {
            return 325;
           }

Ich gehe davon aus, dass eine Übersetzung in PHP einfach wäre.

2
Tim Cooper

Eine andere Lösung besteht darin, eine Tabelle mit Städten mit Zeitzonen zu importieren und dann die Haversine-Formel zu verwenden, um die nächstgelegene Stadt in dieser Tabelle zu finden, die für Ihre Koordinaten relevant ist .. Ich habe hier eine vollständige Beschreibung veröffentlicht: http: // sylnsr .blogspot.com/2012/12/find-next-location-by-width-and.html

Für ein Beispiel zum Laden der Daten in MySQL habe ich hier ein Beispiel gepostet (mit Quellen zum Herunterladen eines kleinen Daten-Dumps): http://sylnsr.blogspot.com/2012/12/load-timezone-data-by -Stadt-und-Land.html

Beachten Sie, dass die Genauigkeit der Suche davon abhängt, wie umfassend Ihre Suchdaten sind.

Danksagungen und Referenzen: MySQL-Großkreisentfernung (Haversine-Formel)

1
MikeM

Leider sind Zeitzonen für einige einfache Funktionen nicht regelmäßig genug. Siehe Karte in Wikipedia - Zeitzone

Einige sehr grobe Annäherungen können jedoch berechnet werden: 1 Stunde Differenz entspricht 15 Längengrad (360/24).

1
MillKa

Ich bin nicht sicher, ob dies nützlich ist oder nicht, aber ich habe eine Datenbank mit Zeitzonenformen (nur für Nordamerika) erstellt, die nicht nur für Grenzen, sondern auch für die Sommerzeit äußerst genau und aktuell ist. Formen auch für inoffizielle Ausnahmen. Sie könnten also den Satz von Formen für eine bestimmte Position abfragen, mehrere für diese Position zutreffende Formen zurückgeben und die richtige für die Jahreszeit auswählen.

Sie können ein Bild der Formen unter http://OnTimeZone.com/OnTimeZone_shapes.gif sehen. Bei blauen Formen handelt es sich um Bereiche, in denen die Sommerzeit nicht berücksichtigt wird. Bei Magenta werden die Bereiche verwendet, in denen die Sommerzeit berücksichtigt wird. Neongrüne Formen (klein und bei dieser Zoomstufe schwer zu erkennen) sind für Bereiche mit inoffiziellen Abweichungen von der offiziellen Zeitzone. Viel mehr Details dazu auf der OnTimeZone.com-Site.

Die auf OnTimeZone.com zum Download verfügbaren Daten sind für den nichtkommerziellen Gebrauch kostenlos. Die Formdaten, die nicht zum Download zur Verfügung stehen, sind für eine kommerzielle Lizenz erhältlich.

1
Steve

Sie können die hier angegebenen Zeitzonengrenzen verwenden:

http://www.opensource.Apple.com/source/TimeZoneData/

Ich habe Daten heruntergeladen, die 5-stellige Postleitzahlen für Zeitzonen enthalten, und Daten, die den UTC-Versatz für jede Zeitzone während DST- und Nicht-DST-Zeiträumen bestimmen.

Dann habe ich die Daten vereinfacht, um nur die ersten drei Ziffern der Postleitzahl zu berücksichtigen, da alle Postleitzahlen, die die ersten drei Ziffern teilen, sehr nahe beieinander liegen. Die drei Ziffern kennzeichnen ein eindeutiges Postverteilungszentrum.

Die resultierende Json-Datei verlangt von Ihnen, zu entscheiden, ob Sie derzeit DST unterliegen oder nicht, und es hat wahrscheinlich hier und da einige Ungenauigkeiten. Es ist jedoch eine ziemlich gute lokale Lösung, die sehr kompakt und einfach abzufragen ist.

Hier ist es: https://Gist.github.com/benjiwheeler/8aced8dac396c2191cf0

0
Ben Wheeler
You can get the timezone based on the location in javascript.

function initAutocomplete() {
        // Create the autocomplete object, restricting the search to geographical
        // location types.
        autocomplete = new google.maps.places.Autocomplete(
                /** @type {!HTMLInputElement} */(document.getElementById('Location')),
                {types: ['geocode']});

        // When the user selects an address from the dropdown, populate the address
        // fields in the form.
        autocomplete.addListener('place_changed', fillInAddress);
    }

    function fillInAddress() {
        // Get the place details from the autocomplete object.
        var place = autocomplete.getPlace();

        fnGettimezone($('#Location').serialize());
        for (var component in componentForm) {
            document.getElementById(component).value = '';
            document.getElementById(component).disabled = false;
        }

        // Get each component of the address from the place details
        // and fill the corresponding field on the form.
        for (var i = 0; i < place.address_components.length; i++) {
            var addressType = place.address_components[i].types[0];
            if (componentForm[addressType]) {
                var val = place.address_components[i][componentForm[addressType]];
                document.getElementById(addressType).value = val;
            }
        }

    }


function fnGettimezone(location) {
    $.ajax({
            url: "http://maps.googleapis.com/maps/api/geocode/json?address=" + location + "&sensor=false",
            dataType: 'json',
            success: function (result) {
                 console.log(result);
                // result is already a parsed javascript object that you could manipulate directly here
                var myObject = JSON.parse(JSON.stringify(result));
                lat = myObject.results[0].geometry.location.lat;
                lng = myObject.results[0].geometry.location.lng;
                console.log(myObject);

                $.ajax({
                    url: "https://maps.googleapis.com/maps/api/timezone/json?location=" + lat + "," + lng + "&timestamp=1331161200&sensor=false",
                    dataType: 'json',
                    success: function (result) {
                        // result is already a parsed javascript object that you could manipulate directly here
                        var myObject = JSON.parse(JSON.stringify(result));
                        $('#timezone').val(myObject.timeZoneName);

                    }
                });

            }
        });
    }
0
Ummar farook P

Dieses Projekt erstellt ein Shapefile aus Daten von OpenStreetMap und verlinkt auf mehrere Bibliotheken, die damit umgehen. Für PHP können Sie nachsehen unter https://github.com/minube/geo-timezone

0
vwvw

Ich benutze geocoder.ca

Geben Sie einen beliebigen Ort in Nordamerika, Ausgabe-Geocodes, Ortsvorwahlen und Zeitzonen in Json oder Jsonp ein.

Zum Beispiel: http://geocoder.ca/1600%20pennsylvania%20avenue,Washington,DC

Vorwahl: (202) Zeitzone: America/New_York

Json: 

{"standard":{"staddress":"Pennsylvania Ave","stnumber":"1600","prov":"DC","city":"WASHINGTON","postal":"20011","confidence":"0.8"},"longt":"-76.972948","TimeZone":"America/New_York","AreaCode":"202","latt":"38.874533"}
0
Ervin Ruci

Sie können Google Timezone-API verwenden. https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

{
   "dstOffset" : 0,
   "rawOffset" : -28800,
   "status" : "OK",
   "timeZoneId" : "America/Los_Angeles",
   "timeZoneName" : "Pacific Standard Time"
}
0
Sheena Singla