FileTime returns the best guess of the file's creation time (or modtime). If the file doesn't have its own metadata indication the creation time (such as in EXIF), FileTime uses the modification time from the file system. It there was a valid EXIF but an error while trying to get a date from it, it
(f io.ReaderAt)
| 987 | // It there was a valid EXIF but an error while trying to get a date from it, |
| 988 | // it logs the error and tries the other methods. |
| 989 | func FileTime(f io.ReaderAt) (time.Time, error) { |
| 990 | var ct time.Time |
| 991 | defaultTime := func() (time.Time, error) { |
| 992 | if osf, ok := f.(*os.File); ok { |
| 993 | fi, err := osf.Stat() |
| 994 | if err != nil { |
| 995 | return ct, fmt.Errorf("Failed to find a modtime: stat: %w", err) |
| 996 | } |
| 997 | return fi.ModTime(), nil |
| 998 | } |
| 999 | return ct, errors.New("all methods failed to find a creation time or modtime") |
| 1000 | } |
| 1001 | |
| 1002 | size, ok := findSize(f) |
| 1003 | if !ok { |
| 1004 | size = 256 << 10 // enough to get the EXIF |
| 1005 | } |
| 1006 | r := io.NewSectionReader(f, 0, size) |
| 1007 | var tiffErr error |
| 1008 | ex, err := exif.Decode(r) |
| 1009 | if err != nil { |
| 1010 | tiffErr = err |
| 1011 | if exif.IsShortReadTagValueError(err) { |
| 1012 | return ct, io.ErrUnexpectedEOF |
| 1013 | } |
| 1014 | if exif.IsCriticalError(err) || exif.IsExifError(err) { |
| 1015 | return defaultTime() |
| 1016 | } |
| 1017 | } |
| 1018 | ct, err = ex.DateTime() |
| 1019 | if err != nil { |
| 1020 | return defaultTime() |
| 1021 | } |
| 1022 | // If the EXIF file only had local timezone, but it did have |
| 1023 | // GPS, then lookup the timezone and correct the time. |
| 1024 | if ct.Location() == time.Local { |
| 1025 | if exif.IsGPSError(tiffErr) { |
| 1026 | log.Printf("Invalid EXIF GPS data: %v", tiffErr) |
| 1027 | return ct, nil |
| 1028 | } |
| 1029 | if lat, long, err := ex.LatLong(); err == nil { |
| 1030 | if loc := lookupLocation(latlong.LookupZoneName(lat, long)); loc != nil { |
| 1031 | if t, err := exifDateTimeInLocation(ex, loc); err == nil { |
| 1032 | return t, nil |
| 1033 | } |
| 1034 | } |
| 1035 | } else if !exif.IsTagNotPresentError(err) { |
| 1036 | log.Printf("Invalid EXIF GPS data: %v", err) |
| 1037 | } |
| 1038 | } |
| 1039 | return ct, nil |
| 1040 | } |
| 1041 | |
| 1042 | // This is basically a copy of the exif.Exif.DateTime() method, except: |
| 1043 | // - it takes a *time.Location to assume |