From e6be0179b7ed408cb621d4261dd2207e30353f1a Mon Sep 17 00:00:00 2001
From: Alexander Graf <mail@agraf.me>
Date: Sun, 7 Jan 2018 14:52:03 +0100
Subject: [PATCH] Support {date_utc} filename_pattern

{date_utc} encodes the post creation date in UTC rather than the
current local timezone, as {date} does.

This was proposed in #69. Encoding the post creation date in
local time zone induces problems regarding --fast-update when the
time zone is changed.
---
 docs/basic-usage.rst |  2 +-
 docs/cli-options.rst |  2 +-
 instaloader.py       | 21 ++++++++++++++++-----
 3 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/docs/basic-usage.rst b/docs/basic-usage.rst
index 94c2bab..6f0ea54 100644
--- a/docs/basic-usage.rst
+++ b/docs/basic-usage.rst
@@ -95,7 +95,7 @@ pattern, the token ``{target}`` is replaced by the target name, and
 :option:`--filename-pattern` configures the path of the post's files relative
 to the target directory. The default is ``--filename-pattern={date}``.
 The tokens ``{target}`` and ``{profile}`` are replaced like in the
-dirname pattern. Further, the tokens ``{date}`` and ``{shortcode}`` are
+dirname pattern. Further, the tokens ``{date}``, ``{date_utc}`` and ``{shortcode}`` are
 defined. Additionally, in case of not downloading stories, the attributes of
 :class:`.Post` can be used, e.g. ``{post.owner_id}`` or ``{post.mediaid}``.
 
diff --git a/docs/cli-options.rst b/docs/cli-options.rst
index c8daaee..15c431d 100644
--- a/docs/cli-options.rst
+++ b/docs/cli-options.rst
@@ -144,7 +144,7 @@ How to Download
    Prefix of filenames. Posts are stored in the directory whose pattern is given
    with ``--dirname-pattern``.  ``{profile}`` is replaced by the profile name,
    ``{target}`` is replaced by the target you specified, i.e.  either ``:feed``,
-   ``#hashtag`` or the profile name.  Also, the fields ``{date}`` and
+   ``#hashtag`` or the profile name.  Also, the fields ``{date}``, ``{date_utc}`` and
    ``{shortcode}`` can be specified.  In case of not downloading stories, the
    attributes of the :class:`.Post` class can be used in addition, e.g.
    ``{post.owner_id}`` or ``{post.mediaid}``.
diff --git a/instaloader.py b/instaloader.py
index fb3cea5..beb7afc 100755
--- a/instaloader.py
+++ b/instaloader.py
@@ -268,9 +268,14 @@ class Post:
 
     @property
     def date(self) -> datetime:
-        """Timestamp when the post was created."""
+        """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"])
 
+    @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"])
+
     @property
     def url(self) -> str:
         """URL of the picture / video thumbnail of the post"""
@@ -430,8 +435,12 @@ class Instaloader:
         self.sleep = sleep
         self.quiet = quiet
         self.dirname_pattern = dirname_pattern if dirname_pattern is not None else '{target}'
-        self.filename_pattern = filename_pattern.replace('{date}', '{date:%Y-%m-%d_%H-%M-%S}') \
-            if filename_pattern is not None else '{date:%Y-%m-%d_%H-%M-%S}'
+        if filename_pattern is not None:
+            self.filename_pattern = filename_pattern \
+                .replace('{date}', '{date:%Y-%m-%d_%H-%M-%S}') \
+                .replace('{date_utc}', '{date_utc:%Y-%m-%d_%H-%M-%S_UTC}')
+        else:
+            self.filename_pattern = '{date:%Y-%m-%d_%H-%M-%S}'
         self.download_videos = download_videos
         self.download_video_thumbnails = download_video_thumbnails
         self.download_geotags = download_geotags
@@ -907,7 +916,8 @@ class Instaloader:
         profilename = post.owner_username if needs_profilename else None
         dirname = self.dirname_pattern.format(profile=profilename, target=target.lower())
         filename = dirname + '/' + self.filename_pattern.format(profile=profilename, target=target.lower(),
-                                                                date=post.date, shortcode=post.shortcode,
+                                                                date=post.date, date_utc=post.date_utc,
+                                                                shortcode=post.shortcode,
                                                                 post=post)
         os.makedirs(os.path.dirname(filename), exist_ok=True)
 
@@ -1048,9 +1058,10 @@ class Instaloader:
 
         shortcode = item["code"] if "code" in item else "no_code"
         date = datetime.fromtimestamp(item["taken_at"])
+        date_utc = datetime.utcfromtimestamp(item["taken_at"])
         dirname = self.dirname_pattern.format(profile=profile, target=target)
         filename = dirname + '/' + self.filename_pattern.format(profile=profile, target=target,
-                                                                date=date,
+                                                                date=date, date_utc=date_utc,
                                                                 shortcode=shortcode)
         os.makedirs(os.path.dirname(filename), exist_ok=True)
         downloaded = False