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 datevar 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 UTCvar 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 nullif (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