More than once I’ve found myself in a situation where I had happily taken pictures with my digital camera only to discover afterwards that the camera-internal clock was running fast or slow. Whether it’s seconds to a few minutes or whole hour increments due to a forgotten daylight savings time adjustment or travel beyond one timezone – there are situations when you want that time stored in the picture’s meta data to be precise. Thankfully known offsets can be corrected with the help of Phil Harvey’s great piece of software ExifTool, however there are a few tricky details.

This article exposes them to some length, so depending on how interested you are in those details you may or may not want to skip ahead to the solution offered at the end.

ExifTool, show me all the dates

Let’s first have a look at all the various dates stored in the JPEG file:

$ exiftool -AllDates DSC01234.JPG

Date/Time Original              : 2011:09:10 17:12:59
Create Date                     : 2011:09:10 17:12:59
Modify Date                     : 2011:09:10 17:12:59

All the dates? Well, apparently there’s more to it than that, as the following command reveals.

$ exiftool -a DSC01234.JPG | grep Date

File Modification Date/Time     : 2011:09:10 17:12:59+02:00
Modify Date                     : 2011:09:10 17:12:59
Date/Time Original              : 2011:09:10 17:12:59
Create Date                     : 2011:09:10 17:12:59
Modify Date                     : 2011:09:10 17:12:59

The parameter -a results in ExifTool printing all meta data out of which only the Date ones are extracted. While the File Modification Date/Time is easily explained as meta data stored outside the realm of the JPEG file but instead in the file system, why are there two occurrences of Modify Date? To find out let’s turn on the verbose output of ExifTool that yields a tree view.

$ exiftool -v DSC01234.JPG

  ExifToolVersion = 8.15
  FileName = DSC01234.JPG
  [...]
  FileModifyDate = 1315667579
  [...]
JPEG APP1 (19371 bytes):
  ExifByteOrder = II
  + [IFD0 directory with 11 entries]
  | [...]
  | 1)  Make = SONY
  | 2)  Model = DSC-F828
  | [...]
  | 7)  ModifyDate = 2011:09:10 17:12:59
  | [...]
  | 9)  ExifOffset (SubDirectory) -->
  | + [ExifIFD directory with 30 entries]
  | | [...]
  | | 4)  ExifVersion = 0220
  | | 5)  DateTimeOriginal = 2011:09:10 17:12:59
  | | 6)  CreateDate = 2011:09:10 17:12:59
  | | [...]
  | [...]
  + [IFD1 directory with 10 entries]
  | [...]
  | 1)  Make = SONY
  | 2)  Model = DSC-F828
  | [...]
  | 7)  ModifyDate = 2011:09:10 17:12:59
  | 8)  ThumbnailOffset = 2486
  | 9)  ThumbnailLength = 16879
[...]

I shortened the output to give a clear view on the relevant data (camera data is also supplied in case all of this is model-dependent). This shows first of all two subtrees named IFD0 and IFD1, each of which contains a ModifyDate field. IFD0 contains much more meta data than IFD1, including the sub-subtree ExifIFD that contains the two date fields DateTimeOriginal and CreateDate. But back to IFD1. This is the only place where there’s any mention of the embedded thumbnail picture in the form of ThumbnailOffset and ThumbnailLength. So it appears that IFD1 holds the meta data for the thumbnail picture, a finding that’s confirmed by ExifTool’s man page. Finally there’s the field FileModifyDate whose value doesn’t look at all like a date at first because it’s in unconverted Unix time format.

In order to really get all date/time meta information, those not contained in the IFD0 subtree have to be specified explicitly.

$ exiftool -AllDates -IFD1:ModifyDate -FileModifyDate -G1 DSC01234.JPG

[ExifIFD]       Date/Time Original              : 2011:09:10 17:12:59
[ExifIFD]       Create Date                     : 2011:09:10 17:12:59
[IFD0]          Modify Date                     : 2011:09:10 17:12:59
[IFD1]          Modify Date                     : 2011:09:10 17:12:59
[System]        File Modification Date/Time     : 2011:09:10 17:12:59+02:00

Here the parameter -G1 has been added to show the second-level hierarchy of each entry.

Now for the offset correction itself

Now that we know all about retrieving date-related meta data, let’s get back to the problem at hand, that is modifying said data. The man page for ExifTool and additionally the one for Image::ExifTool::Shift.pl is quite detailed so I’ll only give a brief overview. Include a parameter like -AllDates-='7:8:9 12:34:56' to move all date fields 7 years, 8 months, 9 days, 12 hours, 34 minutes, and 56 seconds into the past relative to the meta data currently stored. Use += instead of -= to move them into the future. But wait, all dates? If you thought all the talking about the five different date fields was excessive and skipped it, try the following.

$ exiftool -AllDates-='0:0:0 12:34:56' DSC01234.JPG
$ exiftool -AllDates -IFD1:ModifyDate -FileModifyDate -G1 DSC01234.JPG

[ExifIFD]       Date/Time Original              : 2011:09:10 04:38:03
[ExifIFD]       Create Date                     : 2011:09:10 04:38:03
[IFD0]          Modify Date                     : 2011:09:10 04:38:03
[IFD1]          Modify Date                     : 2011:09:10 17:12:59
[System]        File Modification Date/Time     : 2011:10:07 14:58:32+02:00

Unfortunately the IFD1 Modify Date wasn’t modified and the File Modification Date/Time was changed to right now. While you may like the latter to reflect the last change performed on the file I’m assuming you’d like it to also indicate the time the picture was taken. This can be achieved by copying the Date/Time Original to the File Modification Date/Time like this:

$ exiftool '-DateTimeOriginal>FileModifyDate' DSC01234.JPG
$ exiftool -AllDates -IFD1:ModifyDate -FileModifyDate DSC01234.JPG

Date/Time Original              : 2011:09:10 04:38:03
Create Date                     : 2011:09:10 04:38:03
Modify Date                     : 2011:09:10 04:38:03
Modify Date                     : 2011:09:10 17:12:59
File Modification Date/Time     : 2011:09:10 04:38:03+02:00

That still leaves the Modify Date of the thumbnail untouched, though. To fix it, the same offset correction that was applied to -AllDates before has to applied to -IFD1:ModifyDate as well.

$ exiftool -IFD1:ModifyDate-='0:0:0 12:34:56' DSC01234.JPG
$ exiftool -AllDates -IFD1:ModifyDate -FileModifyDate DSC01234.JPG

Date/Time Original              : 2011:09:10 04:38:03
Create Date                     : 2011:09:10 04:38:03
Modify Date                     : 2011:09:10 04:38:03
Modify Date                     : 2011:09:10 04:38:03
File Modification Date/Time     : 2011:10:07 15:15:48+02:00

Great. Now the thumbnail data is fixed, but as the JPEG file was modified in the process the File Modification Date/Time was reset to the current time once more. Thankfully ExifTool created a backup before the first modification of the file, so let’s revert to that before utilizing the one-step solution.

$ mv DSC01234.JPG_original DSC01234.JPG
$ exiftool -AllDates -IFD1:ModifyDate -FileModifyDate DSC01234.JPG

Date/Time Original              : 2011:09:10 17:12:59
Create Date                     : 2011:09:10 17:12:59
Modify Date                     : 2011:09:10 17:12:59
Modify Date                     : 2011:09:10 17:12:59
File Modification Date/Time     : 2011:09:10 17:12:59+02:00

The solution

To sum it all up, the JPEG file as well as the file system contains date-related meta data that can be changed using ExifTool. However, the three different areas (high-res picture, thumbnail picture, file system meta data) need to be explicitly specified to really change all of them. To shift all those dates e.g. 12 hours, 34 minutes, and 56 seconds back in time, use the following command:

$ shift='0:0:0 12:34:56' exiftool -AllDates-="$shift" \
-IFD1:ModifyDate-="$shift" -FileModifyDate-="$shift" DSC01234.JPG
$ exiftool -AllDates -IFD1:ModifyDate -FileModifyDate DSC01234.JPG

Date/Time Original              : 2011:09:10 04:38:03
Create Date                     : 2011:09:10 04:38:03
Modify Date                     : 2011:09:10 04:38:03
Modify Date                     : 2011:09:10 04:38:03
File Modification Date/Time     : 2011:09:10 04:38:03+02:00

If you want to exclude certain meta data fields from the offset correction, just remove the appropriate command line parameters. The only field for which I think that makes any sense is the File Modification Date/Time if you want that to reflect the last change done to the file as opposed to the time when the picture was taken. Speaking of that field, if you did any modifications to the file before, it won’t hold the time you pressed the release anymore, anyway. Using the all-in-one offset correction method would be a bad idea in that case. However, if you want the file system meta data to reflect the picture-taking time despite any modifications of the file you can always achieve that by executing

$ exiftool '-DateTimeOriginal>FileModifyDate' DSC01234.JPG

after you’re done with any modifications to the file, be it EXIF-related or otherwise.