fixed PhotoInfo.date() to account for timezone, updated tests
This commit is contained in:
@@ -2,7 +2,7 @@ import platform
|
|||||||
import os.path
|
import os.path
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from plistlib import load as plistload
|
from plistlib import load as plistload
|
||||||
from datetime import datetime
|
from datetime import datetime, timezone, timedelta
|
||||||
import tempfile
|
import tempfile
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import sys
|
import sys
|
||||||
@@ -439,7 +439,8 @@ class PhotosDB:
|
|||||||
self._dbphotos[uuid]["lastmodifieddate"] = datetime.fromtimestamp(
|
self._dbphotos[uuid]["lastmodifieddate"] = datetime.fromtimestamp(
|
||||||
row[5] + td
|
row[5] + td
|
||||||
)
|
)
|
||||||
self._dbphotos[uuid]["imageDate"] = datetime.fromtimestamp(row[5] + td)
|
|
||||||
|
self._dbphotos[uuid]["imageDate"] = datetime.fromtimestamp(row[5] + td) # - row[9], timezone.utc)
|
||||||
self._dbphotos[uuid]["mainRating"] = row[6]
|
self._dbphotos[uuid]["mainRating"] = row[6]
|
||||||
self._dbphotos[uuid]["hasAdjustments"] = row[7]
|
self._dbphotos[uuid]["hasAdjustments"] = row[7]
|
||||||
self._dbphotos[uuid]["hasKeywords"] = row[8]
|
self._dbphotos[uuid]["hasKeywords"] = row[8]
|
||||||
@@ -613,17 +614,16 @@ class PhotoInfo:
|
|||||||
return self.__info["filename"]
|
return self.__info["filename"]
|
||||||
|
|
||||||
def date(self):
|
def date(self):
|
||||||
return self.__info["imageDate"]
|
""" image creation date as timezone aware datetime object """
|
||||||
|
imagedate = self.__info["imageDate"]
|
||||||
|
delta = timedelta(seconds=self.__info["imageTimeZoneOffsetSeconds"])
|
||||||
|
tz = timezone(delta)
|
||||||
|
imagedate_utc = imagedate.astimezone(tz=tz)
|
||||||
|
return imagedate_utc
|
||||||
|
|
||||||
""" returns true if photo is missing from disk (which means it's not been downloaded from iCloud)
|
def tzoffset(self):
|
||||||
NOTE: the photos.db database uses an asynchrounous write-ahead log so changes in Photos
|
""" timezone offset from UTC in seconds """
|
||||||
do not immediately get written to disk. In particular, I've noticed that downloading
|
return self.__info["imageTimeZoneOffsetSeconds"]
|
||||||
an image from the cloud does not force the database to be updated until something else
|
|
||||||
e.g. an edit, keyword, etc. occurs forcing a database synch
|
|
||||||
The exact process / timing is a mystery to be but be aware that if some photos were recently
|
|
||||||
downloaded from cloud to local storate their status in the database might still show
|
|
||||||
isMissing = 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
def path(self):
|
def path(self):
|
||||||
photopath = ""
|
photopath = ""
|
||||||
@@ -663,6 +663,15 @@ class PhotoInfo:
|
|||||||
return self.__uuid
|
return self.__uuid
|
||||||
|
|
||||||
def ismissing(self):
|
def ismissing(self):
|
||||||
|
""" returns true if photo is missing from disk (which means it's not been downloaded from iCloud)
|
||||||
|
NOTE: the photos.db database uses an asynchrounous write-ahead log so changes in Photos
|
||||||
|
do not immediately get written to disk. In particular, I've noticed that downloading
|
||||||
|
an image from the cloud does not force the database to be updated until something else
|
||||||
|
e.g. an edit, keyword, etc. occurs forcing a database synch
|
||||||
|
The exact process / timing is a mystery to be but be aware that if some photos were recently
|
||||||
|
downloaded from cloud to local storate their status in the database might still show
|
||||||
|
isMissing = 1
|
||||||
|
"""
|
||||||
return True if self.__info["isMissing"] == 1 else False
|
return True if self.__info["isMissing"] == 1 else False
|
||||||
|
|
||||||
def hasadjustments(self):
|
def hasadjustments(self):
|
||||||
|
|||||||
@@ -123,8 +123,11 @@ def dump(cli_obj):
|
|||||||
@click.pass_context
|
@click.pass_context
|
||||||
def query(ctx, cli_obj, keyword, person, album, uuid, json):
|
def query(ctx, cli_obj, keyword, person, album, uuid, json):
|
||||||
""" query the Photos database using 1 or more search options """
|
""" query the Photos database using 1 or more search options """
|
||||||
|
|
||||||
|
#if no query terms, show help and return
|
||||||
if not keyword and not person and not album and not uuid:
|
if not keyword and not person and not album and not uuid:
|
||||||
print(cli.commands['query'].get_help(ctx))
|
print(cli.commands['query'].get_help(ctx))
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
photos = cli_obj.photosdb.photos(
|
photos = cli_obj.photosdb.photos(
|
||||||
keywords=keyword, persons=person, albums=album, uuid=uuid
|
keywords=keyword, persons=person, albums=album, uuid=uuid
|
||||||
|
|||||||
BIN
tests/Test-10.14.5.photoslibrary/database/photos.db-shm
Normal file
BIN
tests/Test-10.14.5.photoslibrary/database/photos.db-shm
Normal file
Binary file not shown.
@@ -116,7 +116,7 @@ def test_attributes():
|
|||||||
p = photos[0]
|
p = photos[0]
|
||||||
assert p.keywords() == ["Kids"]
|
assert p.keywords() == ["Kids"]
|
||||||
assert p.filename() == "Pumkins2.jpg"
|
assert p.filename() == "Pumkins2.jpg"
|
||||||
assert p.date() == datetime.datetime(2018, 9, 28, 16, 7, 7)
|
assert p.date() == datetime.datetime(2018, 9, 28, 16, 7, 7,0,datetime.timezone(datetime.timedelta(seconds=-14400)))
|
||||||
assert p.description() == "Girl holding pumpkin"
|
assert p.description() == "Girl holding pumpkin"
|
||||||
assert p.name() == "I found one!"
|
assert p.name() == "I found one!"
|
||||||
assert p.albums() == ["Pumpkin Farm"]
|
assert p.albums() == ["Pumpkin Farm"]
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ def test_attributes():
|
|||||||
p = photos[0]
|
p = photos[0]
|
||||||
assert p.keywords() == ["Kids"]
|
assert p.keywords() == ["Kids"]
|
||||||
assert p.filename() == "Pumkins2.jpg"
|
assert p.filename() == "Pumkins2.jpg"
|
||||||
assert p.date() == datetime.datetime(2018, 9, 28, 16, 7, 7)
|
assert p.date() == datetime.datetime(2018, 9, 28, 16, 7, 7,0,datetime.timezone(datetime.timedelta(seconds=-14400)))
|
||||||
assert p.description() == "Girl holding pumpkin"
|
assert p.description() == "Girl holding pumpkin"
|
||||||
assert p.name() == "I found one!"
|
assert p.name() == "I found one!"
|
||||||
assert p.albums() == ["Pumpkin Farm"]
|
assert p.albums() == ["Pumpkin Farm"]
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ def test_attributes():
|
|||||||
p = photos[0]
|
p = photos[0]
|
||||||
assert p.keywords() == ["Kids"]
|
assert p.keywords() == ["Kids"]
|
||||||
assert p.filename() == "Pumkins2.jpg"
|
assert p.filename() == "Pumkins2.jpg"
|
||||||
assert p.date() == datetime.datetime(2018, 9, 28, 16, 7, 7)
|
assert p.date() == datetime.datetime(2018, 9, 28, 16, 7, 7,0,datetime.timezone(datetime.timedelta(seconds=-14400)))
|
||||||
assert p.description() == "Girl holding pumpkin"
|
assert p.description() == "Girl holding pumpkin"
|
||||||
assert p.name() == "I found one!"
|
assert p.name() == "I found one!"
|
||||||
assert p.albums() == ["Pumpkin Farm"]
|
assert p.albums() == ["Pumpkin Farm"]
|
||||||
|
|||||||
Reference in New Issue
Block a user