Back in February, some friends and I spent a week visiting Punta Cana. We made a lot of photos there but, when we came back, we realized that most of us (not all!) forgot to adjust our camera's date to the foreign timezone, which was 5 hours behind of ours.

I imported all our photos in iPhoto but the difference in their timestamps made all images appear unsorted in the main view; this was very annoying. So I wondered if the EXIF information embedded in them could be easily fixed. It turns out it is possible, but the tools to do so — or at least the one I used — leave a lot to be desired: it was not exactly trivial to resolve the problem.

In order to modify the EXIF information, I installed the free libexif library alongside a very simple frontend to it named exif, distributed from the same page. To painlessly get this in Mac OS X, just use the graphics/exif package in pkgsrc.

Then I had to see which fields I wanted to modify in each photo. This can be accomplished with the exif --tag <photo-name.jpg> command, which shows all tags currently attached to the photo and their corresponding values. Skimming through the resulting list, it is easy to spot which fields correspond to date information. I specifically picked up 0x0132, 0x9003 and 0x9004, but some of them may not exist in your images.

With this information at hand, I wrote a little script that looped over all affected photos and, for each tag, adjusted it to the new value. It goes as follows:
#!/bin/sh

while [ $# -gt 0 ]; do
file=$1; shift

for tag in 0x0132 0x9003 0x9004; do
date=$(exif --tag=${tag} $file | grep Value |
cut -d ' ' -f 4-)
date=$(perl adjust.pl "${date}")
exif --tag=${tag} --ifd=0 --set-value="${date}" ${file}
mv ${file}.modified.jpeg ${file}
done
done
The magic to subtract five hours to each date is hidden in the adjust.pl script, which looks like this:
($date, $time) = split / /, $ARGV[0];

($year, $month, $day) = split /:/, $date;
($hour, $min, $sec) = split /:/, $time;
$amount = 5;
if ($hour >= $amount) {
$hour -= $amount;
} else {
$hour = $hour - $amount + 24;
if ($day == 1) {
$day = 31;
$month -= 1;
} else {
$day -= 1;
}
}

printf "%04d:%02d:%02d %02d:%02d:%02dn",
$year, $month, $day, $hour, $min, $sec;
I know the code is really crappy but it did the job just fine!