From 2d4f3b8537cfcb33015ec2e3db8ee8114869f745 Mon Sep 17 00:00:00 2001 From: Alexander Graf <17130992+aandergr@users.noreply.github.com> Date: Sat, 15 Jan 2022 17:29:28 +0100 Subject: [PATCH] Make {Post,StoryItem}.date_local timezone aware This commit is made up of 21365ec6688b55c91803040693c3b67cc8820cb8 555c86633c61b106c5c3201e1d5f030a04a4f801 d864ce08ff43a2d86ac6123459bb9fa32b924657 Discussed in #1305, #1316, #1372. Co-Authored-By: Misael Co-Authored-By: Eduardo Kalinowski --- instaloader/instaloader.py | 14 +++++++------- instaloader/structures.py | 26 +++++++++++++++++--------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/instaloader/instaloader.py b/instaloader/instaloader.py index af5814d..105586f 100644 --- a/instaloader/instaloader.py +++ b/instaloader/instaloader.py @@ -816,7 +816,7 @@ class Instaloader: last_scraped = latest_stamps.get_last_story_timestamp(name) scraped_timestamp = datetime.now().astimezone() for item in user_story.get_items(): - if latest_stamps is not None and item.date_utc.replace(tzinfo=timezone.utc) <= last_scraped: + if latest_stamps is not None and item.date_local <= last_scraped: break if storyitem_filter is not None and not storyitem_filter(item): self.context.log("<{} skipped>".format(item), flush=True) @@ -1205,7 +1205,7 @@ class Instaloader: posts_takewhile: Optional[Callable[[Post], bool]] = None if latest_stamps is not None: last_scraped = latest_stamps.get_last_tagged_timestamp(profile.username) - posts_takewhile = lambda p: p.date_utc.replace(tzinfo=timezone.utc) > last_scraped + posts_takewhile = lambda p: p.date_local > last_scraped tagged_posts = profile.get_tagged_posts() self.posts_download_loop(tagged_posts, target if target @@ -1213,7 +1213,7 @@ class Instaloader: _PostPathFormatter.sanitize_path(':tagged')), fast_update, post_filter, takewhile=posts_takewhile) if latest_stamps is not None and tagged_posts.first_item is not None: - latest_stamps.set_last_tagged_timestamp(profile.username, tagged_posts.first_item.date_local.astimezone()) + latest_stamps.set_last_tagged_timestamp(profile.username, tagged_posts.first_item.date_local) def download_igtv(self, profile: Profile, fast_update: bool = False, post_filter: Optional[Callable[[Post], bool]] = None, @@ -1228,12 +1228,12 @@ class Instaloader: posts_takewhile: Optional[Callable[[Post], bool]] = None if latest_stamps is not None: last_scraped = latest_stamps.get_last_igtv_timestamp(profile.username) - posts_takewhile = lambda p: p.date_utc.replace(tzinfo=timezone.utc) > last_scraped + posts_takewhile = lambda p: p.date_local > last_scraped igtv_posts = profile.get_igtv_posts() self.posts_download_loop(igtv_posts, profile.username, fast_update, post_filter, total_count=profile.igtvcount, owner_profile=profile, takewhile=posts_takewhile) if latest_stamps is not None and igtv_posts.first_item is not None: - latest_stamps.set_last_igtv_timestamp(profile.username, igtv_posts.first_item.date_local.astimezone()) + latest_stamps.set_last_igtv_timestamp(profile.username, igtv_posts.first_item.date_local) def _get_id_filename(self, profile_name: str) -> str: if ((format_string_contains_key(self.dirname_pattern, 'profile') or @@ -1426,14 +1426,14 @@ class Instaloader: if latest_stamps is not None: # pylint:disable=cell-var-from-loop last_scraped = latest_stamps.get_last_post_timestamp(profile_name) - posts_takewhile = lambda p: p.date_utc.replace(tzinfo=timezone.utc) > last_scraped + posts_takewhile = lambda p: p.date_local > last_scraped posts_to_download = profile.get_posts() self.posts_download_loop(posts_to_download, profile_name, fast_update, post_filter, total_count=profile.mediacount, owner_profile=profile, takewhile=posts_takewhile) if latest_stamps is not None and posts_to_download.first_item is not None: latest_stamps.set_last_post_timestamp(profile_name, - posts_to_download.first_item.date_local.astimezone()) + posts_to_download.first_item.date_local) if stories and profiles: with self.context.error_catcher("Download stories"): diff --git a/instaloader/structures.py b/instaloader/structures.py index d244e55..c4c51c3 100644 --- a/instaloader/structures.py +++ b/instaloader/structures.py @@ -262,17 +262,16 @@ class Post: @property def date_local(self) -> datetime: - """Timestamp when the post was created (local time zone).""" - return datetime.fromtimestamp(self._node["date"] - if "date" in self._node - else self._node["taken_at_timestamp"]) + """Timestamp when the post was created (local time zone). + + .. versionchanged:: 4.9 + Return timezone aware datetime object.""" + return datetime.fromtimestamp(self._get_timestamp_date_created()).astimezone() @property def date_utc(self) -> datetime: """Timestamp when the post was created (UTC).""" - return datetime.utcfromtimestamp(self._node["date"] - if "date" in self._node - else self._node["taken_at_timestamp"]) + return datetime.utcfromtimestamp(self._get_timestamp_date_created()) @property def date(self) -> datetime: @@ -313,6 +312,12 @@ class Post: return len(edges) return 1 + def _get_timestamp_date_created(self) -> float: + """Timestamp when the post was created""" + return (self._node["date"] + if "date" in self._node + else self._node["taken_at_timestamp"]) + def get_is_videos(self) -> List[bool]: """ Return a list containing the ``is_video`` property for each media in the post. @@ -1140,8 +1145,11 @@ class StoryItem: @property def date_local(self) -> datetime: - """Timestamp when the StoryItem was created (local time zone).""" - return datetime.fromtimestamp(self._node['taken_at_timestamp']) + """Timestamp when the StoryItem was created (local time zone). + + .. versionchanged:: 4.9 + Return timezone aware datetime object.""" + return datetime.fromtimestamp(self._node['taken_at_timestamp']).astimezone() @property def date_utc(self) -> datetime: