Skip to content

Instantly share code, notes, and snippets.

@okwes
Created October 29, 2024 04:15
Show Gist options
  • Save okwes/d00c6e064a5ba7731ff31db853489dcc to your computer and use it in GitHub Desktop.
Save okwes/d00c6e064a5ba7731ff31db853489dcc to your computer and use it in GitHub Desktop.
Immich Bulk Date Shift. The Immich web ui only supports setting one time for many assets, this code allows the date of many assets to be shifted by x days, seconds etc. This will shift the date/time for all photos in a given album
# under CC0/Public Domain. Do as you like. NO WARRANTY
# make venv, pip install requests python-dateutil
# Replace the 3 variables at the top and adjust the function call for adjust_iso8601_time() to suit your desired time change for all photos in the album you give.
# Better code may exist but this is a quick fix to a problem I had
import requests
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
import json
API_URL = "https://immich.example.com/api/"
API_KEY = "don't share me!"
ALBUM_ID = "uuid" # this can be copied from the album view url when viewing
def adjust_iso8601_time(iso_string: str, days=0, hours=0, minutes=0, timezone='UTC') -> str | None:
try:
# Parse the ISO 8601 string, handling time zones manually
if 'Z' in iso_string:
iso_string = iso_string.replace('Z', '+00:00') # Convert 'Z' to UTC offset
dt = datetime.fromisoformat(iso_string)
# Convert to the specified time zone if necessary
if timezone != 'UTC':
dt = dt.astimezone(ZoneInfo(timezone))
# Adjust the datetime object by specified amounts
adjusted_dt = dt + timedelta(days=days, hours=hours, minutes=minutes)
# Convert back to ISO 8601 format in UTC
new_iso_string = adjusted_dt.astimezone(ZoneInfo('UTC')).isoformat(timespec='milliseconds').replace('+00:00', 'Z')
return new_iso_string
except ValueError as e:
print(f"Error parsing date: {e}")
return None
def change_date_immich(photo_uuid: str, new_date: str) -> requests.Response:
url = f"{API_URL}assets"
payload = json.dumps({
"dateTimeOriginal": new_date,
"ids": [
photo_uuid
]
})
headers: dict[str, str] = {
'Content-Type': 'application/json',
'x-api-key': API_KEY
}
return requests.request("PUT", url, headers=headers, data=payload)
def main():
album_url = f"{API_URL}albums/{ALBUM_ID}"
payload = {}
headers = {
'Accept': 'application/json',
'x-api-key': API_KEY
}
response = requests.request("GET", album_url, headers=headers, data=payload)
for asset in response.json()["assets"]:
exif_data = asset.get("exifInfo")
if exif_data:
og_time = exif_data.get("dateTimeOriginal")
if og_time:
new_time = adjust_iso8601_time(og_time, -31, 0, 0)
print(f"Oldtime: {og_time}, adjusted: {new_time}")
if new_time:
print(change_date_immich(asset["id"], new_time).text)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment