mirror of
https://github.com/samsonjs/SwiftTimeZoneLookup.git
synced 2026-04-26 14:47:41 +00:00
automatic resolution switching
This commit is contained in:
parent
90d3a002fa
commit
f235ad0801
2 changed files with 42 additions and 12 deletions
|
|
@ -8,34 +8,60 @@ public enum SwiftTimeZoneLookupError: Error {
|
||||||
|
|
||||||
public struct SwiftTimeZoneLookupResult {
|
public struct SwiftTimeZoneLookupResult {
|
||||||
/// Timezone identifier like `Europe/Berlin`
|
/// Timezone identifier like `Europe/Berlin`
|
||||||
let timezone: String
|
public let timezone: String
|
||||||
|
|
||||||
/// Country name like `Germany`
|
/// Country name like `Germany`
|
||||||
let countryName: String?
|
public let countryName: String?
|
||||||
|
|
||||||
/// 2 character country code like `DE` for Germany
|
/// 2 character country code like `DE` for Germany
|
||||||
let countryAlpha2: String?
|
public let countryAlpha2: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class SwiftTimeZoneLookup {
|
public final class SwiftTimeZoneLookup {
|
||||||
private let database: OpaquePointer
|
/// 0.00017 degrees (~20m) resolution
|
||||||
|
private let database21: OpaquePointer
|
||||||
|
|
||||||
|
/// 0.0055 degrees (~0.5km) resolution
|
||||||
|
private let database16: OpaquePointer
|
||||||
|
|
||||||
/// Throws if the timezone database could not be opened
|
/// Throws if the timezone database could not be opened
|
||||||
public init() throws {
|
public init() throws {
|
||||||
guard let timezone21 = Bundle.module.url(forResource: "timezone21", withExtension: "bin") else {
|
guard let timezone21 = Bundle.module.url(forResource: "timezone21", withExtension: "bin") else {
|
||||||
throw SwiftTimeZoneLookupError.couldNotFindTimezone21bin
|
throw SwiftTimeZoneLookupError.couldNotFindTimezone21bin
|
||||||
}
|
}
|
||||||
guard let database = timezone21.withUnsafeFileSystemRepresentation({ timezone21 in
|
guard let timezone16 = Bundle.module.url(forResource: "timezone16", withExtension: "bin") else {
|
||||||
ZDOpenDatabase(timezone21)
|
throw SwiftTimeZoneLookupError.couldNotFindTimezone21bin
|
||||||
}) else {
|
}
|
||||||
|
|
||||||
|
guard let database21 = timezone21.withUnsafeFileSystemRepresentation(ZDOpenDatabase) else {
|
||||||
throw SwiftTimeZoneLookupError.couldNotOpenDatabase
|
throw SwiftTimeZoneLookupError.couldNotOpenDatabase
|
||||||
}
|
}
|
||||||
self.database = database
|
guard let database16 = timezone16.withUnsafeFileSystemRepresentation(ZDOpenDatabase) else {
|
||||||
|
throw SwiftTimeZoneLookupError.couldNotOpenDatabase
|
||||||
|
}
|
||||||
|
|
||||||
|
self.database21 = database21
|
||||||
|
self.database16 = database16
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try with lower resolution first and use high resolution database if too close to the border
|
||||||
|
private func highResLookup(latitude: Float, longitude: Float) -> UnsafeMutablePointer<ZoneDetectResult>? {
|
||||||
|
var safezone: Float = .nan
|
||||||
|
guard let result = ZDLookup(database16, latitude, longitude, &safezone) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if safezone >= 0.0055*2 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
guard let result21 = ZDLookup(database21, latitude, longitude, &safezone) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return result21
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve timezone by coordinate and return timezone, country name and alpha2
|
/// Resolve timezone by coordinate and return timezone, country name and alpha2
|
||||||
public func lookup(latitude: Float, longitude: Float) -> SwiftTimeZoneLookupResult? {
|
public func lookup(latitude: Float, longitude: Float) -> SwiftTimeZoneLookupResult? {
|
||||||
guard let result = ZDLookup(database, latitude, longitude, nil) else {
|
guard let result = highResLookup(latitude: latitude, longitude: longitude) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
defer { ZDFreeResults(result) }
|
defer { ZDFreeResults(result) }
|
||||||
|
|
@ -72,7 +98,7 @@ public final class SwiftTimeZoneLookup {
|
||||||
|
|
||||||
/// Resolve the timz
|
/// Resolve the timz
|
||||||
public func simple(latitude: Float, longitude: Float) -> String? {
|
public func simple(latitude: Float, longitude: Float) -> String? {
|
||||||
guard let result = ZDLookup(database, latitude, longitude, nil) else {
|
guard let result = highResLookup(latitude: latitude, longitude: longitude) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
defer { ZDFreeResults(result) }
|
defer { ZDFreeResults(result) }
|
||||||
|
|
@ -100,6 +126,6 @@ public final class SwiftTimeZoneLookup {
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
ZDCloseDatabase(database)
|
ZDCloseDatabase(database21)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import XCTest
|
import XCTest
|
||||||
@testable import SwiftTimeZoneLookup
|
import SwiftTimeZoneLookup
|
||||||
|
|
||||||
final class SwiftTimeZoneLookupTests: XCTestCase {
|
final class SwiftTimeZoneLookupTests: XCTestCase {
|
||||||
func testLookup() throws {
|
func testLookup() throws {
|
||||||
|
|
@ -13,5 +13,9 @@ final class SwiftTimeZoneLookupTests: XCTestCase {
|
||||||
|
|
||||||
XCTAssertEqual(database.lookup(latitude: 42.5, longitude: -8.6)?.countryName, "Spain")
|
XCTAssertEqual(database.lookup(latitude: 42.5, longitude: -8.6)?.countryName, "Spain")
|
||||||
XCTAssertEqual(database.lookup(latitude: 42.5, longitude: -8.6)?.countryAlpha2, "ES")
|
XCTAssertEqual(database.lookup(latitude: 42.5, longitude: -8.6)?.countryAlpha2, "ES")
|
||||||
|
|
||||||
|
// on the border to the netherlands. Requires high resolution lookup
|
||||||
|
XCTAssertEqual(database.simple(latitude: 53.242293, longitude: 7.209253), "Europe/Berlin")
|
||||||
|
XCTAssertEqual(database.simple(latitude: 53.239692, longitude: 7.207879), "Europe/Amsterdam")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue