关于地理位置:如何使用纬度和经度坐标从某个位置获取时区?

How to get a time zone from a location using latitude and longitude coordinates?

StackOverflow中有太多关于从位置解析时区的问题。这个社区wiki试图整合所有有效的响应。

请更新我的答案,或者根据需要添加自己的答案。

问题考虑到一个地点的纬度和经度,人们如何知道该地点的时区是什么?

在大多数情况下,我们都在寻找IANA/OLSON时区ID,尽管有些服务可能只返回一个UTC偏移量,或者其他时区标识符。有关详细信息,请阅读时区标记信息。


时区位置Web服务

  • 谷歌地图时区API
  • Microsoft Azure地图时区API
  • 地名时区API
  • TimeZunDeDAPI
  • Askgeo-商业(但可以说比地名更准确)
  • 地理车库时区API-商业,专注于航海时区。

原始时区边界数据

  • 时区边界生成器-从OpenStreetmap地图数据生成时区形状文件。包括海岸线附近的领海。

以下项目以前是时区边界数据的来源,但现在不再积极维护。

  • TZ_World-来自Eric Muller的原始形状文件数据
  • 其中,earth timezone-geojson版本与wodb数据合并在

时区地理定位离线实现

使用时区边界生成器数据的实现

  • 节点geo tz-javascript库
  • TZ查找-javascript库
  • 地理时区-.NET库
  • TimeZoneFinder-python库
  • ZoneDetect-C库
  • 时态-爪哇图书馆
  • Lutz-R库

使用旧的TZ-World数据的实现

  • 拉特隆图书馆(也请阅读本帖。)
  • Java库
  • TZWHERE-javascript/节点库
  • pytzwhere-python库
  • 时区查找器-Ruby库
  • LavaLoTimeTealZeave- Java和SWIFT库
  • 几点到?-描述php和mongodb的博客文章
  • rundel/timezone-r库

调用其中一个Web服务的库

  • 时区-调用地名的Ruby Gem
  • ASKGEGO有它自己的用于从Java或.NET调用的库。
  • geonames有客户程序库,几乎可以处理所有的事情。

其他想法

  • 用R-树找到最近的城市
  • 使用mysql查找最近的城市

如果您知道任何其他信息,请更新此列表

另外,注意最近的城市方法可能不会产生"正确"的结果,只是一个近似值。

转换到Windows区域

列出的大多数方法都将返回IANA时区ID。如果需要转换为Windows时区以与.NET中的TimeZoneInfo类一起使用,请使用TimeZoneConverter库。

不使用zone.tab

TZ数据库包含一个名为zone.tab的文件。此文件主要用于显示供用户选择的时区列表。它包括每个时区参考点的纬度和经度坐标。这允许创建突出显示这些点的地图。例如,请参见Moment TimeZone主页上显示的交互式地图。

虽然使用这些数据从纬度和经度坐标解析时区可能很有吸引力,但请考虑这些是点而不是边界。最好的办法是确定最近的点,在许多情况下,这不是正确的点。

请考虑以下示例:

&Time Zone Example Art

这两个方块代表不同的时区,其中每个方块中的黑点是参考位置,例如可以在zone.tab中找到的位置。蓝点表示我们试图为其找到时区的位置。很明显,这个位置在左边的橙色区域内,但是如果我们只看离参考点最近的距离,它将解析为右边的绿色区域。


这个node.js的解决方案怎么样网址:https://github.com/mattbornski/tzwhere

与之对应的python:https://github.com/pegler/pytzwhere


我们在Teleport刚刚开始打开我们的API,其中一个用例还公开了坐标的TZ信息。

例如,我们可以通过以下方式请求所有可用的TZ信息作为坐标:

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

这将返回以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
 "_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解析。


下面介绍如何使用谷歌的脚本编辑器在GSheet中获取TimeZoneName和TimeZoneID。

步骤1。获取谷歌时区API的API密钥

步骤2。创建新的GSheet。在"工具"菜单下,单击"脚本编辑器"。添加以下代码:

1
2
3
4
5
6
7
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()函数,并使用它,如上图所示。


您可以使用geodlocator.js轻松获取时区等等…

它使用需要密钥的谷歌API。因此,首先要配置地理定位器:

1
2
3
4
5
6
7
geolocator.config({
    language:"en",
    google: {
        version:"3",
        key:"YOUR-GOOGLE-API-KEY"
    }
});

如果有坐标,则获取时区:

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

实例输出:

1
2
3
4
5
6
7
8
{
    id:"Europe/Paris",
    name:"Central European Standard Time",
    abbr:"CEST",
    dstOffset: 0,
    rawOffset: 3600,
    timestamp: 1455733120
}

找到并获取时区等信息

如果没有坐标,可以先定位用户位置。

下面的示例将首先尝试HTML5地理定位API以获取坐标。如果失败或拒绝,它将通过地理IP查找获得坐标。最后,它将得到时区和更多…

1
2
3
4
5
6
7
8
9
10
11
12
13
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);
});

实例输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
    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
}

认识到这是一个比大多数人想象的更复杂的问题确实很重要。在实践中,我们中的许多人也愿意接受"尽可能多的情况"下工作的一组代码,在这些情况下,至少可以识别和最小化其致命问题。所以我把这一切和行动的精神放在了脑后。最后,对于那些试图将GPS转换为时区,最终目标是拥有一个位置敏感的时间对象(更重要的是,帮助提高平均实现质量,时间对象从这个wiki跟踪)的人来说,我在python中生成了以下内容(请随意编辑):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)


  • 有几个在线资源提供时区的geojson数据(这里有一个,这里有另一个)

  • 使用几何库从GejJSON坐标创建多边形对象(Shaply[Python),GeOs[C++],JTS,NTS[NET])。

  • 将您的lat/lng转换为一个点对象(但是您的库表示该对象),并检查它是否与时区多边形相交。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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

  • 通过使用纬度和经度获取当前位置的时区,代码下面的代码对我有效。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    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();
    }


    如果您想使用geonames.org,那么使用这个代码。(但geonames.org有时速度很慢)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    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;

     }

    并将其用于:

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

    好的,这里是没有正确NTP时间的短版本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    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;

    }

    并将其用于:

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

    来自Guppy:

    1
    2
    3
    4
    5
    6
    7
    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

    DstTzInfoAmerica/Anchorage.dst绑定方法

    美洲/安克雷奇'LMT-1天,标准时间14:00:00


    https://en.wikipedia.org/wiki/great-circleu距离

    下面是一个使用JSON数据的很好的实现:网址:https://github.com/agap/llttz

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    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());
        }
    }


    尝试使用Java的谷歌时区API,使用当前NTP时间客户端和正确的UTCXDATEMEMENFROWY时间戳转换代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    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;

    }

    并将其用于:

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


    如果您希望避免使用Web服务,可以像这样从浏览器中检索该信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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?:?三十七UTC时差:UTC-3国家代码时区:BRT

    希望能有所帮助。