Làm cách nào để có được múi giờ từ một vị trí bằng tọa độ kinh độ và vĩ độ?


310

Có quá nhiều câu hỏi trên StackOverflow về việc giải quyết múi giờ từ một vị trí. Wiki cộng đồng này là một nỗ lực để hợp nhất tất cả các phản hồi hợp lệ.

Vui lòng cập nhật câu trả lời của tôi, hoặc thêm câu trả lời của bạn khi bạn thấy phù hợp.

Câu hỏi
Đưa ra vĩ độ và kinh độ của một địa điểm, làm thế nào để biết múi giờ nào có hiệu lực ở vị trí đó?

Trong hầu hết các trường hợp, chúng tôi đang tìm kiếm id múi giờ IANA / Olson, mặc dù một số dịch vụ có thể chỉ trả về phần bù UTC hoặc một số định danh múi giờ khác. Vui lòng đọc thông tin thẻ múi giờ để biết chi tiết.


2
Một điều tôi nhận thấy là thiếu bất kỳ yêu cầu dấu thời gian UTC nào khi xác định múi giờ. Chẳng hạn, thời gian dài / muộn ở Luân Đôn không đủ để xác định thời tiết múi giờ là GMT hoặc BST (Tiết kiệm thời gian mùa hè / ánh sáng ban ngày của Anh). Vì vậy, chắc chắn để xác định múi giờ chính xác mà bạn cần lat, long và dấu thời gian UTC.
Thác nước Michael

4
@MichaelWaterfall - Để xác định xem bạn đang ở GMT (UTC + 0000) hay BST (UTC + 0100) - có, bạn hoàn toàn chính xác. Nhưng đó là những độ lệch múi giờ , không phải là định danh múi giờ. Cả hai đều được bao phủ bởi cùng một "Europe/London"định danh múi giờ của cơ sở dữ liệu múi giờ IANA.
Matt Johnson-Pint

À không sao, và phần bù tiết kiệm ánh sáng ban ngày sẽ được thêm vào (nếu cần) sau khi hiển thị thời gian bằng một định danh múi giờ nhất định?
Thác nước Michael

@Michael - điều đó phụ thuộc vào việc thực hiện cụ thể, nhưng thông thường, có.
Matt Johnson-Pint

1
Nó vẫn có thể yêu cầu dấu thời gian UTC. Ví dụ, Nga thay đổi ranh giới múi giờ 4 lần trong 6 năm qua. vi.wikipedia.org/wiki/Time_in_Russia
Arnial

Câu trả lời:


422

Dịch vụ web Vị trí múi giờ

Dữ liệu Ranh giới Múi giờ thô

Các dự án sau đây trước đây là nguồn dữ liệu ranh giới múi giờ, nhưng không còn được duy trì tích cực.

  • tz_world - dữ liệu shapefile gốc từ Eric Muller
  • whereonearth-timezone - Phiên bản GeoJSON với dữ liệu WOEDB được hợp nhất trong

Định vị ngoại tuyến theo múi giờ

Việc triển khai sử dụng dữ liệu Trình tạo ranh giới múi giờ

Việc triển khai sử dụng dữ liệu tz_world cũ hơn

Các thư viện gọi một trong các dịch vụ web

  • múi giờ - Đá quý Ruby gọi GeoNames
  • AskGeo có các thư viện riêng để gọi từ Java hoặc .Net
  • GeoNames có thư viện khách cho tất cả mọi thứ

Dịch vụ web tự lưu trữ

Những ý tưởng khác

Vui lòng cập nhật danh sách này nếu bạn biết bất kỳ người nào khác

Ngoài ra, lưu ý rằng cách tiếp cận thành phố gần nhất có thể không mang lại kết quả "chính xác", chỉ là một xấp xỉ.

Chuyển đổi sang các khu vực Windows

Hầu hết các phương thức được liệt kê sẽ trả về id múi giờ IANA. Nếu bạn cần chuyển đổi sang múi giờ Windows để sử dụng với TimeZoneInfolớp trong .NET, hãy sử dụng thư viện TimeZoneConverter .

Đừng sử dụng area.tab

sở dữ liệu tz bao gồm một tệp được gọi zone.tab. Tập tin này chủ yếu được sử dụng để trình bày danh sách các múi giờ để người dùng chọn. Nó bao gồm các tọa độ vĩ độ và kinh độ cho điểm tham chiếu cho từng múi giờ. Điều này cho phép một bản đồ được tạo ra làm nổi bật những điểm này. Ví dụ: xem bản đồ tương tác được hiển thị trên trang chủ của múi giờ .

Mặc dù có thể rất hấp dẫn khi sử dụng dữ liệu này để giải quyết múi giờ từ tọa độ kinh độ và vĩ độ, hãy xem xét rằng đây là các điểm - không phải là ranh giới. Điều tốt nhất có thể làm là xác định điểm gần nhất , trong nhiều trường hợp sẽ không phải là điểm chính xác.

Hãy xem xét ví dụ sau:

                            Nghệ thuật ví dụ múi giờ

Hai hình vuông đại diện cho các múi giờ khác nhau, trong đó chấm đen trong mỗi hình vuông là vị trí tham chiếu, chẳng hạn như những gì có thể tìm thấy trong zone.tab. Dấu chấm màu xanh biểu thị vị trí chúng tôi đang cố gắng tìm múi giờ. Rõ ràng, vị trí này nằm trong vùng màu cam ở bên trái, nhưng nếu chúng ta chỉ nhìn vào khoảng cách gần nhất đến điểm tham chiếu, nó sẽ phân giải thành vùng màu lục bên phải.


1
GeoNames thực sự hoàn hảo cho những gì tôi cần. Cảm ơn!
Luke

1
@Matt Tuy nhiên, theo tôi hiểu, hiện tại không có cơ sở dữ liệu ngoại tuyến nào cung cấp thông tin múi giờ và bù đắp từ UTC dựa trên tọa độ vị trí?
Martin

@MattJohnson làm cách nào tôi có thể sử dụng thư viện máy khách geonames
Erum

Đây là một danh sách tuyệt vời, cảm ơn bạn! Google có vẻ như là sự lựa chọn rõ ràng, nhưng tôi đã rất ngạc nhiên khi thấy họ nói với tôi rằng London đang ở GMT, trong khi thực tế nó đang ở BST vào lúc này. Đối với New York, nó đã có sự điều chỉnh mùa hè chính xác.
lewis

8
Các tỷ lệ Google API mới này đang bị tống tiền. 200 yêu cầu $ 1 kể từ ngày 18 tháng 7. Đó là mức tăng gấp 10 lần.
Chris Lukic


8

Chúng tôi tại Teleport mới bắt đầu mở API của chúng tôi và một trong những giai đoạn cũng đang tiết lộ thông tin TZ cho tọa độ.

Ví dụ: người ta có thể yêu cầu tất cả thông tin TZ có sẵn của chúng tôi cho tọa độ theo cách sau:

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

Điều này sẽ trả lại như sau

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

Ví dụ tôi đã sử dụng ./jq để phân tích cú pháp JSON.


2
Cám ơn vì đã chia sẻ. Có phải đó là cách tiếp cận thành phố gần nhất, hay bạn đang sử dụng cách tiếp cận điểm đa giác? (Xem sơ đồ của tôi với hai hình vuông ở trên.)
Matt Johnson-Pint

3

Dưới đây là cách bạn có thể sử dụng trình chỉnh sửa tập lệnh của Google để lấy timezoneName và timeZoneId bên trong một trang tính.

Bước 1. Nhận khóa API cho API múi giờ của Google

Bước 2. Tạo một bảng tính mới. Bên dưới trình đơn 'công cụ', nhấp vào 'trình chỉnh sửa tập lệnh'. Thêm mã sau đây:

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

Bước 3. Lưu và xuất bản getTimezone()chức năng của bạn và sử dụng nó như thể hiện trong hình trên.


2

Bạn có thể sử dụng geolocator.js để dễ dàng lấy múi giờ và hơn thế nữa ...

Nó sử dụng Google API yêu cầu khóa. Vì vậy, trước tiên, bạn định cấu hình trình định vị địa lý:

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

Nhận TimeZone nếu bạn có tọa độ:

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

Ví dụ đầu ra:

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

Xác định vị trí sau đó nhận TimeZone và hơn thế nữa

Nếu bạn không có tọa độ, bạn có thể xác định vị trí người dùng trước.

Ví dụ bên dưới trước tiên sẽ thử API vị trí địa lý HTML5 để lấy tọa độ. Nếu thất bại hoặc bị từ chối, nó sẽ nhận được tọa độ thông qua tra cứu Geo-IP. Cuối cùng, nó sẽ có được múi giờ và hơn thế nữa ...

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

Ví dụ đầu ra:

{
    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

Và đây là một triển khai tốt khi sử dụng dữ liệu 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());
    }
}

Bạn cũng có thể thêm một số nội dung từ các liên kết?
Robert

1

tiết lộ: Tôi là tác giả của hình ảnh docker được mô tả dưới đây

Tôi đã gói https://github.com/evansiroky/node-geo-tz trong một container-docker rất đơn giản

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

Bạn có thể khởi động docker-container với

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

Điều này hiển thị dịch vụ tra cứu trên localhost của bạn trên cổng 3000. Sau đó, bạn có thể thực hiện tra cứu múi giờ bằng cách

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

0

Hãy thử mã này để sử dụng API múi giờ của Google từ Java với Máy khách thời gian NTP hiện tại và chuyển đổi UTC_Datetime_from_timestamp chính xác:

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;

}

Và sử dụng nó với:

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

1
Điều này có vẻ như rất nhiều mã cho một nhiệm vụ đơn giản. Bạn đã có một máy khách NTP đầy đủ trong đó, đó có thể là một ý tưởng tốt - nhưng không nhất thiết phải có. Bạn có thể giảm nó xuống một chút xin vui lòng?
Matt Johnson-Pint

0

Ok đây là phiên bản ngắn mà không có thời gian NTP chính xác:

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;

}

Và sử dụng nó với:

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

0

Nếu bạn muốn sử dụng geonames.org thì hãy sử dụng mã này. (Nhưng đôi khi geonames.org rất chậm)

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;

 }

Và sử dụng nó với:

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

0

Từ cá bảy màu:

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

Phương pháp giới hạn America/Anchorage.dstcủaDstTzInfo

LMT-1 của Mỹ / Neo, 14:00:00 STD


Tôi nghĩ Guppy là một lỗi đánh máy. Bạn có nghĩa là Geopy hoặc cái gì khác?
Matt Johnson-Pint

0

Điều thực sự quan trọng để nhận ra rằng đây là một vấn đề phức tạp hơn hầu hết mọi người sẽ nghi ngờ. Trong thực tế, nhiều người trong chúng ta cũng sẵn sàng chấp nhận một bộ mã làm việc cho "càng nhiều trường hợp càng tốt", trong đó ít nhất các vấn đề nghiêm trọng của nó có thể được xác định và giảm thiểu tập thể. Vì vậy, tôi đăng bài này với tất cả điều đó và tinh thần của OP trong tâm trí. Cuối cùng, để có giá trị thực tế cho những người khác đang cố gắng chuyển đổi GPS thành múi giờ với mục tiêu cuối cùng là có một đối tượng thời gian nhạy cảm với vị trí (và quan trọng hơn là giúp nâng cao chất lượng triển khai trung bình với các đối tượng thời gian theo wiki này) ở đây là những gì tôi đã tạo trong Python (xin vui lòng chỉnh sửa):

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)

Cảm ơn, nhưng điều này trông giống như một số mã sử dụng pytzwhere đã được liệt kê trong câu trả lời wiki cộng đồng chính. Nếu bạn có ý định cung cấp một mẫu về cách kết hợp pytzwhere với pytz, bạn có thể muốn gửi nó dưới dạng PR cho chính dự án pytzwhere. Ở đây chúng tôi chỉ tìm kiếm các giải pháp lat / lon to tz - trong đó pytzwhere là một trong số đó.
Matt Johnson-Pint

0
  1. Có một số nguồn trực tuyến có dữ liệu Geojson cho các múi giờ ( đây là một , đây là một nguồn khác)

  2. Sử dụng một thư viện hình học để tạo các đối tượng đa giác từ các tọa độ GeoJSON ( quyến rũ [python], GEOS [c ++], JTS [java], NTS [.net]).

  3. Chuyển đổi lat / lng của bạn thành một đối tượng điểm (tuy nhiên thư viện của bạn đại diện cho điều đó) và kiểm tra xem nó có giao nhau với đa giác múi giờ không.

    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

bằng cách sử dụng vĩ độ và kinh độ lấy múi giờ của vị trí hiện tại bên dưới mã làm việc cho tôi

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
Bạn đang gọi dịch vụ nào? Và bạn có thực sự muốn chia sẻ chìa khóa của bạn với chúng tôi ??
Matt Johnson-Pint

0

Đối với những người trong chúng ta sử dụng Javascript và đang tìm cách lấy múi giờ từ mã zip thông qua Google API , đây là một phương pháp.

  1. Tìm nạp lat / lng qua định vị địa lý
  2. tìm nạp múi giờ bằng cách chuyển nó vào API múi giờ .
    • Sử dụng Luxon ở đây để chuyển đổi múi giờ.

Lưu ý: sự hiểu biết của tôi là mã zip không phải là duy nhất trên khắp các quốc gia, vì vậy điều này có thể phù hợp nhất để sử dụng ở Hoa Kỳ.

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>


Các bạn sẽ phải sao chép và dán mã vào một trình duyệt mới vì đoạn mã sẽ không cho phép chúng tôi nhắc về vị trí của người dùng
Maximus Su

Hy vọng các bạn đánh giá cao nó
Maximus Su

Sau khi nhập lat và lng, nhấn vào vị trí, GMT sau đó kích hoạt đồng hồ
Maximus Su

Tôi thực sự không nghĩ rằng bạn muốn chia sẻ khóa API của bạn với opencagedata với chúng tôi, phải không? Thay vì bán mã, bạn chỉ cần mô tả API này.
Matt Johnson-Pint

Chà, một số người chỉ cần xem một mẫu hàm gọi lại để api để hiểu rõ hơn
Maximus Su

-3

Nếu bạn muốn tránh một dịch vụ web, bạn có thể truy xuất thông tin đó từ trình duyệt như thế này:

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

Trong trường hợp hiện tại của tôi, nó đang in:

Ngày đầy đủ: 27/01/2014 16: 53: 37 Offset UTC : UTC-3 Mã múi giờ quốc gia: BRT

Hy vọng nó có thể hữu ích.


Mặc dù tôi đánh giá cao việc bạn đã nỗ lực trong việc này, xin vui lòng nhận ra: 1) Múi giờ không cố định bù đắp 2) Chữ viết tắt múi giờ không được chuẩn hóa hoặc định danh duy nhất 3) Điều này đã được thực hiện, chính xác hơn nhiều, với jsTimeZoneDetect . 4) Câu trả lời của bạn không phù hợp với câu hỏi. Câu hỏi là làm thế nào để xác định múi giờ từ tọa độ kinh độ và vĩ độ .
Matt Johnson-Pint
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.