Technical summary:
- One can use
PIL
to extract EXIF tags byImage._getexif()
. - EXIF tags are stored in a dict, keyed by intergers. One needs to use
ExifTags.TAGS.items()
to enumerate the mapping between integer and string name. - The
DateTime
tag has a special format:2023:11:11 15:56:57
. The delimieter of date segment is:
instead of-
. There is no timezone part in the string.
Following is the utility snippet:
from PIL import Image, ImageDraw, ImageFont, ExifTags
def get_exif_by_tag_name(image, tag_name):
exif = image._getexif()
for k, v in ExifTags.TAGS.items():
if v == tag_name:
return exif.get(k, None)
return None
def get_datetime_from_exif(path, tz):
image = Image.open(path)
s = get_exif_by_tag_name(image, 'DateTime')
d, t = s.split()
d = d.replace(':', '-')
fs = f'{d} {t} {tz}'
dt = dt_parser.parse(fs)
return dt
Usage:
get_datetime_from_exif(path, 'HKT')
datetime.datetime(2023, 11, 11, 15, 56, 57, tzinfo=tzlocal())
One can try to extract other fields related with datetime, but not all the fields are present in file: (it is subject to the device)
get_exif_by_tag_name(image, 'DateTime')
get_exif_by_tag_name(image, 'DateTimeOriginal')
get_exif_by_tag_name(image, 'TimeZoneOffset')
Update 20240225
In the recent development of our open source PhotoCast system, we realized that different cameras record data in different fields. Based on current knowledge, we adopted the following resolution path of photo timestamp:
- timestamp given by caller. This allows the client to ultimately modify the index datetime upon corner cases.
EXIF.DateTimeOriginal
-- This is sometimes referred to as "Content Create Time" in photo editing software/ file system; this value is also by default retained when converting file formats.EXIF.DateTimeDigitized
-- This is sometimes referred to as "Content Modified Time" in photo editing software / file system; this value is also by default retained when converting file formats.EXIF.DateTime
-- This is sometimes referred to as "Create Time". Some cameras retain this value as when the photo was taken. Some cameras / photo editing software edits this value as when the image file was created.
Following is one example return from our PhotoCast sytem, demonstrating how those values may differ from each other:
'timestamp_candidates': [{'source': 'EXIF.DateTimeOriginal', 'value': 'Sun, 18 Feb 2024 10:20:58 GMT'}, {'source': 'EXIF.DateTimeDigitized', 'value': 'Sun, 18 Feb 2024 10:20:58 GMT'}, {'source': 'EXIF.DateTime', 'value': 'Sun, 18 Feb 2024 15:16:58 GMT'}, {'source': 'backend.timestamp', 'value': 'Sun, 25 Feb 2024 03:13:50 GMT'}]}