EXIF Nonsense
tl;dr
My Canon’s internal clock was not set correctly when I went on vacation and I used exiftool (link) to fix the timestamps with this command:
exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' '-TimeZone*=+2:00' filtered_canon_copy_no_video
exiftool -overwrite_original_in_place '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 6:0:0" filtered_canon_copy_no_video
The first one shifts the dates to the correct time, and sets the timezone tag. The second one sets the file’s modification date to 6 hours before the date taken so that the macOS file system correctly lists it.
I went on vacation, and unfortunately, my Canon’s internal clock wasn’t quite accurate.
I’m always wrestling with this camera about daylight savings time, using it so sparingly that I have to switch it back nearly every time.
On top of this, it was 6 hours of timezone off when I went to Europe.
All I really want is a unix timestamp for these photos, which I can display later as “6pm” with some javascript, knowing that it means 6pm in CEST, but the timestamps need to be fixed for anything else to happen.
Step One: Find the correct time
I just took a photo of time.gov. I plan to adjust every photo’s exif date in some automated fashion, given that there are 2,277 photos that need to have their timestamp fixed.
Step Two: Unix timestamps? How do jpegs store their EXIF data?
EXIF data doesn't require timezones. It was never required, and there are now many ways to denote the timezone in EXIF data.
As for the second question? I think it’s a rabbit hole that is frankly, irrelevant if I use this library.
Step Three: exiftool
It’s neat. Running the command shows you the (extensive) documentation. There’s a built in flag called “globalTimeShift”!
Side note: Timezone false hope?
Asking exiftool to show you all the timestamps in the file (with -time:all)
Asking for exiftool -time:all IMG_7343.JPG (from my camera) gives me a timezone and it’s offset. Is it just my computer system’s local timezone, or was it from the photo? This was the output.
> exiftool -time:all IMG_7343.JPG
File Modification Date/Time : 2025:06:18 01:13:04-04:00
File Access Date/Time : 2025:07:12 21:48:53-04:00
File Inode Change Date/Time : 2025:07:12 21:48:52-04:00
Modify Date : 2025:06:18 07:13:04
Date/Time Original : 2025:06:18 07:13:04
Create Date : 2025:06:18 07:13:04
Time Zone : -05:00
Time Zone City : New York
Daylight Savings : Off
Sub Sec Time : 00
Sub Sec Time Original : 00
Sub Sec Time Digitized : 00
Create Date : 2025:06:18 07:13:04.00
Date/Time Original : 2025:06:18 07:13:04.00
Modify Date : 2025:06:18 07:13:04.00
Asking for exiftool -time:all IMG_0569.JPG (from my phone) gives me a GPS time stamp because it’s geotagged. It flips between my phone’s local time and GMT. The offset from GMT is specified in “Offset Time”, just like the proposal suggested! Neat!
> exiftool -time:all IMG_0569.JPG
File Modification Date/Time : 2025:05:20 22:44:21-04:00
File Access Date/Time : 2025:07:12 21:47:56-04:00
File Inode Change Date/Time : 2025:06:11 02:44:57-04:00
Modify Date : 2025:05:20 22:43:19
Date/Time Original : 2025:05:20 22:43:19
Create Date : 2025:05:20 22:43:19
Offset Time : -04:00
Offset Time Original : -04:00
Offset Time Digitized : -04:00
Sub Sec Time Original : 582
Sub Sec Time Digitized : 582
GPS Time Stamp : 02:43:07
GPS Date Stamp : 2025:05:21
Profile Date Time : 2022:01:01 00:00:00
Create Date : 2025:05:20 22:43:19.582-04:00
Date/Time Original : 2025:05:20 22:43:19.582-04:00
Modify Date : 2025:05:20 22:43:19-04:00
GPS Date/Time : 2025:05:21 02:43:07Z
Comparing my phone’s metadata from the cameras shows that yes, the camera did actually add a time zone to the exif data, but the lack of standards makes this process very camera-specific.
Actually finding the offset I need
Looking at the exif for the photo of time.gov:
> exiftool -time:all timestamp_correction_baseline.JPG
File Modification Date/Time : 2025:07:12 18:29:04-04:00
File Access Date/Time : 2025:07:12 21:04:07-04:00
File Inode Change Date/Time : 2025:07:12 18:18:44-04:00
Modify Date : 2025:07:12 18:29:03
Date/Time Original : 2025:07:12 18:29:03
Create Date : 2025:07:12 18:29:03
Time Zone : -05:00
Time Zone City : New York
Daylight Savings : Off
Sub Sec Time : 46
Sub Sec Time Original : 46
Sub Sec Time Digitized : 46
Create Date : 2025:07:12 18:29:03.46
Date/Time Original : 2025:07:12 18:29:03.46
Modify Date : 2025:07:12 18:29:03.46
I’m going to ignore all the time zones at the moment, and focus on getting the values I need to align it to the correct time, and worry about the time zone later.
UTC was 22:17:20 in the photo.
(-5, EST) makes it 17:17:20, but one forgets that it’s currently Daylight Savings. Thank GOD that
(-4, EDT) makes it 18:17:20
Camera: 18:29:03
Truth: 18:17:20
Diff: 00:11:43
So, the camera is fast by 11 minutes and 43 seconds.
Which exiftool command actually works?!
I did some of this work at a library, and the wifi disconnected so often that I had decided to just forego internet access for this work session. No internet means that it’s time to actually look at Exiftool’s built-in documentation.
It’s ridiculously good, with dozens of examples of how to use the countless flags and features that this program packs.
I’m simply searching for date in the file and trying everything that it offers.
To test these commands safely, I’ve copied some photos into a separate test directory.
exiftool documentation snippet:
"exiftool -DateTimeOriginal-='0:0:0 1:30:0' dir"
Adjust original date/time of all images in directory "dir" by
subtracting one hour and 30 minutes. (This is equivalent to
"-DateTimeOriginal-=1.5". See Image::ExifTool::Shift.pl for
details.)
"exiftool -createdate+=3 -modifydate+=3 a.jpg b.jpg"
Add 3 hours to the CreateDate and ModifyDate timestamps of two
images.
These don’t work. It simply sets all the timestamps to the current time.
exiftool documentation snippet:
"ShiftTime"
Shifts EXIF-formatted date/time string by a specified amount. Start with
a leading minus sign to shift backwards in time. See
Image::ExifTool::Shift.pl for details about shift syntax. For example,
to shift a date/time value back by one year:
exiftool -p '${createdate;ShiftTime("-1:0:0 0")}' a.jpg
This displays what I want it to do (in the console’s output), but I don’t need the dates echoed back to me, I need them applied to the file.
exiftool documentation snippet:
-globalTimeShift *SHIFT*
Shift all formatted date/time values by the specified amount when
reading. Does not apply to unformatted (-n) output. *SHIFT* takes
the same form as the date/time shift when writing (see
Image::ExifTool::Shift.pl for details), with a negative shift being
indicated with a minus sign ("-") at the start of the *SHIFT*
string. For example:
# return all date/times, shifted back by 1 hour
exiftool -globalTimeShift -1 -time:all a.jpg
# set the file name from the shifted CreateDate (-1 day) for
# all images in a directory
exiftool "-filename<createdate" -globaltimeshift "-0:0:1 0:0:0" \
-d %Y%m%d-%H%M%S.%%e dir
This was promising, but, I can’t figure out how to find Shift.pl to clarify these notes. None of the examples adjust the original dates.
exiftool '-FileModifyDate<DateTimeOriginal' dir
Finally, this command gets me somewhere. The changes applied from other commands finally become visible in the file browser with this!
exiftool -FileModifyDate-='0:0:0 0:11:43' filtered_test_corrected
Works! I suppose macos only cares about “FileModifyDate”, and ignores all the other date tags.
Progress, at last!
Trust, but verify
Sure, I ran some command that theoretically set the timestamps correctly, but I wanted a way to be a little more sure.
Luckily, I had developed a slight infatuation (article coming soon) with the train station clocks, and had a handful of photographs of them. You’d hope that a train clock is an accurace reference, given some relevant history.
So, I checked the (now maybe-fixed) timestamps on these clock photos. I know that my camera should have been off by 6 hours, because I went to a timezone with a 6 hour difference from EST, where it was previously set.
What’s intriguing is that at first glance, the camera’s timestamps have been fixed with a simple 11 minute offset?
Closer inspection revealed that 12-hour time gave me false hope - photos at 12 noon had a timestamp of just around midnight. My phone had been in 24-hour time for years, but I found out here that my laptop was still set to 12-hour time.
Ignoring that sidenote, it appears that the macOS finder app only cares about the file’s modification date.
Using this command:
exiftool -AllDates-='0:0:0 0:11:43' filtered_test_corrected
You would think that “AllDates” would modify all the date tags, right? Wrong. https://exiftool.org/forum/index.php?topic=8412.0.
Also in that link, you can “fix” this by doing
exiftool '-FileModifyDate<DateTimeOriginal' FileOrDir
Which does work!
Interestingly, doing it this way, the time zone from my computer has been applied. Exiftool warned about this, and now it’s time to fix it.
Before I do that, I can actually combine the two previous commands by doing this:
exiftool '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 0:11:43" filtered_test_corrected
Well, not quite. That only changes the file modification timestamp. It’s actually better to do the previous command, as it modifies the original dates, and then also makes the file modification date change.
The documentation showed that you could match many tags with an *, so I tried:
exiftool '-*Date<DateTimeOriginal' -globaltimeshift "-0:0:0 0:11:43" filtered_test_corrected
Which ended up setting ALL the date tags, EXCEPT the one that it was pulling from. Yet another mess.
So, the working process so far includes:
exiftool -AllDates-='0:0:0 0:11:43' filtered_test_corrected
to set the proper metadata to the “right time” (ignoring time zones).
exiftool '-FileModifyDate<DateTimeOriginal' filtered_test_corrected
to let the operating system actually read said time correctly
and now, to fix the time zones.
exiftool '-EXIF:OffsetTime*=+02:00' filtered_test_corrected
was something suggested by https://exiftool.org/forum/index.php?topic=13170.0
but I’m honestly getting confused at this rate.
working from the top:
- adjusting the slow clock so it’s correct (in NYC)
- changing the time zone offset so it’s correct (for UTC+2) (https://superuser.com/questions/1840199/how-to-fix-timezone-of-images-using-exiftool)
- +6 is correct? because I’m trying to go from -4 to +2
- setting the filemodifydate so finder displays the photo’s original timestamp
exiftool -AllDates-='0:0:0 0:11:43' filtered_test_corrected
exiftool -OffsetTimeOriginal+=+6:00 -OffsetTimeDigitized+=+6:00 -CreateDate+=+6:00 -DateCreated+=+6:00 -DigitalCreationTime+=+6:00 -TimeCreated+=+6:00 filtered_test_corrected
exiftool '-FileModifyDate<DateTimeOriginal' filtered_test_corrected
doesn’t work.
exiftool '-TimeZone*=+6:00' filtered_test_corrected
does set the timezone shown by exiftool’s -time:all command
but doesn’t do anything for the operating system
BUT
google photos likes this timezone tag!
from the top again
6:00:00
0:11:43
5:48:17
- I’ve done 6 hours - 11 minutes and 43 seconds, getting 5 hours, 48 minutes, and 17 seconds.
- This way, the photo’s capture date has been shifted 6 hours forward and corrected for the 11 minute fast time inaccuracy in one move.
- This sets the photo’s time zone to +2:00. The metadata still says that the timezone city is “New York”, but that’s simply cosmetic
- This sets the file’s modification date to the original date, with a 6 hour shift.
exiftool -AllDates+='0:0:0 5:48:17' filtered_test_corrected
exiftool '-TimeZone*=+2:00' filtered_test_corrected
exiftool '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 6:0:0" filtered_test_corrected
I’m satisfied. The metadata seems to match the stuff that comes from my phone and glasses: the creation date is in the “local” (+2:00) time zone, and the file modification date is that date, translated for my computer’s (-4:00) time zone. Google Photos displays the local time, with the +2 timezone displayed, and it’s time to do this to the entire photo library.
exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' filtered_test_corrected
exiftool -overwrite_original_in_place '-TimeZone*=+2:00' filtered_test_corrected
exiftool -overwrite_original_in_place '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 6:0:0" filtered_test_corrected
interested in saving time, can this be one command?
exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' '-TimeZone*=+2:00' '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 6:0:0" filtered_test_corrected
forgot that the file modification date took the original DateTimeOriginal tag
exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' '-TimeZone*=+2:00' '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 5:48:17" filtered_test_corrected
tried to combine the global shift in here
exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' '-TimeZone*=+2:00' '-FileModifyDate<DateTimeOriginal' -globaltimeshift "+0:0:0 5:48:17" filtered_test_corrected
global shift was negative instead of positive
I’m not messing with what works. Back to the 3 commands.
I can at LEAST incorporate the time zone command into another command.
exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' '-TimeZone*=+2:00' filtered_test_corrected
exiftool -overwrite_original_in_place '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 6:0:0" filtered_test_corrected
but I’m leaving the FileModifyDate logic the same.
Time to test this on some more images
exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' '-TimeZone*=+2:00' larger_test_to_fix_timestamps
exiftool -overwrite_original_in_place '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 6:0:0" larger_test_to_fix_timestamps
With only 101 images, this took a second or two to execute. 748MB. I’m scared that with 2,278 items, 17.19GB is a lot to just “see what happens” with.
I didn’t test on videos! I should do that.
I copied all the photos to a new folder, so any changes are “isolated”.
Final command:
exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' '-TimeZone*=+2:00' filtered_canon_copy_no_video
exiftool -overwrite_original_in_place '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 6:0:0" filtered_canon_copy_no_video
It took a while. The command doesn’t give progress while it’s running, so I checked in Activity Manager to see what was happpening. My laptop didn’t slow down noticeably, but sure enough, Perl was doing something big - 40-80% of CPU, and gigabytes of disk usage.
> exiftool -overwrite_original_in_place -AllDates+='0:0:0 5:48:17' '-TimeZone*=+2:00' filtered_canon_copy_no_video
1 directories scanned
2272 image files updated
> exiftool -overwrite_original_in_place '-FileModifyDate<DateTimeOriginal' -globaltimeshift "-0:0:0 6:0:0" filtered_canon_copy_no_video
1 directories scanned
2272 image files updated
Success.