Skip to content

Instantly share code, notes, and snippets.

@shotasenga
Created August 24, 2024 02:31
Show Gist options
  • Save shotasenga/18fd226bb53669858fa2141df0671ca6 to your computer and use it in GitHub Desktop.
Save shotasenga/18fd226bb53669858fa2141df0671ca6 to your computer and use it in GitHub Desktop.
Some of the photos exported from Google photos didn't have correct timestamp. This script adjust the date time info based on the exported JSON.
import re
import datetime
import piexif
import glob
import json
import os
from PIL import Image
import shutil
def iterate_images(directory):
for root, dirs, files in os.walk(directory):
for file in files:
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')):
yield os.path.join(root, file)
def pick_one(fpath, matches):
if len(matches) == 0:
return None
elif len(matches) == 1:
return matches[0]
print('Multiple matches found for', fpath)
with Image.open(fpath) as img:
img.show()
for i, m in enumerate(matches):
print(i, m['photoTakenTime']['formatted'])
selected = input('Pick one and press enter:')
return matches[int(selected)]
def retrieve_captured_timestamp(fpath):
fname = re.sub(r'\s*\(\d+\)', '', os.path.basename(fpath))
print(os.path.basename(fpath), fname)
matches = glob.glob(f'Extracted/**/{fname}.json', recursive=True)
meta = pick_one(fpath, [json.load(open(m)) for m in matches])
if meta is None:
return None
return int(meta['photoTakenTime']['timestamp'])
def adjust_date(fpath, captured_at):
if fpath.lower().endswith(('.jpg', '.jpeg')):
exif_dict = piexif.load(fpath)
date_str = datetime.datetime.fromtimestamp(captured_at).strftime('%Y:%m:%d %H:%M:%S')
exif_dict['0th'][piexif.ImageIFD.DateTime] = date_str
exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal] = date_str
exif_dict['Exif'][piexif.ExifIFD.DateTimeDigitized] = date_str
exif_dict['Exif'][piexif.ExifIFD.OffsetTime] = "+00:00"
exif_dict['Exif'][piexif.ExifIFD.OffsetTimeDigitized] = "+00:00"
exif_dict['Exif'][piexif.ExifIFD.OffsetTimeOriginal] = "+00:00"
piexif.insert(piexif.dump(exif_dict), fpath)
os.utime(fpath, (captured_at, captured_at))
def main():
SOURCE_DIR = './No dates'
OUT_DIR = './New dates'
UNKNOWN_DIR = os.path.join(OUT_DIR, 'Unknown')
os.makedirs(OUT_DIR, exist_ok=True)
os.makedirs(UNKNOWN_DIR, exist_ok=True)
for fpath in iterate_images(SOURCE_DIR):
destination = os.path.join(OUT_DIR, os.path.basename(fpath))
if os.path.exists(destination):
print('Already exists', destination)
continue
captured_at = retrieve_captured_timestamp(fpath)
if captured_at is None:
shutil.copy2(fpath, os.path.join(UNKNOWN_DIR, os.path.basename(fpath)))
else:
shutil.copy2(fpath, destination)
adjust_date(destination, captured_at)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment