{"id":26281879,"url":"https://github.com/romaniakovlev/timeshape","last_synced_at":"2025-05-16T13:02:50.747Z","repository":{"id":43211291,"uuid":"128169626","full_name":"RomanIakovlev/timeshape","owner":"RomanIakovlev","description":"Java library to find timezone based on geo coordinates","archived":false,"fork":false,"pushed_at":"2025-04-25T13:26:27.000Z","size":233,"stargazers_count":177,"open_issues_count":3,"forks_count":39,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-16T13:02:49.584Z","etag":null,"topics":["java","java-library","openstreetmap","timezone"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RomanIakovlev.png","metadata":{"files":{"readme":"README.MD","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-04-05T06:53:28.000Z","updated_at":"2025-05-07T18:52:11.000Z","dependencies_parsed_at":"2024-11-13T11:17:48.688Z","dependency_job_id":"1434b9a7-ce13-4a37-9420-be465e19f4e7","html_url":"https://github.com/RomanIakovlev/timeshape","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RomanIakovlev%2Ftimeshape","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RomanIakovlev%2Ftimeshape/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RomanIakovlev%2Ftimeshape/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RomanIakovlev%2Ftimeshape/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RomanIakovlev","download_url":"https://codeload.github.com/RomanIakovlev/timeshape/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254535826,"owners_count":22087398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","java-library","openstreetmap","timezone"],"created_at":"2025-03-14T16:15:42.545Z","updated_at":"2025-05-16T13:02:50.740Z","avatar_url":"https://github.com/RomanIakovlev.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Timeshape\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.iakovlev/timeshape/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.iakovlev/timeshape/)\n![Build status](https://github.com/RomanIakovlev/timeshape/actions/workflows/release.yml/badge.svg)\n[![Gitter](https://badges.gitter.im/timeshape/community.svg)](https://gitter.im/timeshape/community)\n\nTimeshape is a Java library that can be used to determine to which time zone a given geo coordinate belongs.\nIt's based on data published at\n[https://github.com/evansiroky/timezone-boundary-builder/releases](https://github.com/evansiroky/timezone-boundary-builder/releases),\nwhich itself is inherited from the OpenStreetMap data.\n\nBut what if knowing just time zone for a geo coordinate is not enough? Wouldn't it be nice to know more, like\nadministrative area or city neighborhood? Check out [GeoBundle](https://geobundle.com), now there's a Java library for that, too!\n\n## Quote\n\n\u003e “Time is an illusion.”\n\u003e\n\u003e ― **Albert Einstein**\n\n## Getting started\n\nTimeshape is published on Maven Central. The coordinates are the following:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.iakovlev\u003c/groupId\u003e\n    \u003cartifactId\u003etimeshape\u003c/artifactId\u003e\n    \u003cversion\u003e2025b.26/version\u003e\n\u003c/dependency\u003e\n```\n\nStarting from release 2023b.20, Timeshape re-introduces support for Java 8. It was inadevrtently dropped in one of the previous releases,\nbut now it's brought back.\n\n## Android\n\nAndroid developers should add Timeshape to the app level gradle.build as follows:\n\n```gradle\nimplementation('net.iakovlev:timeshape:2025b.26') {\n  // Exclude standard compression library\n  exclude group: 'com.github.luben', module: 'zstd-jni'\n}\n// Import aar for native component compilation\nimplementation 'com.github.luben:zstd-jni:1.5.5-11@aar'\n```\n\n## Adopters\n\nAre you using Timeshape? Please consider opening a pull request to list your organization here:\n\n * Name and website of your organization\n * [Hopper](https://hopper.com/)\n * [Natural Light](https://play.google.com/store/apps/details?id=com.blackholeofphotography.naturallight)\n\n## Using the library\n\nThe user API of library is in `net.iakovlev.timeshape.TimeZoneEngine` class. To use it, follow these steps:\n\n#### Initialization\n\nInitialize the class with the data for the whole world:\n\n```java\nimport net.iakovlev.timeshape.TimeZoneEngine;\nTimeZoneEngine engine = TimeZoneEngine.initialize();\n```\n\nOr, alternatively, initialize it with some bounding box only, to reduce memory usage:\n\n```java\nTimeZoneEngine engine = TimeZoneEngine.initialize(47.0599, 4.8237, 55.3300, 15.2486);\n```\n\nIt is important to mention that for the time zone to be loaded by the second method,\nit must be covered by the bounding box completely, not just intersect with it.\n\nDuring initialization, the data is read from resource and the index is built.\nInitialization takes a significant amount of time (approximately 1 second), so do it only once in program lifetime.\n\nData can also be read from an external file, see overloads of `TimeZoneEngine.initialize` that accept\n`TarArchiveInputStream`. The file format should be same as produced by running `builder` sbt project\n(see [here](doc/Architecture.md#builder)).\nIt is responsibility of caller to close input stream passed to `TimeZoneEngine.initialize`.\n\nThere is an overload of `TimeZoneEngine.initialize` method that accepts a boolean parameter called\n`accelerateGeometry`. If that parameter is equals to `true`, Timeshape will build a bitmap index\nfor each polygon it loads. This requires some extra memory and takes time at initialization, hence\nthat parameter is being `false` by default, however it speeds up the typical point-in-polygon query\napproximately 2.5 times. See performance benchmarks in `AcceleratedGeometryBenchmark.java`, and\nhere is the result:\n```\n[info] Benchmark                                               Mode  Cnt   Score   Error  Units\n[info] AcceleratedGeometryBenchmark.testAcceleratedEngine     thrpt   10  38.142 ± 0.448  ops/s\n[info] AcceleratedGeometryBenchmark.testNonAcceleratedEngine  thrpt   10  15.289 ± 0.121  ops/s\n```\n\n\n##### Improving start up time by using serialization\n\nInitialization on slow devices such as Android phones can take up to 20 seconds. This can be improved by\nserializing an instance of the `TimeZoneEngine` and deserializing on subsequent runs of your program.\nAn example of serializing to a file can be found in `TimeZoneEngineSerializationTest.java` in the\nunit tests. Serialization is especially useful if you can limit `TimeZoneEngine` to a portion of the\ndata set via a user preference.\n\n\n#### Query for `java.time.ZoneId`:\n\nOnce initialization is completed, you can query the `ZoneId` based on latitude and longitude:\n\n```java\nimport java.util.Optional;\nimport java.time.ZoneId;\nOptional\u003cZoneId\u003e maybeZoneId = engine.query(52.52, 13.40);\n```\n\n#### Multiple time zones for single geo point\n\nStarting from release 2019b.7, the data source from which Timeshape is built contains overlapping geometries.\nIn other words, some geo points can simultaneously belong to multiple time zones. To accommodate this,\nTimeshape has made the following change. It's now possible to query all the time zones, to which given\ngeo point belongs:\n\n```java\nList\u003cZoneId\u003e allZones = engine.queryAll(52.52, 13.40);\n```\n\nThe `Optional\u003cZoneId\u003e query(double latitude, double longitude)` method is still there, and it still returns\nmaximum one `ZoneId`. If given geo point belongs to multiple time zones, only single one will be returned.\nWhich of multiple zones will be returned is entirely arbitrary. Because of this, method\n`Optional\u003cZoneId\u003e query(double latitude, double longitude)` is not suitable for use cases where such choice must\nbe deliberate. In such cases use `List\u003cZoneId\u003e queryAll(double latitude, double longitude)` method and apply further\nbusiness logic to its output to choose the right time zone. Consult file\nhttps://raw.githubusercontent.com/evansiroky/timezone-boundary-builder/master/expectedZoneOverlaps.json\nfor information about areas of the world where multiple time zones are to be expected.\n\n#### Querying polyline\n\nTimeshape supports querying of multiple sequential geo points (a polyline, e.g. a GPS trace) in an optimized way using method\n`List\u003cSameZoneSpan\u003e queryPolyline(double[] points)`. Performance tests (see `net.iakovlev.timeshape.PolylineQueryBenchmark`)\nshow significant speedup of using this method for querying a polyline, comparing to separately querying each point from polyline \nusing `Optional\u003cZoneId\u003e query(double latitude, double longitude)` method:\n\n```\nBenchmark                                  Mode  Cnt  Score   Error  Units\nPolylineQueryBenchmark.testQueryPoints    thrpt    5  2,188 ▒ 0,044  ops/s\nPolylineQueryBenchmark.testQueryPolyline  thrpt    5  4,073 ▒ 0,017  ops/s\n```\n\n### Architecture\n\nSee [dedicated document](doc/Architecture.md) for description of Timeshape internals.\n\n### Versioning\n\nVersion of Timeshape consist of data version and software version, divided by a '.' symbol.\nData version is as specified at [https://github.com/evansiroky/timezone-boundary-builder/releases](https://github.com/evansiroky/timezone-boundary-builder/releases).\nSoftware version is an integer, starting from 1 and incrementing for each published artifact.\n\n## Licenses\n\nThe code of the library is licensed under the [MIT License](https://opensource.org/licenses/MIT).\n\nThe time zone data contained in library is licensed under the [Open Data Commons Open Database License (ODbL)](http://opendatacommons.org/licenses/odbl/).\n\n## Endorsements\n\nTimeshape uses YourKit.\n\n\u003cimg src=\"https://www.yourkit.com/images/yklogo.png\"\u003e\n\nYourKit supports open source projects with innovative and intelligent tools\nfor monitoring and profiling Java and .NET applications.\nYourKit is the creator of \u003ca href=\"https://www.yourkit.com/java/profiler/\"\u003eYourKit Java Profiler\u003c/a\u003e,\n\u003ca href=\"https://www.yourkit.com/dotnet-profiler/\"\u003eYourKit .NET Profiler\u003c/a\u003e,\nand \u003ca href=\"https://www.yourkit.com/youmonitor/\"\u003eYourKit YouMonitor\u003c/a\u003e.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromaniakovlev%2Ftimeshape","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fromaniakovlev%2Ftimeshape","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromaniakovlev%2Ftimeshape/lists"}