diff --git a/elodie/media/base.py b/elodie/media/base.py index 83f29c5a..dd2ecf09 100644 --- a/elodie/media/base.py +++ b/elodie/media/base.py @@ -12,6 +12,12 @@ import mimetypes import os +from datetime import datetime, timedelta +from pytz import timezone +from time import mktime +from tzwhere.tzwhere import tzwhere + +from elodie.config import load_config try: # Py3k compatibility basestring @@ -47,12 +53,40 @@ def get_album(self): """ return None - def get_file_path(self): - """Get the full path to the video. + def get_camera_make(self): + return None - :returns: string + def get_camera_model(self): + return None + + def get_date_taken_adjusted(self, date_taken, latitude, longitude): + """Returns date taken and adjust based on time zone if needed. + Time zone conversion is based on a configurable value from config.ini. + + :returns: int """ - return self.source + config = load_config() + + # Check if use_location config is true and file has lat/lon + # Else default to returning date_taken directly from file + if( + 'Timezone' in config and + 'use_location' in config['Timezone'] and + config['Timezone'].getboolean('use_location') is True and + latitude is not None and + longitude is not None + ): + timezone_string = tzwhere().tzNameAt( + latitude, + longitude + ) + date_taken_as_time = datetime.fromtimestamp(mktime(date_taken)) + now_in_timezone = datetime.now(timezone(timezone_string)) + seconds_offset = now_in_timezone.utcoffset().total_seconds() + adjusted_date_taken = date_taken_as_time - timedelta(seconds = seconds_offset) + return adjusted_date_taken.timetuple() + + return date_taken def get_coordinate(self, type): return None @@ -68,11 +102,12 @@ def get_extension(self): source = self.source return os.path.splitext(source)[1][1:].lower() - def get_camera_make(self): - return None + def get_file_path(self): + """Get the full path to the video. - def get_camera_model(self): - return None + :returns: string + """ + return self.source def get_metadata(self, update_cache=False): """Get a dictionary of metadata for any file. @@ -103,7 +138,11 @@ def get_metadata(self, update_cache=False): 'extension': self.get_extension(), 'directory_path': os.path.dirname(source) } - + self.metadata['date_taken_adjusted'] = self.get_date_taken_adjusted( + self.metadata['date_taken'], + self.metadata['latitude'], + self.metadata['longitude'] + ) return self.metadata def get_mimetype(self): diff --git a/elodie/tests/config_test.py b/elodie/tests/config_test.py index ee073f73..23919d28 100644 --- a/elodie/tests/config_test.py +++ b/elodie/tests/config_test.py @@ -10,12 +10,12 @@ sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))) from elodie import constants -from elodie.config import load_config BASE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) @patch('elodie.config.config_file', '%s/config.ini-sample' % BASE_PATH) def test_load_config_singleton_success(): + from elodie.config import load_config config = load_config() assert config['MapQuest']['key'] == 'your-api-key-goes-here', config.get('MapQuest', 'key') config.set('MapQuest', 'key', 'new-value') @@ -27,5 +27,6 @@ def test_load_config_singleton_success(): @patch('elodie.config.config_file', '%s/config.ini-does-not-exist' % BASE_PATH) def test_load_config_singleton_no_file(): + from elodie.config import load_config config = load_config() assert config == {}, config diff --git a/elodie/tests/media/photo_test.py b/elodie/tests/media/photo_test.py index d2141895..bb15b547 100644 --- a/elodie/tests/media/photo_test.py +++ b/elodie/tests/media/photo_test.py @@ -1,15 +1,16 @@ # -*- coding: utf-8 # Project imports from __future__ import unicode_literals +import mock import os import sys from datetime import datetime import shutil -import tempfile import time from nose.plugins.skip import SkipTest +from tempfile import gettempdir sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))) sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) @@ -57,6 +58,89 @@ def test_is_not_valid(): assert not photo.is_valid() +@mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-no-config' % gettempdir()) +def test_get_date_taken_adjusted_no_config(): + from elodie.config import load_config + with open('%s/config.ini-date-taken-adjusted-no-config' % gettempdir(), 'w') as f: + f.write(""" + """) + + if hasattr(load_config, 'config'): + del load_config.config + + photo = Photo(helper.get_file('plain.jpg')) + metadata = photo.get_metadata() + date_taken_adj = photo.get_date_taken_adjusted(metadata['date_taken'], metadata['latitude'], metadata['longitude']) + + if hasattr(load_config, 'config'): + del load_config.config + +@mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-do-not-use-location' % gettempdir()) +def test_get_date_taken_adjusted_do_not_use_location(): + from elodie.config import load_config + with open('%s/config.ini-date-taken-adjusted-do-not-use-location' % gettempdir(), 'w') as f: + f.write(""" +[Timezone] +use_location=False + """) + + if hasattr(load_config, 'config'): + del load_config.config + + photo = Photo(helper.get_file('plain.jpg')) + metadata = photo.get_metadata() + date_taken_adj = photo.get_date_taken_adjusted(metadata['date_taken'], metadata['latitude'], metadata['longitude']) + + if hasattr(load_config, 'config'): + del load_config.config + + assert date_taken_adj == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken_adj + +@mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-without-exif-location' % gettempdir()) +def test_get_date_taken_adjusted_without_exif_location(): + from elodie.config import load_config + with open('%s/config.ini-date-taken-adjusted-without-exif-location' % gettempdir(), 'w') as f: + f.write(""" +[Timezone] +use_location=True + """) + + if hasattr(load_config, 'config'): + del load_config.config + + photo = Photo(helper.get_file('plain.jpg')) + metadata = photo.get_metadata() + date_taken_adj = photo.get_date_taken_adjusted(metadata['date_taken'], metadata['latitude'], metadata['longitude']) + + if hasattr(load_config, 'config'): + del load_config.config + + assert date_taken_adj == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken_adj + +@mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-for-timestamp-use-location' % gettempdir()) +def test_get_date_taken_adjusted_for_timestamp_use_location(): + from elodie.config import load_config + with open('%s/config.ini-date-taken-adjusted-for-timestamp-use-location' % gettempdir(), 'w') as f: + f.write(""" +[Timezone] +use_location=True + """) + + if hasattr(load_config, 'config'): + del load_config.config + + photo = Photo(helper.get_file('with-location.jpg')) + metadata = photo.get_metadata() + date_taken_adj = photo.get_date_taken_adjusted(metadata['date_taken'], metadata['latitude'], metadata['longitude']) + date_taken_adj_from_metadata = photo.get_metadata()['date_taken_adjusted'] + is_dst = date_taken_adj.tm_isdst + + if hasattr(load_config, 'config'): + del load_config.config + + assert date_taken_adj == date_taken_adj_from_metadata, (date_taken_adj, date_taken_adj_from_metadata) + assert date_taken_adj == helper.time_convert((2015, 12, 5, 7, 59, 26, 5, 339, is_dst)), date_taken_adj + def test_get_metadata_of_invalid_photo(): photo = Photo(helper.get_file('invalid.jpg')) metadata = photo.get_metadata() diff --git a/requirements.txt b/requirements.txt index 2c8fccbd..45537143 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,6 @@ Send2Trash==1.3.0 future==0.16.0 configparser==3.5.0 tabulate==0.7.7 +pytz==2019.1 +tzwhere==3.0.3 +numpy==1.16.3