如何在iOS中通过经纬度确定时区

10

我如何确定给定经度和纬度所处的NSTimeZone?

5个回答

12

我已经尝试过APTimeZones库。在我的案例中,我需要从特定城市的经纬度获取时区和国家名称。

我查看了该库以了解其工作原理。实际上,它有一个以JSON格式呈现的文件,其中包含所有时区及其对应的经纬度。它接受经纬度作为输入,并循环遍历此JSON文件,比较所有时区的经纬度与输入经纬度之间的距离。然后返回从输入经纬度到最短距离的时区。

但问题是,对于位于大国边界的城市,它会返回相邻国家的时区。由于我也从中提取了国家代码,因此我得到了相邻的国家。

所以,在这种情况下,Apple的本机框架更好。

以下代码对我很有效。

CLLocation *location = [[CLLocation alloc] initWithLatitude:your_latitude longitude:your_longitude];
CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
[geoCoder reverseGeocodeLocation: location completionHandler:^(NSArray *placemarks, NSError *error)
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(@"Timezone -%@",placemark.timeZone);

//And to get country name simply.
NSLog(@"Country -%@",placemark.country);

}];

在Swift中

let location = CLLocation(latitude: your_latitude, longitude: your_longitude)
let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(location) { (placemarks, err) in
     if let placemark = placemarks?[0] {
          print(placemark.timeZone)
          print(placemark.country)
     }
}

2
这是最优雅的解决方案,没有第三方库!我简直不敢相信 CLPlacemark 上有一个 timeZone 属性 :) - PostCodeism
2
没错,伙计,这值得分享,所以我分享了。祝编码愉快 :) - Roohul
自 iOS11 和 macOS10.13 开始,它是公共框架,不需要查看其他解决方案。 - Marek H

2

这里是我使用的技巧。可以从中提取时区标识符,并且您可以使用此标识符来设置时区。

CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];

[geoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {

    if (error == nil && [placemarks count] > 0) {

        placeMark = [placemarks lastObject];
         NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"identifier = \"[a-z]*\\/[a-z]*_*[a-z]*\"" options:NSRegularExpressionCaseInsensitive error:NULL];
        NSTextCheckingResult *newSearchString = [regex firstMatchInString:[placeMark description] options:0 range:NSMakeRange(0, [placeMark.description length])];
        NSString *substr = [placeMark.description substringWithRange:newSearchString.range];
        NSLog(@"timezone id %@",substr); 

    }];

是的,这是苹果的私有框架,但如果您从本地框架获取它,则最好不要使用第三方库。 - Dharmesh Vaghani
这个在 iOS 更新中出现问题的可能性非常大。 - Josh Bernfeld
2
自iOS11,macOS10.13以来,它已经是公开的。 - Marek H
这会显示用户的时间和时区,而不是位置的时间。iOS 13.4 - Mike Taverne

1

我创建了另一个库,用于将坐标解析为时区和国家。https://github.com/patrick-zippenfenig/SwiftTimeZoneLookup

时区数据库作为一个bundle(约5 MB)嵌入其中。我刚刚更新了最新版本2023b from timezone-boundary-builder

使用方法:

import SwiftTimeZoneLookup


let database = try SwiftTimeZoneLookup()
guard let timezone = database.simple(latitude: 47.5, longitude: 8.6) else {
  fatalError("Timezone not found, coordinates invalid?")
}
print(timezone) // "Europe/Zurich"


guard let lookup = database.lookup(latitude: 47.5, longitude: 8.6) else {
  fatalError("Timezone not found, coordinates invalid?")
}
print(lookup) // SwiftTimeZoneLookupResult(timezone: "Europe/Zurich", countryName: Optional("Switzerland"), countryAlpha2: Optional("CH"))

1
我将DarkSky的时区代码移植到了Swift,它使用准确的时区形状生成了一个简化的时区数据库,允许快速查找和小尺寸。相比之下,APTimeZones只能查找最接近中心的时区,功能不够完善。

https://github.com/bialylis/tz-lookup-oss


-1
你可以在Swift中使用Core Location来实现,但是它需要用户在线并且以异步方式运行。
import CoreLocation

func timeZone(forLatitude latitude: CLLocationDegrees, longitude: CLLocationDegrees, completion: @escaping (TimeZone?) -> Void) {
    let location = CLLocation(latitude: latitude, longitude: longitude)
    let geocoder = CLGeocoder()

    geocoder.reverseGeocodeLocation(location) { placemarks, error in
        if let error = error {
            print("Error reverse geocoding location: \(error.localizedDescription)")
            completion(nil)
        } else if let placemark = placemarks?.first {
            completion(placemark.timeZone)
        } else {
            print("No placemark data found.")
            completion(nil)
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接