Correcting dates on image files

Our camera’s clock got reset and we didn’t notice until we had shot nearly two hundred photos. Doh! Even after we figured out the offset required to correct the problem, it turned out to be a bit involved to apply it. I ended up writing a Ruby script to do it. Then I was able to correct both the filesystem dates as well as the embedded EXIF timestamps for all the images with the following command:

camera_date.rb "18 Jan 2005 23:31:12" "14 Sep 2009 11:31:12" *.PEF

The first time stamp is the incorrect time stamp of one of the images, and the second is the correct time stamp for that particular image. This offset is then applied to all the specified files (*.PEF). The Ruby script is below. It requires that ExifTool be installed.

#!/usr/bin/env ruby
 
require 'time'
 
# 2009-10-17 LHN: Adjust file modification time and EXIF fields of files.
# Used to correct files that were recorded on a camera that had it's clock
# accidentally reset.
 
# Requires ExifTool (http://www.sno.phy.queensu.ca/~phil/exiftool)
 
def help_message
  puts <<HEREDOC
 
Camera Date rev 2009-10-18
 
Camera Date is intended to correct images take on cameras whose clocks were
accidentally reset. It will update the following pieces of information:
  * filesystem timestamp
  * EXIF fields DateTimeOriginal, CreateDate, ModifyDate, Date
 
Syntax is camera_date.rb bad_date good_date file ...
 
bad_date is the date of an image as recorded by the camera
good_date is the correct date for that image
 
bad_date and good_date are used to calculate an ofset that can then be applied
to all specified files.
 
dates are specified in RFC8288 format and must be surrounded by quotes.
 
Example:
camera_date.rb "18 Jan 2005 22:10:03" "14 Sep 2009 10:10:03" IMGP7843.PEF IMGP7845.PEF
 
HEREDOC
  exit
end
 
help_message unless ARGV.length >= 3
 
begin
  INPUT_DATE = Time.parse(ARGV[0])
  OUTPUT_DATE = Time.parse(ARGV[1])
  OFFSET_TOTAL_SECS = OUTPUT_DATE.to_i - INPUT_DATE.to_i
  puts "#{INPUT_DATE} => #{OUTPUT_DATE}"
  puts "Offset in seconds is #{OFFSET_TOTAL_SECS}" 
 
  ARGV[2 .. -1].each{ |entry| 
    mtime = File.stat(entry).mtime
    newtime = mtime + OFFSET_TOTAL_SECS
    puts "#{entry}: #{mtime} -> #{newtime}"
    system("exiftool \"-AllDates=#{newtime.strftime("%Y:%m:%d %H:%M:%S")}\" \"-Date=#{newtime.strftime("%Y:%m:%d")}\" #{entry}")
    system("touch -c -t#{newtime.strftime("%Y%m%d%H%M.%S")} #{entry}")
  }
  puts "Done."
rescue StandardError => e
  puts e
  help_message
end

The problem and command are clear, but To whom are you talking? Where are you when this command is typed? It could be input to the gallery program (application level) or a terminal session (operating system level) and input to a file on a server in a folder unknown.

You corrected them all (200 photos), but the example is a single pic. There is some conventional way of doing blocks of photos that have the same day (date) if not the same hour?

Thanks for creating utilities — I use some from you every day.
–jerry