timezone_finder 1.0.0
timezone_finder: ^1.0.0 copied to clipboard
Makes package:timezone easier to use — turn a place on Earth into the Location it sits in.
timezone_finder #
An add-on for package:timezone. It turns a point on Earth into a Location.
Split in 1.0.0 #
Up to 0.2.0, this package also converted a TZDateTime to another Location and gave English time zone names. Those features moved to timezone_extensions. If you used them, add both packages:
dependencies:
timezone_extensions: ^0.1.0
timezone_finder: ^1.0.0
Initialization #
timezone_finder is deeply connected to the official timezone package, so two datasets have to be ready first:
- tzdata — IANA zone rules, from
package:timezone. Always loadlatest_all.latestdrops the tzdb link identifiers — 106 of this package's 419 boundary identifiers are missing from it, and a lookup that hits one throws. - Boundaries — land polygons, from this package. Already compiled in on the VM. On web they are a ~4 MB
.binyou install once at startup.
On web, import package:timezone_finder/browser.dart instead of package:timezone_finder/timezone_finder.dart. It is web-only and re-exports the same API. A Flutter app that also targets mobile or desktop should conditionally import browser.dart on the same branch that loads the .bin — importing it off web is a compile error; using timezone_finder.dart on web compiles, then throws at lookup.
VM, CLI, server, Flutter mobile and desktop #
- Import
package:timezone/data/latest_all.dartandpackage:timezone/timezone.dartpackage:timezone_finder/timezone_finder.dart
- Start the code with
tz.initializeTimeZones()to load tzdata for thetimezonepackage.
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart';
import 'package:timezone_finder/timezone_finder.dart';
void main() {
tz.initializeTimeZones();
final paris = findLocation(2.3522, 48.8566); // Europe/Paris Location
}
On a server, await ensurePreloaded() at isolate startup if you do not want the first request to pay the decode.
Dart web #
- Import
package:timezone/browser.dartpackage:timezone_finder/browser.dart
- Start the code with
await tz.initializeTimeZone('packages/timezone/data/latest_all.tzf'), notlatest.tzf(default)await initializeBoundaries()fetches the.binfrompackages/timezone_finder/data/boundaries.binwithout any asset pipeline. Pass a URL to self-host.
import 'package:timezone/browser.dart' as tz;
import 'package:timezone_finder/browser.dart';
Future<void> main() async {
await tz.initializeTimeZone('packages/timezone/data/latest_all.tzf');
await initializeBoundaries();
final paris = findLocation(2.3522, 48.8566); // Europe/Paris Location
}
Flutter web #
- Declare the
.binin your app'spubspec.yaml:
flutter:
assets:
- packages/timezone_finder/data/boundaries.bin
The path stays the same across boundary updates, so this entry never needs changing. The timezone_finder package does not declare the .bin as a Flutter asset, so Android and iOS builds — which use the embedded index — do not carry 4 MB they never read.
- Import
package:timezone/browser.dartpackage:timezone_finder/browser.dart
- Start the code with
await tz.initializeTimeZone('packages/timezone/data/latest_all.tzf'), notlatest.tzf(default)installBoundaries(...)fromrootBundle
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:timezone/browser.dart' as tz;
import 'package:timezone_finder/browser.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await tz.initializeTimeZone('packages/timezone/data/latest_all.tzf');
final data = await rootBundle.load(
'packages/timezone_finder/data/boundaries.bin',
);
installBoundaries(data.buffer.asUint8List());
final paris = findLocation(2.3522, 48.8566); // Europe/Paris Location
runApp(const MyApp());
}
findLocation, ensurePreloaded, and boundaryDataVersion throw a StateError until the .bin is installed. initializeBoundaries fetch failures throw BoundariesInitException; corrupt bytes throw IndexFormatException.
API #
After initialization, the surface is small. Argument order is GeoJSON: longitude, then latitude.
🎯 Find a Location #
null means no land polygon covers the point. Coastal belts extend ~22 km offshore, so a narrow strait often resolves and open ocean does not. Bad coordinates throw ArgumentError. Missing tzdata, latest instead of latest_all, or a web lookup before install throw StateError. null is never an error.
final home = findLocation(-118.6884215, 34.0327862)!; // America/Los_Angeles Location
final hotel = findLocation(151.2430457, -33.8760146)!; // Australia/Sydney Location
Shipped data version: boundaryDataVersion (Timezone Boundary Builder release). It is independent of the tzdb version inside package:timezone.
Data used #
| Dataset | Source | What it answers |
|---|---|---|
| Land polygons | Timezone Boundary Builder from OpenStreetMap | Which IANA zone contains this longitude/latitude |
| Zone rules | package:timezone (IANA tzdb) |
Offsets, DST, abbreviations |
Coordinates come from wherever you already have them — a GPS fix, a map tap, a database column. From an address, Nominatim and Photon return a FeatureCollection; pick a feature and pass its Point coordinates to findLocation.
Licenses #
- Code — MIT (
LICENSE). - Boundary data — ODbL v1.0 (
LICENSE-DATA). Share-alike: if you publicly ship an adapted database, offer that adapted database under ODbL too.
If you redistribute the boundary data (or a work produced from it), include:
Time zone boundary data © OpenStreetMap contributors, available under the Open Database License (ODbL). Boundaries built by Timezone Boundary Builder.
IANA publishes no official polygons; tz-link cites TZBB as the de facto source. TZBB is by Evan Siroky, built from OpenStreetMap data.