 
    ;; pre-create partitions
    (log/info (trs "Creating partitions based on unique days in resource_events"))
-   (jdbc/call-with-query-rows
-    ["select distinct date_trunc('day', \"timestamp\") as rowdate
-      from resource_events_premigrate"]
-    (fn [rows]
-      (doseq [row rows]
-        (partitioning/create-resource-events-partition (-> (:rowdate row)
-                                                           (.toInstant)
-                                                           (ZonedDateTime/ofInstant (ZoneId/of "UTC"))
-                                                           (.truncatedTo (ChronoUnit/DAYS)))))))
+   ;; PDB-4641 - PostgreSQL returns dates in the client's timezone. What we need
+   ;; to do here is force the connection into UTC. We want the date of the event,
+   ;; in UTC, so that we can create the partition for it. To do this, we have
+   ;; the find_resource_events_unique_dates plpgsql function above. For the duration
+   ;; of this migration transaction, dates will be displayed in UTC.
+   ;; If the timezone is in the local timezone (say, EST, or CEST), you get the date
+   ;; in that timezone with the time cut off. So, 2020-01-30T05:00:00Z, which truncates
+   ;; to 2020-01-30 using the pgsql date functions. In reality, this is actually
+   ;; 2020-01-31 in UTC, which is the date we need for creating the partition successfully.
+   (let [current-timezone (:current_setting (first (jdbc/query-to-vec "SELECT current_setting('TIMEZONE')")))]
+     (jdbc/call-with-query-rows
+       ["select rowdate from find_resource_events_unique_dates()"]
+       (fn [rows]
+         (doseq [row rows]
+           (partitioning/create-resource-events-partition (-> (:rowdate row)
+                                                              (.toLocalDate)
+                                                              (.atStartOfDay (ZoneId/of "UTC")))))))
+     (jdbc/do-commands
+       ;; restore the transaction's timezone setting after creating the partitions
+       (str "SET local timezone to '" current-timezone "'")))
 
   (let [event-count (-> "select count(*) from resource_events_premigrate"
                         jdbc/query-to-vec first :count)


  (jdbc/do-commands
   ;; Indexes are created on the individual partitions, not on the base table
   "DROP TABLE resource_events_premigrate")))

(def migrations
  "The available migrations, as a map from migration version to migration function."

            [puppetlabs.puppetdb.scf.storage :as scf]
            [puppetlabs.puppetdb.scf.partitioning :as partitioning])
  (:import [org.postgresql.util PGobject]
           [java.time LocalDate ZonedDateTime ZoneId OffsetDateTime]
           (java.sql Timestamp)
           (java.time.temporal ChronoUnit)
           (java.time.format DateTimeFormatter)))

(defn init-through-2-3-8
  []
