Skip to content

Commit

Permalink
Commit for first release, utilize snappy and gob to cache the model a…
Browse files Browse the repository at this point in the history
…nd load it.
  • Loading branch information
catmullet committed May 12, 2021
1 parent 8f08f41 commit 05a3534
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 13 deletions.
71 changes: 60 additions & 11 deletions geojson.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@ package tz
import (
"archive/zip"
"bytes"
"encoding/gob"
"encoding/json"
"fmt"
"github.com/golang/snappy"
"io"
"log"
"math"
"os"
"path/filepath"
"sort"
"sync"
"time"
)

type TimeZoneCollection struct {
Features []*Feature
*sync.RWMutex
mutex *sync.RWMutex
}

type Feature struct {
Expand Down Expand Up @@ -55,16 +59,29 @@ var multiPolygon struct {
Coordinates [][][][]float64
}

func NewGeoJsonTimeZoneLookup(geoJsonFile string) (TimeZoneLookup, error) {
var fc = &TimeZoneCollection{
Features: make([]*Feature, 500),
RWMutex: new(sync.RWMutex),
}
func NewGeoJsonTimeZoneLookup(geoJsonFile string, logOutput ...io.Writer) (TimeZoneLookup, error) {

logger := log.New(io.MultiWriter(logOutput...), "tz", log.Lshortfile)
logger.Println("initializing...")

const timzonesFile = "timezones-with-oceans.geojson.zip"

if len(geoJsonFile) == 0 {
geoJsonFile = os.Getenv("GEO_JSON_FILE")
}
if len(geoJsonFile) == 0 {
geoJsonFile = "timezones-with-oceans.geojson.zip"
logger.Println("no geo time zone file specified, using default")
geoJsonFile = timzonesFile
}

var fc = &TimeZoneCollection{
Features: make([]*Feature, 500),
mutex: new(sync.RWMutex),
}

if err := findCachedModel(fc); err == nil {
logger.Println("cached model found")
return fc, nil
}

g, err := zip.OpenReader(geoJsonFile)
Expand All @@ -78,7 +95,6 @@ func NewGeoJsonTimeZoneLookup(geoJsonFile string) (TimeZoneLookup, error) {
var file = g.File[0]
var buf = bytes.NewBuffer([]byte{})
src, err := file.Open()

if err != nil {
return nil, fmt.Errorf("failed to unzip file: %w", err)
}
Expand Down Expand Up @@ -109,7 +125,40 @@ func NewGeoJsonTimeZoneLookup(geoJsonFile string) (TimeZoneLookup, error) {
return fc.Features[i].Geometry.MinPoint.Lon <= fc.Features[j].Geometry.MinPoint.Lon
})

return fc, nil
logger.Println("finished")
return fc, createCachedModel(fc)
}

func findCachedModel(fc *TimeZoneCollection) error {
cache, err := os.Open(filepath.Join(os.TempDir(), "tzdata.snappy"))
if err != nil {
if cache, err = os.Open(filepath.Join("cache", "tzdata.snappy")); err != nil {
return err
}
}
defer cache.Close()
snp := snappy.NewReader(cache)
dec := gob.NewDecoder(snp)
if err := dec.Decode(fc); err != nil && err != io.EOF {
return err
}
return nil
}

func createCachedModel(fc *TimeZoneCollection) error {
cache, err := os.Create(filepath.Join("cache", "tzdata.snappy"))
if err != nil {
return err
}
defer cache.Close()
snp := snappy.NewBufferedWriter(cache)
enc := gob.NewEncoder(snp)
if err := enc.Encode(fc); err != nil {
cache.Close()
return err
}

return nil
}

func (g *Geometry) UnmarshalJSON(data []byte) (err error) {
Expand Down Expand Up @@ -181,8 +230,8 @@ func updateMaxMin(maxPoint, minPoint *Point, lat, lon float64) {
}

func (fc *TimeZoneCollection) TimeZone(lat, lon float64) (tz string) {
fc.Lock()
defer fc.Unlock()
fc.mutex.Lock()
defer fc.mutex.Unlock()
for _, feat := range fc.Features {
f := feat
tzString := f.Properties.Tzid
Expand Down
12 changes: 10 additions & 2 deletions geojson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,25 @@ var querys = []coords{

func TestMain(m *testing.M) {
var err error
tzl, err = NewGeoJsonTimeZoneLookup("timezones-with-oceans.geojson.zip")
tzl, err = NewGeoJsonTimeZoneLookup("timezones-with-oceans.geojson.zip", os.Stdout)
if err != nil {
log.Println(err)
os.Exit(1)
}
code := m.Run()
os.Exit(code)
}

func TestSmallPolygon(t *testing.T) {
tz := tzl.TimeZone(24.3000, 153.9667)
t.Log("time_zone:", tz)
if tz != "Asia/Tokyo" {
t.Fail()
}
}

func BenchmarkLongTimeZone(b *testing.B) {
for i := 0; i < b.N; i++ {
//tzl.TimeZone(42.7235,-73.6931)
tzl.TimeZone(5.840370, -55.196100)
}
}
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/catmullet/tz

go 1.15

require github.com/golang/snappy v0.0.3
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=

0 comments on commit 05a3534

Please sign in to comment.