Як отримати часовий пояс з місця, використовуючи координати широти та довготи?


310

У StackOverflow надто багато питань щодо вирішення часового поясу з місця. Ця вікі спільноти - це спроба консолідувати всі дійсні відповіді.

Будь ласка, оновіть мою відповідь або додайте свою, як вважаєте за потрібне.

Запитання
Враховуючи широту та довготу місцеположення, як можна знати, який часовий пояс діє в цьому місці?

У більшості випадків ми шукаємо ідентифікатор часового поясу IANA / Olson, хоча деякі служби можуть повернути лише зміщення UTC або інший ідентифікатор часового поясу. Будь ласка, прочитайте інформацію тегів часового поясу для отримання детальної інформації.


2
Одне, що я помітив, - це відсутність вимоги часової позначки UTC під час визначення часового поясу. Наприклад, тривалості / лат в Лондоні недостатньо для визначення погоди часового поясу GMT або BST (літній часовий / літній час в Британії). Отже, щоб визначити правильний часовий пояс, вам потрібні lat, long та часова мітка UTC.
Водоспад Майкл

4
@MichaelWaterfall - Щоб визначити, чи перебуваєте ви в GMT (UTC + 0000) або BST (UTC + 0100) - так, ви абсолютно праві. Але це зрушення часового поясу , а не ідентифікатори часового поясу. Обидва охоплені тим самим "Europe/London"ідентифікатором часового поясу бази даних часового поясу IANA.
Метт Джонсон-Пінт

Ну гаразд, і компенсація літнього часу буде додана (якщо потрібно) після надання часу з заданим ідентифікатором часового поясу?
Водоспад Майкл

@Michael - це залежить від конкретної реалізації, але зазвичай так.
Метт Джонсон-Пінт

1
Це все ще може вимагати UTC часової позначки. Наприклад, Росія змінює межі часових поясів 4 рази за останні 6 років. en.wikipedia.org/wiki/Time_in_Russia
Арніал

Відповіді:


421

Веб-сервіси розташування часової зони

Дані про граничні часові зони

  • Timezone Boundary Builder - створює файли форм часового поясу з даних карт OpenStreetMaps. Включає територіальні води біля берегової лінії.

Наступні проекти раніше були джерелами меж часових поясів, але вони більше не підтримуються активно.

Геолокація часового поясу в режимі офлайн

Реалізації, що використовують дані будівельника часових поясів

Реалізації, що використовують старіші дані tz_world

Бібліотеки, які телефонують до однієї з веб-служб

  • часовий пояс - Ruby дорогоцінний камінь, який викликає GeoNames
  • AskGeo має власні бібліотеки для дзвінків з Java або .Net
  • GeoNames має бібліотеки клієнтів для майже всього

Самостійні веб-сервіси

Інші ідеї

Будь ласка, оновіть цей список, якщо вам відомі інші

Також зауважте, що підхід до найближчого міста може не дати "правильного" результату, а лише наближення.

Перетворення у зони Windows

Більшість перерахованих методів повертає ідентифікатор часового поясу IANA. Якщо вам потрібно перетворити у часовий пояс Windows для використання TimeZoneInfoкласу в .NET, використовуйте бібліотеку TimeZoneConverter .

Не використовуйте zone.tab

База даних tz включає файл під назвою zone.tab. Цей файл в основному використовується для подання списку часових поясів, з яких користувач може вибрати. Він включає координати широти та довготи для точки відліку для кожного часового поясу. Це дозволяє створити карту, підкреслюючи ці точки. Наприклад, див. Інтерактивну карту, показану на головній сторінці часового поясу .

Хоча може бути заманливо використовувати ці дані для вирішення часового поясу за координатами широти та довготи, врахуйте, що це точки, а не межі. Найкраще можна було б визначити найближчу точку, яка у багатьох випадках не буде правильною точкою.

Розглянемо наступний приклад:

                            Приклад часової зони ст

Два квадрати представляють різні часові пояси, де чорна крапка в кожному квадраті є опорним місцем, наприклад, те, що можна знайти в zone.tab. Синя крапка являє місце, де ми намагаємося знайти часовий пояс. Зрозуміло, що це розташування знаходиться в межах помаранчевої зони зліва, але якщо ми просто подивимось на найближчу відстань до опорної точки, воно вирішиться до зеленуватої зони праворуч.


1
GeoNames насправді ідеально підходить для того, що мені потрібно. Дякую!
Лука

1
@Matt Однак, як я розумію, на даний момент немає офлайн бази даних, яка б надала інформацію про часовий пояс і зміщення з UTC на основі координат розташування?
Мартін

@MattJohnson, як я можу використовувати бібліотеки клієнтів для геоімен
Erum,

Це фантастичний список, дякую! Google виглядає як очевидний вибір, але я був здивований, виявивши, що мені кажуть, що Лондон є в GMT, а фактично він знаходиться в BST. Для Нью-Йорка це було правильне літнє регулювання.
lewis

8
Ці нові ставки API Google є вимагаючими. 200 запитів на 1 долар станом на 7/18. Це 10-кратне збільшення.
Кріс Лукич


8

Ми в Teleport тільки почали відкривати API, і один із випадків використання також відкриває TZ для координат.

Наприклад, можна запитати всю нашу доступну інформацію про ТЗ для координат таким чином:

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

Це поверне наступне

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

Для прикладу, який я використав ./jq для розбору JSON.


2
Дякую, що поділились. Чи це підхід до найближчого міста, чи ви використовуєте підхід «в полігоні»? (Дивіться мою схему з двома квадратами вище.)
Метт Джонсон-Пінт

3

Ось як можна скористатися редактором сценаріїв Google, щоб отримати timezoneName та timeZoneId всередині gsheet.

Крок 1. Отримайте ключ API для API часового поясу Google

Крок 2. Створіть новий gsheet. Під меню "інструменти" натисніть "Редактор сценаріїв". Додайте наступний код:

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

Крок 3. Збережіть та опублікуйте свою getTimezone()функцію та використовуйте її, як показано на зображенні вище.


2

Ви можете використовувати geolocator.js для легкого отримання часового поясу та іншого ...

Він використовує API Google, для яких потрібен ключ. Отже, спочатку ви налаштуєте геолокатор:

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

Отримайте TimeZone, якщо у вас є координати:

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

Приклад виводу:

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

Знайдіть, потім отримайте TimeZone та багато іншого

Якщо у вас немає координат, ви можете спочатку знайти позицію користувача.

Наведений нижче приклад спочатку спробує API геолокації HTML5 для отримання координат. Якщо він не вдасться або відхилиться, він отримає координати через гео-IP-пошук. Нарешті, він отримає часовий пояс і більше ...

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

Приклад виводу:

{
    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

І ось хороша реалізація за допомогою даних 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());
    }
}

Чи можете ви також додавати якийсь вміст із посилань?
Роберт

1

розкриття: Я є автором докерного зображення, описаного нижче

Я загорнув https://github.com/evansiroky/node-geo-tz у дуже просту докер-контейнер

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

Можна запустити докер-контейнер за допомогою

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

Це відкриває службу пошуку на вашому localhost на порту 3000. Потім ви можете виконати пошук часових поясів, виконавши

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

0

Спробуйте цей код для використання API часової зони Google від Java з поточним клієнтом часу NTP та правильним перетворенням 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;

}

І використовувати його з:

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

1
Це здається великою кількістю коду для простого завдання. У вас є повний клієнт NTP, що може бути хорошою ідеєю - але це не обов'язково. Ви можете трохи зменшити, будь ласка?
Метт Джонсон-Пінт

0

Ок, ось коротка версія без правильного часу 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;

}

І використовувати його з:

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

0

Якщо ви хочете використовувати geonames.org, тоді використовуйте цей код. (Але geonames.org іноді дуже повільний)

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;

 }

І використовувати його з:

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

0

Від Гуппі:

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

Пов'язаний метод America/Anchorage.dstзDstTzInfo

Америка / Анкоридж 'LMT-1 день, 14:00:00 STD


Я думаю, що Гуппі - це помилка. Ви маєте на увазі Геопію чи щось інше?
Метт Джонсон-Пінт

0

Дійсно важливо визнати, що це проблема складніша, ніж більшість підозрює. На практиці багато хто з нас також готові прийняти робочий набір коду, який працює на «якомога більше випадків», де хоча б його фатальні проблеми можна визначити та мінімізувати колективно. Тож я розміщую це з урахуванням всього цього і духу ОП на увазі. Нарешті, для практичної цінності для інших, хто намагається перетворити GPS у часовий пояс з кінцевою метою - встановити часовий об’єкт, залежний від місця розташування (і що ще важливіше - сприяти підвищенню якості середніх реалізацій із часовими об'єктами, які випливають з цієї вікі) ось що я створив у Python (будь ласка, не соромтесь редагувати):

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)

Дякую, але це виглядає як якийсь код, який використовує pytzwhere, який уже вказаний у головній відповіді вікі спільноти. Якщо ви мали намір надати зразок того, як поєднувати pytzwhere з pytz, ви можете подати це як PR до самого проекту pytzwhere. Тут ми просто шукаємо рішення lat / lon to tz - з яких pytzwhere є одним із них.
Метт Джонсон-Пінт

0
  1. В Інтернеті є кілька джерел, які мають дані про geojson для часових поясів ( ось одне , ось інше)

  2. Використовуйте бібліотеку геометрії для створення полігональних об'єктів з координат GeoJSON ( стрункий [Python], ГЕОС [C ++], JTS [Java], НГС [.net]).

  3. Перетворіть lat / lng в точковий об’єкт (однак ваша бібліотека представляє це) і перевірте, чи він перетинає полігон часового поясу.

    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

використовуючи широту і довготу отримати часовий пояс поточного місцезнаходження нижче коду, який працював для мене

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
Яку послугу ви телефонуєте? А ти справді хотів поділитися своїми ключами з нами ??
Метт Джонсон-Пінт

0

Для тих із нас, хто використовує Javascript і прагне отримати часовий пояс із поштового коду через API Google , ось один спосіб.

  1. Отримати lat / lng за допомогою геолокації
  2. отримати часовий пояс, передавши його в API часового поясу .
    • Використання Луксона тут для перетворення часових поясів.

Примітка: я розумію, що поштові індекси не є унікальними для всіх країн, тому це, ймовірно, найкраще підходить для використання в США.

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>


Хлопці, вам доведеться скопіювати та вставити код у новий веб-переглядач, оскільки фрагмент коду не дозволить нам підказувати місцезнаходження користувача
Maximus Su

Сподіваюся, ви, хлопці, оціните це
Максимус Су

Як тільки введіть lat і lng, натисніть на розташування, GMT, потім активуйте годинник
Maximus Su

Я насправді не думаю, що ти мав намір поділитися з нами своїм ключем API, щоб відкрити календарі, чи не так? Замість демпінгового коду ви можете просто описати цей API.
Метт Джонсон-

Ну, деяким людям просто потрібно побачити зразок функції зворотного виклику, щоб апі краще зрозуміти
Maximus Su

-3

Якщо ви хочете уникати веб-сервісу, ви можете отримати цю інформацію з браузера на зразок цього:

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

У моєму випадку це друк:

Повна дата: 27.01.2014 16: 53: 37 UTC Зсув: UTC-3 Код країни Часовий пояс: BRT

Сподіваюся, це може бути корисним.


Хоча я ціную, що ви доклали певних зусиль для цього, будь ласка, усвідомте: 1) Часові пояси не є фіксованими компенсаціями 2) Скорочення часових поясів не стандартизовані або унікальні ідентифікатори 3) Це вже зроблено, набагато точніше, за допомогою jsTimeZoneDetect . 4) Ваша відповідь не відповідає питанню. Питання полягало в тому, як визначити часовий пояс за координатами широти та довготи .
Метт Джонсон-Пінт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.