I'm struggling to understand some intricacies about the Date/Time Original field. Let's use a sample file generated via magick -size 50x50 xc:#0000ff test.jpg as a reference.
> exiftool -Time:all '/var/home/squeak/Desktop/test.jpg' | sort
File Access Date/Time : 2025:02:25 22:08:35+01:00
File Inode Change Date/Time : 2025:02:25 22:08:34+01:00
File Modification Date/Time : 2025:02:25 22:08:34+01:00
Let's write timezone information:
> exiftool -DateTimeOriginal="2020:01:01 12:34:56+02:00" -OffsetTimeOriginal="+02:00" -o test_from_terminal.jpg test.jpg
1 image files created
Now I add a timezone-aware timestamp:
> exiftool -Time:all '/var/home/squeak/Desktop/test_from_terminal.jpg' | sort
Date/Time Original : 2020:01:01 12:34:56
Date/Time Original : 2020:01:01 12:34:56+02:00
File Access Date/Time : 2025:02:25 22:36:15+01:00
File Inode Change Date/Time : 2025:02:25 22:36:14+01:00
File Modification Date/Time : 2025:02:25 22:36:14+01:00
Offset Time Original : +02:00
Note the duplicated Date/Time Original field, once containing a timezoneless timestamp and once containing a timezone-aware value. I wanted to be able to do something like this from Python so I made this with pyexiftool:
from exiftool import ExifToolHelper
with ExifToolHelper() as eh:
eh.set_tags(
"/var/home/squeak/Desktop/test.jpg",
{
"DateTimeOriginal": "2020:01:01 12:34:56+02:00",
"OffsetTimeOriginal": "+02:00",
},
params=[
"-o",
"/var/home/squeak/Desktop/test_from_pyexiftool.jpg",
],
)
The resulting file doesn't have the duplicated Date/Time Original field:
> exiftool -Time:all '/var/home/squeak/Desktop/test_from_pyexiftool.jpg' | sort
Date/Time Original : 2020:01:01 12:34:56+02:00
File Access Date/Time : 2025:02:25 22:39:02+01:00
File Inode Change Date/Time : 2025:02:25 22:39:01+01:00
File Modification Date/Time : 2025:02:25 22:39:01+01:00
Offset Time Original : +02:00
A tool I'm working with can ingest files with the duplicate Date/Time Original value correctly, but not files with only the timezone-aware value. So I wanted to find out why pyexiftool isn't doing the same thing. Under the hood, it seems to execute with sane-looking parameters:
(Pdb)
> /var/home/squeak/.cache/pypoetry/virtualenvs/test-Wt2haxSr-py3.13/lib/python3.13/site-packages/exiftool/helper.py(484)set_tags()
-> return self.execute(*exec_params)
(Pdb) print(exec_params)
['-o', '/var/home/squeak/Desktop/test_from_pyexiftool.jpg', '-DateTimeOriginal=2020:01:01 12:34:56+02:00', '-OffsetTimeOriginal=+02:00', '/var/home/squeak/Desktop/test.jpg']
This was on line https://github.com/sylikc/pyexiftool/blob/master/exiftool/helper.py#L484.
What's the purpose of the double Date/Time Original field? Are the parameters pyexiftool runs exiftool with correct?
Use the command in FAQ #3 (https://exiftool.org/faq.html#Q3). That will show you tags with duplicated names and the groups they belong too, as well as the actual tag names. Without the -s (-short) option (https://exiftool.org/exiftool_pod.html#s-NUM--short), you will see tag descriptions (see FAQ #2 (https://exiftool.org/faq.html#Q2)) not tag names.
Take note that the DateTimeOriginal cannot contain a time zone unless it is the XMP group, e.g. XMP:DateTimeOriginal. See FAQ #5, How do I format date and time information for writing (https://exiftool.org/faq.html#Q5).
Example
C:\>exiftool -P -overwrite_original -all= -subsecDateTimeOriginal="2020:01:01 12:34:56+02:00" y:\!temp\Test4.jpg
1 image files updated
C:\>exiftool -time:all --system:all y:\!temp\Test4.jpg
Date/Time Original : 2020:01:01 12:34:56
Offset Time Original : +02:00
Date/Time Original : 2020:01:01 12:34:56+02:00
C:\>exiftool -a -g -time:all --system:all y:\!temp\Test4.jpg
---- EXIF ----
Date/Time Original : 2020:01:01 12:34:56
Offset Time Original : +02:00
---- Composite ----
Date/Time Original : 2020:01:01 12:34:56+02:00
C:\>exiftool -a -g -s -time:all --system:all y:\!temp\Test4.jpg
---- EXIF ----
DateTimeOriginal : 2020:01:01 12:34:56
OffsetTimeOriginal : +02:00
---- Composite ----
SubSecDateTimeOriginal : 2020:01:01 12:34:56+02:00
PyExiftool is a third party tool. We cannot provide support for it.
Aha, the timezone info is indeed coming from XMP and not EXIF itself.
No need to talk about pyexiftool, I was just wondering whether invoking exiftool with ['-o', '/var/home/squeak/Desktop/test_from_pyexiftool.jpg', '-DateTimeOriginal=2020:01:01 12:34:56+02:00', '-OffsetTimeOriginal=+02:00', '/var/home/squeak/Desktop/test.jpg'] is correct (that's what the library was doing). The parameters were being fed to exiftool in -stay_open mode with -execute, so perhaps that triggers different tag resolution behavior.
Either way, passing EXIF:DateTimeOriginal and XMP:DateTimeOriginal explicitly solves the problem for me. Thanks for your help!
There should be no difference in behaviour with and without -stay_open running.
- Phil
Upon closer inspection, there was no XMP:DateTimeOffset present in test_from_terminal.jpg:
> exiftool -time:all --system:all -a -g ~/Desktop/test_from_terminal.jpg
---- EXIF ----
Date/Time Original : 2020:01:01 12:34:56
Offset Time Original : +02:00
---- Composite ----
Date/Time Original : 2020:01:01 12:34:56+02:00
> exiftool -time:all --system:all -a -g ~/Desktop/test_from_pyexiftool.jpg
---- EXIF ----
Date/Time Original : 2020:01:01 12:34:56+02:00
Offset Time Original : +02:00
I ran the exiftool command that pyexiftool invoked:
> exiftool -o ~/Desktop/test_from_terminal_2.jpg -DateTimeOriginal='2020:01:01 12:34:56+02:00' -OffsetTimeOriginal='+02:00' ~/Desktop/test.jpg
1 image files created
> exiftool -time:all --system:all -a -g ~/Desktop/test_from_terminal_2.jpg
---- EXIF ----
Date/Time Original : 2020:01:01 12:34:56
Offset Time Original : +02:00
---- Composite ----
Date/Time Original : 2020:01:01 12:34:56+02:00
Why could the 'Composite' tag be missing?
The Composite:SubSecDateTimeOriginal tag is generated only if EXIF:DateTimeOriginal and (EXIF:SubSecTimeOriginal or EXIF:OffsetTimeOriginal) exists.
- Phil