diff --git a/go.mod b/go.mod
index 0c6f5412fe59a40426165441053f7b5cfa02a4b8..8eff8a6eca97284ed5043c87877bf3810f296ad1 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.12
 require (
 	github.com/Masterminds/semver v1.5.0
 	github.com/appleboy/go-fcm v0.1.4
+	github.com/bradfitz/latlong v0.0.0-20170410180902-f3db6d0dff40
 	github.com/cozy/goexif2 v0.0.0-20180125141006-830968571cff
 	github.com/cozy/gomail v0.0.0-20170313100128-1395d9a6a6c0
 	github.com/cozy/httpcache v0.0.0-20180914105234-d3dc4988de66
diff --git a/go.sum b/go.sum
index 954dad5c694460c66c0d27d7740432cefca64419..9b9bfcb40339e95187f3e3a42384597ec218be18 100644
--- a/go.sum
+++ b/go.sum
@@ -18,6 +18,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
+github.com/bradfitz/latlong v0.0.0-20170410180902-f3db6d0dff40 h1:wsnz4B2CSHJ09pwtMReU/GRqWDsI7XSasq7Nphem3Xk=
+github.com/bradfitz/latlong v0.0.0-20170410180902-f3db6d0dff40/go.mod h1:ZcXX9BndVQx6Q/JM6B8x7dLE9sl20S+TQsv4KO7tEQk=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
diff --git a/model/vfs/metadata.go b/model/vfs/metadata.go
index a27fb1a0cfa44bb7351c84b290f41acb01320b2f..4fd893ae0bd4bd3031923cf38f8339c11bcb867d 100644
--- a/model/vfs/metadata.go
+++ b/model/vfs/metadata.go
@@ -2,11 +2,14 @@ package vfs
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"image"
 	"io"
 	"io/ioutil"
 	"math"
+	"strings"
+	"sync"
 	"time"
 
 	// Packages image/... are not used explicitly in the code below,
@@ -18,7 +21,9 @@ import (
 	// Same for image/webp
 	_ "golang.org/x/image/webp"
 
+	"github.com/bradfitz/latlong"
 	"github.com/cozy/goexif2/exif"
+	"github.com/cozy/goexif2/tiff"
 	"github.com/dhowden/tag"
 )
 
@@ -222,8 +227,10 @@ func (e *ExifExtractor) Result() Metadata {
 	x := <-e.ch
 	switch x := x.(type) {
 	case *exif.Exif:
+		localTZ := false
 		if dt, err := x.DateTime(); err == nil {
 			m["datetime"] = dt
+			localTZ = dt.Location() == time.Local
 		}
 		if flash, err := x.Flash(); err == nil {
 			m["flash"] = flash
@@ -234,6 +241,13 @@ func (e *ExifExtractor) Result() Metadata {
 					"lat":  lat,
 					"long": long,
 				}
+				if localTZ {
+					if loc := lookupLocation(latlong.LookupZoneName(lat, long)); loc != nil {
+						if t, err := exifDateTimeInLocation(x, loc); err == nil {
+							m["datetime"] = t
+						}
+					}
+				}
 			}
 		}
 		if _, ok := m["width"]; !ok {
@@ -259,6 +273,57 @@ func (e *ExifExtractor) Result() Metadata {
 	return m
 }
 
+// Code taken from perkeep
+// https://github.com/perkeep/perkeep/blob/7f17c0483f2e86575ed87aac35fb75154b16b7f4/pkg/schema/schema.go#L1043-L1094
+
+// This is basically a copy of the exif.Exif.DateTime() method, except:
+//   * it takes a *time.Location to assume
+//   * the caller already assumes there's no timezone offset or GPS time
+//     in the EXIF, so any of that code can be ignored.
+func exifDateTimeInLocation(x *exif.Exif, loc *time.Location) (time.Time, error) {
+	tag, err := x.Get(exif.DateTimeOriginal)
+	if err != nil {
+		tag, err = x.Get(exif.DateTime)
+		if err != nil {
+			return time.Time{}, err
+		}
+	}
+	if tag.Format() != tiff.StringVal {
+		return time.Time{}, errors.New("DateTime[Original] not in string format")
+	}
+	const exifTimeLayout = "2006:01:02 15:04:05"
+	dateStr := strings.TrimRight(string(tag.Val), "\x00")
+	return time.ParseInLocation(exifTimeLayout, dateStr, loc)
+}
+
+var zoneCache struct {
+	sync.RWMutex
+	m map[string]*time.Location
+}
+
+func lookupLocation(zone string) *time.Location {
+	if zone == "" {
+		return nil
+	}
+	zoneCache.RLock()
+	l, ok := zoneCache.m[zone]
+	zoneCache.RUnlock()
+	if ok {
+		return l
+	}
+	loc, err := time.LoadLocation(zone)
+	zoneCache.Lock()
+	if zoneCache.m == nil {
+		zoneCache.m = make(map[string]*time.Location)
+	}
+	zoneCache.m[zone] = loc // even if nil
+	zoneCache.Unlock()
+	if err != nil {
+		return nil
+	}
+	return loc
+}
+
 // AudioExtractor is used to extract album/artist/etc. from audio
 type AudioExtractor struct {
 	w  *io.PipeWriter