It may depend on the camera/phone and OS; but, I don't think the timezone is explicitly stored in the picture's EXIF metadata.
In some metadata, there is a
GPS Time (Atomic Clock) which is set to UTC. So, Photos probably just calculates the offsets of
Date and Time (Original) to display the timezone.
You may be able to use exiftool to build a list of those two times for your pictures, and search for outliers which are more (or less) different than the others.
Update from original poster:
I threw together a quick Python script to compare these times, and print the ones that aren't in the expected time zone, or have different values for minutes. You'll need to export the unmodified originals from Photos, since the modified ones don't have this metadata, and then pass their filenames to this script.
Of course, I have no idea if this is anything close to what Photos does to set the time zone. But it correctly identified the photos that I knew of with the wrong time zone, and didn't find any false positives.
from subprocess import check_output
import sys, re, os
from dateutil.parser import parse
from datetime import datetime
expected_offset_hours = 8.0 # set to appropriate time zone offset
def get_field(out, name):
match = re.search("^" + re.escape(name) + "\t(.+?)$", out, re.MULTILINE)
for arg in sys.argv[1:]:
if not os.path.exists(arg):
out = check_output(["exif", "-m", arg])
gps_date = get_field(out, "GPS Date")
gps_time = get_field(out, "GPS Time (Atomic Clock)")
if gps_date == None or gps_time == None:
print arg + "\tNo GPS date/time"
gps_parsed = datetime.strptime(gps_date + " " + gps_time, '%Y:%m:%d %H:%M:%S.%f')
orig_datetime = get_field(out, "Date and Time (Original)")
if orig_datetime == None:
orig_parsed = datetime.strptime(orig_datetime, '%Y:%m:%d %H:%M:%S')
offset_secs = (orig_parsed - gps_parsed).total_seconds()
offset_hours = round(offset_secs / 3600)
offset_mins = abs(offset_secs - (offset_hours * 3600)) // 60
if offset_hours != expected_offset_hours or offset_mins > 0:
#print gps_date + ' ' + gps_time + ' ' + str(gps_parsed)
#print orig_datetime + ' ' + str(orig_parsed)
print arg + "\t" + str(offset_hours) + "\t" + str(offset_mins)