summaryrefslogtreecommitdiff
path: root/vendor/github.com/dsoprea/go-exif/v3/common/utility.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/dsoprea/go-exif/v3/common/utility.go')
-rw-r--r--vendor/github.com/dsoprea/go-exif/v3/common/utility.go148
1 files changed, 148 insertions, 0 deletions
diff --git a/vendor/github.com/dsoprea/go-exif/v3/common/utility.go b/vendor/github.com/dsoprea/go-exif/v3/common/utility.go
new file mode 100644
index 000000000..575049706
--- /dev/null
+++ b/vendor/github.com/dsoprea/go-exif/v3/common/utility.go
@@ -0,0 +1,148 @@
+package exifcommon
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/dsoprea/go-logging"
+)
+
+var (
+ timeType = reflect.TypeOf(time.Time{})
+)
+
+// DumpBytes prints a list of hex-encoded bytes.
+func DumpBytes(data []byte) {
+ fmt.Printf("DUMP: ")
+ for _, x := range data {
+ fmt.Printf("%02x ", x)
+ }
+
+ fmt.Printf("\n")
+}
+
+// DumpBytesClause prints a list like DumpBytes(), but encapsulated in
+// "[]byte { ... }".
+func DumpBytesClause(data []byte) {
+ fmt.Printf("DUMP: ")
+
+ fmt.Printf("[]byte { ")
+
+ for i, x := range data {
+ fmt.Printf("0x%02x", x)
+
+ if i < len(data)-1 {
+ fmt.Printf(", ")
+ }
+ }
+
+ fmt.Printf(" }\n")
+}
+
+// DumpBytesToString returns a stringified list of hex-encoded bytes.
+func DumpBytesToString(data []byte) string {
+ b := new(bytes.Buffer)
+
+ for i, x := range data {
+ _, err := b.WriteString(fmt.Sprintf("%02x", x))
+ log.PanicIf(err)
+
+ if i < len(data)-1 {
+ _, err := b.WriteRune(' ')
+ log.PanicIf(err)
+ }
+ }
+
+ return b.String()
+}
+
+// DumpBytesClauseToString returns a comma-separated list of hex-encoded bytes.
+func DumpBytesClauseToString(data []byte) string {
+ b := new(bytes.Buffer)
+
+ for i, x := range data {
+ _, err := b.WriteString(fmt.Sprintf("0x%02x", x))
+ log.PanicIf(err)
+
+ if i < len(data)-1 {
+ _, err := b.WriteString(", ")
+ log.PanicIf(err)
+ }
+ }
+
+ return b.String()
+}
+
+// ExifFullTimestampString produces a string like "2018:11:30 13:01:49" from a
+// `time.Time` struct. It will attempt to convert to UTC first.
+func ExifFullTimestampString(t time.Time) (fullTimestampPhrase string) {
+ t = t.UTC()
+
+ return fmt.Sprintf("%04d:%02d:%02d %02d:%02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
+}
+
+// ParseExifFullTimestamp parses dates like "2018:11:30 13:01:49" into a UTC
+// `time.Time` struct.
+func ParseExifFullTimestamp(fullTimestampPhrase string) (timestamp time.Time, err error) {
+ defer func() {
+ if state := recover(); state != nil {
+ err = log.Wrap(state.(error))
+ }
+ }()
+
+ parts := strings.Split(fullTimestampPhrase, " ")
+ datestampValue, timestampValue := parts[0], parts[1]
+
+ // Normalize the separators.
+ datestampValue = strings.ReplaceAll(datestampValue, "-", ":")
+ timestampValue = strings.ReplaceAll(timestampValue, "-", ":")
+
+ dateParts := strings.Split(datestampValue, ":")
+
+ year, err := strconv.ParseUint(dateParts[0], 10, 16)
+ if err != nil {
+ log.Panicf("could not parse year")
+ }
+
+ month, err := strconv.ParseUint(dateParts[1], 10, 8)
+ if err != nil {
+ log.Panicf("could not parse month")
+ }
+
+ day, err := strconv.ParseUint(dateParts[2], 10, 8)
+ if err != nil {
+ log.Panicf("could not parse day")
+ }
+
+ timeParts := strings.Split(timestampValue, ":")
+
+ hour, err := strconv.ParseUint(timeParts[0], 10, 8)
+ if err != nil {
+ log.Panicf("could not parse hour")
+ }
+
+ minute, err := strconv.ParseUint(timeParts[1], 10, 8)
+ if err != nil {
+ log.Panicf("could not parse minute")
+ }
+
+ second, err := strconv.ParseUint(timeParts[2], 10, 8)
+ if err != nil {
+ log.Panicf("could not parse second")
+ }
+
+ timestamp = time.Date(int(year), time.Month(month), int(day), int(hour), int(minute), int(second), 0, time.UTC)
+ return timestamp, nil
+}
+
+// IsTime returns true if the value is a `time.Time`.
+func IsTime(v interface{}) bool {
+
+ // TODO(dustin): Add test
+
+ return reflect.TypeOf(v) == timeType
+}