Android Get Photo Timezone

April 3, 2020
Using EXIF or GPS Location

Photo exif data doesn’t contain timezone information, just a timestamp.

NOTE: Android Read Exif Date as LocalDateTime

Probable Solutions

  • You can use device default timezone: ZoneId.systemDefault()
  • You can guess the correct timezone by using photo’s GPS location
  • You can let user select timezone when importing photos by batches, and verify accuracy by showing actual time of a few samples

Problems

  • The user might forget to switch device timezone when travelling abroad, thus it will mess up the whole timestamp accuracy
  • The user might take photos in home country, then travel abroad and try to import photos using device timezone
  • User might not switch on GPS for photos

Option 1: Get Timezone Offset from EXIF

TAG_OFFSET_TIME_ORIGINAL is introduced in Android R/11.

A tag used to record the offset from UTC (the time difference from Universal Time Coordinated including daylight saving time) of the time of DateTimeOriginal tag. The format when recording the offset is “±HH:MM”.

val offsetString = exif.getAttribute(ExifInterface.TAG_OFFSET_TIME_ORIGINAL)
val offset = if (offsetString != null) {
    ZoneOffset.of(offsetString)
}

NOTE: androidx.exifinterface 1.2.x is required for xifInterface.TAG_OFFSET_TIME_ORIGINAL

NOTE: Read Exif with Scoped Storage

NOTE: I tested on Huawei P30 with Android Q/10, such information is not available.

If your photo have GPS info, you could possibly derived the offset as well (by calculating the diff between photo date and GPS date/UTC).

// get exif date
var exifDateString = exif.getAttribute(ExifInterface.TAG_DATETIME_ORIGINAL)?.replace("-", ":")
if (exifDateString == null) {
    exifDateString = exif.getAttribute(ExifInterface.TAG_DATETIME)?.replace("-", ":")
}
val exifDate = if (exifDateString != null) {
    LocalDateTime.parse(exifDateString, exifDateFormatter)
}
else null

// get gps date - in UTC
var gpsDateStamp = exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP)
var gpsTimeStamp = exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP)
val gpsDate = if (gpsDateStamp != null && gpsTimeStamp != null) {
    val gpsDateString = "$gpsDateStamp $gpsTimeStamp".replace("-", ":")
    // Timber.d("gpsDateString=$gpsDateString")
    LocalDateTime.parse(gpsDateString, exifDateFormatter)
} else null

if (gpsDate != null && exifDate != null) {
    var minutes = Duration.between(gpsDate, exifDate).toMinutes()
    val mod = minutes % 15
    if (mod > 0) {
        minutes += if (mod <= 8) -mod else 15 - mod
    }
    val seconds = minutes * 60

    val offset = ZoneOffset.ofTotalSeconds(seconds.toInt())
}

Option 2: Convert EXIF Location to Timezone

Get Photo GPS Location With Android 10 Scoped Storage, then convert location to Timezone.

References

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.