Jak uzyskać strefę czasową z lokalizacji przy użyciu współrzędnych szerokości i długości geograficznej?

310

StackOverflow ma zbyt wiele pytań na temat rozwiązywania strefy czasowej z lokalizacji. Ta wiki społeczności jest próbą skonsolidowania wszystkich poprawnych odpowiedzi.

Zaktualizuj moją odpowiedź lub dodaj własną według własnego uznania.

Pytanie
Biorąc pod uwagę szerokość i długość geograficzną lokalizacji, skąd wiadomo, która strefa czasowa obowiązuje w tej lokalizacji?

W większości przypadków szukamy identyfikatora strefy czasowej IANA / Olson, chociaż niektóre usługi mogą zwracać tylko przesunięcie UTC lub inny identyfikator strefy czasowej. Aby uzyskać szczegółowe informacje, przeczytaj informacje o znaczniku strefy czasowej .

Matt Johnson-Pint
źródło
2
Jedną z rzeczy, które zauważyłem, jest brak jakiegokolwiek wymogu znacznika czasu UTC podczas określania strefy czasowej. Na przykład długi / lat w Londynie nie wystarczy, aby określić pogodę, strefa czasowa to GMT lub BST (brytyjskie oszczędności czasu letniego / czasu letniego). Dlatego z pewnością określ prawidłową strefę czasową, której potrzebujesz lat, long i znacznik czasu UTC.
Michael Waterfall
4
@MichaelWaterfall - Aby ustalić, czy jesteś w GMT (UTC + 0000) czy BST (UTC + 0100) - tak, masz absolutną rację. Ale są to przesunięcia stref czasowych , a nie identyfikatory stref czasowych. Oba są objęte tym samym "Europe/London"identyfikatorem strefy czasowej bazy danych stref czasowych IANA.
Matt Johnson-Pint,
Ach, w porządku, a przesunięcie czasu letniego zostanie dodane (jeśli to konieczne) po renderowaniu czasu z danym identyfikatorem strefy czasowej?
Michael Waterfall
@ Michael - to zależy od konkretnej implementacji, ale zwykle tak.
Matt Johnson-Pint,
1
Nadal może wymagać znacznika czasu UTC. Na przykład Rosja zmienia granice stref czasowych 4 razy w ciągu ostatnich 6 lat. en.wikipedia.org/wiki/Time_in_Russia
Arnial

Odpowiedzi:

421

Usługi sieciowe Lokalizacja strefy czasowej

Surowe dane graniczne strefy czasowej

  • Timezone Boundary Builder - buduje pliki kształtów stref czasowych z danych map OpenStreetMaps. Obejmuje wody terytorialne w pobliżu wybrzeży.

Następujące projekty były wcześniej źródłami danych granicznych strefy czasowej, ale nie są już aktywnie utrzymywane.

Wdrożenia geolokalizacji strefy czasowej offline

Implementacje korzystające z danych konstruktora stref czasowych

Implementacje korzystające ze starszych danych tz_world

Biblioteki wywołujące jedną z usług internetowych

  • strefa czasowa - Rubinowy klejnot, który wywołuje GeoNames
  • AskGeo ma własne biblioteki do wywoływania z Java lub .Net
  • GeoNames ma biblioteki klienta do prawie wszystkiego

Hostowane usługi sieciowe

Inne pomysły

Zaktualizuj tę listę, jeśli znasz jakieś inne

Należy również pamiętać, że podejście do najbliższego miasta może nie dać „poprawnego” wyniku, a jedynie przybliżenie.

Konwersja do stref systemu Windows

Większość wymienionych metod zwróci identyfikator strefy czasowej IANA. Jeśli chcesz przekonwertować na strefę czasową Windows, aby korzystać z TimeZoneInfoklasy w .NET, użyj TimeZoneConverter biblioteki .

Nie używaj zone.tab

Baza danych tz zawiera plik o nazwie zone.tab. Ten plik służy przede wszystkim do przedstawienia listy stref czasowych, z których użytkownik może wybrać. Obejmuje współrzędne szerokości i długości geograficznej dla punktu odniesienia dla każdej strefy czasowej. Umożliwia to utworzenie mapy z wyróżnieniem tych punktów. Na przykład zobacz interaktywną mapę pokazaną na stronie głównej strefy czasowej .

Chociaż może być kuszące, aby użyć tych danych do rozwiązania strefy czasowej na podstawie współrzędnych szerokości i długości geograficznej, należy wziąć pod uwagę, że są to punkty, a nie granice. Najlepsze, co można zrobić, to ustalić najbliższe punktu, który w wielu przypadkach nie będzie właściwym punktem.

Rozważ następujący przykład:

                            Strefa czasowa Przykład Art

Dwa kwadraty reprezentują różne strefy czasowe, w których czarna kropka na każdym kwadracie jest miejscem odniesienia, na przykład tym, co można znaleźć w zone.tab. Niebieska kropka oznacza lokalizację, dla której próbujemy znaleźć strefę czasową. Oczywiście, ta lokalizacja znajduje się w pomarańczowej strefie po lewej stronie, ale jeśli spojrzymy na najbliższą odległość do punktu odniesienia, rozwiąże się ona w strefie zielonkawej po prawej stronie.

Matt Johnson-Pint
źródło
1
GeoNames jest właściwie idealny do tego, czego potrzebuję. Dzięki!
Luke
1
@Matt Jednak, jak rozumiem, w tej chwili nie ma bazy danych offline, która zapewniłaby informacje o strefie czasowej i przesunięcie względem UTC na podstawie współrzędnych lokalizacji?
Martin
@MattJohnson, jak korzystać z bibliotek klienta
nazw geograficznych
To fantastyczna lista, dziękuję! Google wygląda na oczywisty wybór, ale zdziwiłem się, gdy dowiedziałem się, że Londyn jest w GMT, a tak naprawdę w tej chwili jest w BST. W Nowym Jorku miał poprawną letnią korektę.
lewis
8
Te nowe stawki interfejsu API Google są wymuszone. 200 próśb o 1 USD od 7/18. To 10-krotny wzrost.
Chris Lukic
8

Właśnie w Teleportie zaczęliśmy otwierać nasze interfejsy API, a jedna z przypadków użycia ujawnia również informacje TZ dla współrzędnych.

Na przykład można poprosić o wszystkie nasze dostępne informacje TZ o współrzędne w następujący sposób:

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"'

To zwróci następujące

{
  "_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"
}

Na przykład użyłem ./jq do parsowania JSON.

Joonathan
źródło
2
Dzięki za udostępnienie. Czy to podejście zbliża się do miasta, czy używasz podejścia punkt-w-wielokącie? (Zobacz mój schemat z dwoma powyższymi kwadratami.)
Matt Johnson-Pint,
3

Oto, w jaki sposób możesz użyć edytora skryptów Google, aby uzyskać strefę czasową i strefę czasową w arkuszu gsheet.

Krok 1. Uzyskaj klucz API do interfejsu Google strefy czasowej API

Krok 2. Utwórz nowy arkusz gs. W menu „Narzędzia” kliknij „Edytor skryptów”. Dodaj następujący kod:

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

Krok 3. Zapisz i opublikuj swoją getTimezone()funkcję i użyj jej, jak pokazano na powyższym obrazku.

Stiño
źródło
2

Możesz użyć pliku geolocator.js aby łatwo uzyskać strefę czasową i więcej ...

Korzysta z interfejsów API Google, które wymagają klucza. Najpierw skonfiguruj geolocator:

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

Uzyskaj TimeZone, jeśli masz współrzędne:

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

Przykładowe dane wyjściowe:

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

Zlokalizuj, a następnie uzyskaj strefę czasową i więcej

Jeśli nie masz współrzędnych, możesz najpierw zlokalizować pozycję użytkownika.

W poniższym przykładzie najpierw spróbujemy użyć interfejsu API geolokalizacji HTML5, aby uzyskać współrzędne. Jeśli zawiedzie lub zostanie odrzucony, otrzyma współrzędne poprzez wyszukiwanie Geo-IP. Wreszcie otrzyma strefę czasową i więcej ...

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

Przykładowe dane wyjściowe:

{
    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
}
Onur Yıldırım
źródło
1

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

A oto dobra implementacja wykorzystująca dane 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());
    }
}
Tinien
źródło
Czy możesz również dodać treść z linków?
Robert,
1

ujawnienie: Jestem autorem obrazka dokera opisanego poniżej

Https://github.com/evansiroky/node-geo-tz zapakowałem w bardzo prosty kontener-doker

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

Możesz uruchomić dokera-kontenera za pomocą

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

Spowoduje to wyświetlenie usługi wyszukiwania na lokalnym hoście na porcie 3000. Następnie możesz przeprowadzić wyszukiwanie w strefie czasowej

curl "localhost:3000/timezone?latitude=12&longitude=34"
Tobias Gassmann
źródło
0

Wypróbuj ten kod, aby korzystać z interfejsu API Google Time Zone z języka Java z bieżącym klientem czasu NTP i popraw konwersję UTC_Datetime_from_timestamp:

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;

}

I używaj go z:

GeoPoint gp = new GeoPoint(39.6034810,-119.6822510);
String Current_TimeZone_Time = get_time_zone_time(gp);
Ingo
źródło
1
To wygląda na dużo kodu do prostego zadania. Masz tam pełnego klienta NTP, co może być dobrym pomysłem - ale niekoniecznie jest wymagane. Czy możesz to trochę schudnąć?
Matt Johnson-Pint,
0

Ok, oto krótka wersja bez poprawnego czasu NTP:

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;

}

I używaj go z:

GeoPoint gp = new GeoPoint(39.6034810,-119.6822510);
long Current_TimeZone_Time_l = get_time_zone_time_l(gp);
Ingo
źródło
0

Jeśli chcesz użyć geonames.org, użyj tego kodu. (Ale geonames.org jest czasami bardzo wolny)

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;

 }

I używaj go z:

GeoPoint gp = new GeoPoint(39.6034810,-119.6822510);
String Current_TimeZone_Time = get_time_zone_time_geonames(gp);
Ingo
źródło
0

Od 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

Metoda związana America/Anchorage.dstzDstTzInfo

Ameryka / Anchorage 'LMT-1 dzień, 14:00:00 STD

Elchin Jafarov
źródło
Myślę, że Guppy to literówka. Masz na myśli Geopy czy coś innego?
Matt Johnson-Pint,
0

Rzeczywiście ważne jest, aby uznać, że jest to bardziej skomplikowany problem, niż większość by się spodziewała. W praktyce wielu z nas jest również gotowych zaakceptować działający zestaw kodu, który działa w „jak największej liczbie przypadków”, w których co najmniej jego krytyczne problemy można zidentyfikować i zminimalizować zbiorowo. Więc zamieszczam to z myślą o tym wszystkim i duchu OP. Wreszcie, praktyczna wartość dla innych, którzy próbują przekonwertować GPS na strefę czasową, a ostatecznym celem jest posiadanie obiektu czasowego wrażliwego na lokalizację (a co ważniejsze, aby poprawić jakość średnich implementacji za pomocą obiektów czasowych pochodzących z tej wiki) co wygenerowałem w Pythonie (prosimy o edycję):

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)
legel
źródło
Dzięki, ale wygląda to na jakiś kod, który używa pytzwhere, który jest już wymieniony w głównej odpowiedzi wiki społeczności. Jeśli chciałeś podać próbkę połączenia pytzwhere z pytz, możesz przesłać to jako PR do samego projektu pytzwhere. Po prostu szukamy rozwiązań lat / lon to tz - z których pytzwhere jest jednym z nich.
Matt Johnson-Pint
0
  1. Istnieje kilka źródeł online, które mają dane geojson dla stref czasowych ( tutaj jest jedno , oto inne)

  2. Użyj biblioteki geometrii, aby utworzyć obiekty wielokątów ze współrzędnych geojsona ( foremny [python], GEOS [c ++], JTS [java], NTS [.net]).

  3. Konwertuj swoje lat / lng na obiekt punktowy (jednak twoja biblioteka to reprezentuje) i sprawdź, czy przecina on wielokąt strefy czasowej.

    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
    
jtschoonhoven
źródło
0

używając szerokości i długości geograficznej uzyskaj strefę czasową bieżącej lokalizacji poniżej kodu, działało dla mnie

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();
}
Ghanshyam
źródło
11
Do jakiej usługi dzwonisz? Czy naprawdę chciałeś podzielić się z nami swoimi kluczami?
Matt Johnson-Pint,
0

Dla tych z nas, którzy używają Javascript i chcą uzyskać strefę czasową z kodu pocztowego za pośrednictwem interfejsów API Google , oto jedna metoda.

  1. Pobierz lat / lng przez geolokalizację
  2. pobierz strefę czasową, przekazując ją do interfejsu API strefy czasowej .
    • Używanie Luxonu tutaj do konwersji strefy czasowej.

Uwaga: rozumiem, że kody pocztowe nie są unikalne we wszystkich krajach, więc najlepiej nadaje się do użytku w 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);
Złóg
źródło
-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>

Maximus Su
źródło
Faceci będą musieli skopiować i wkleić kod w nowej przeglądarce, ponieważ fragment kodu nie pozwoli nam pytać o lokalizację użytkownika
Maximus Su
Mam nadzieję, że doceniacie to
doceniacie Maximus Su
Po wprowadzeniu lat i lng, naciśnij na lokalizację, GMT, a następnie aktywuj zegar
Maximus Su
Naprawdę nie sądzę, że chciałeś udostępnić nam swój klucz API do opencagedata, prawda? Zamiast kodu zrzutu, możesz po prostu opisać ten interfejs API.
Matt Johnson-Pint,
Cóż, niektórzy ludzie muszą zobaczyć próbkę funkcji zwrotnej do interfejsu API, aby lepiej zrozumieć
Maximus Su
-3

Jeśli wolisz unikać usługi internetowej, możesz pobrać te informacje z przeglądarki w następujący sposób:

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

W moim obecnym przypadku jest to drukowanie:

Pełna data: 27.01.2014 16: 53: 37 Przesunięcie UTC : Strefa czasowa kodu kraju UTC-3 : BRT

Mam nadzieję, że to może być pomocne.

Ja do
źródło
Doceniam, że włożyłeś w to trochę wysiłku, ale pamiętaj: 1) Strefy czasowe nie są stałymi przesunięciami 2) Skróty stref czasowych nie są znormalizowane lub unikalne identyfikatory 3) To już zostało zrobione, o wiele dokładniej, dzięki jsTimeZoneDetect . 4) Twoja odpowiedź nie pasuje do pytania. Pytanie brzmiało, jak określić strefę czasową na podstawie współrzędnych szerokości i długości geograficznej .
Matt Johnson-Pint