Index: tests/phpunit/tests/date/postTime.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- tests/phpunit/tests/date/postTime.php	(date 1567091322984)
+++ tests/phpunit/tests/date/postTime.php	(date 1567091322984)
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @group date
+ * @group datetime
+ */
+class Tests_Date_Post_Time extends WP_UnitTestCase {
+
+	public function test_should_return_wp_timestamp() {
+
+		$timezone = 'Europe/Kiev';
+		update_option( 'timezone_string', $timezone );
+		$datetime     = new DateTimeImmutable( 'now', new DateTimeZone( $timezone ) );
+		$mysql        = $datetime->format( 'Y-m-d H:i:s' );
+		$timestamp    = $datetime->getTimestamp();
+		$wp_timestamp = $datetime->getTimestamp() + $datetime->getOffset();
+
+		$post_id = self::factory()->post->create( array(
+			'post_date'     => $mysql,
+			'post_modified' => $mysql,
+		) );
+
+		$this->assertEquals( $wp_timestamp, get_post_time( 'U', false, $post_id ) );
+		$this->assertEquals( $wp_timestamp, get_post_time( 'G', false, $post_id ) );
+		$this->assertEquals( $timestamp, get_post_time( 'U', true, $post_id ) );
+		$this->assertEquals( $timestamp, get_post_time( 'G', true, $post_id ) );
+		$this->assertEquals( $wp_timestamp, get_post_modified_time( 'U', false, $post_id ) );
+		$this->assertEquals( $wp_timestamp, get_post_modified_time( 'G', false, $post_id ) );
+		$this->assertEquals( $timestamp, get_post_modified_time( 'U', true, $post_id ) );
+		$this->assertEquals( $timestamp, get_post_modified_time( 'G', true, $post_id ) );
+	}
+
+	public function test_should_return_time() {
+
+		$timezone = 'Europe/Kiev';
+		update_option( 'timezone_string', $timezone );
+		$datetime    = new DateTimeImmutable( 'now', new DateTimeZone( $timezone ) );
+		$mysql       = $datetime->format( 'Y-m-d H:i:s' );
+		$rfc3339     = $datetime->format( DATE_RFC3339 );
+		$rfc3339_utc = $datetime->setTimezone( new DateTimeZone( 'UTC' ) )->format( DATE_RFC3339 );
+		$post_id     = self::factory()->post->create( array(
+			'post_date'     => $mysql,
+			'post_modified' => $mysql,
+		) );
+
+		$this->assertEquals( $rfc3339, get_post_time( DATE_RFC3339, false, $post_id ) );
+		$this->assertEquals( $rfc3339_utc, get_post_time( DATE_RFC3339, true, $post_id ) );
+		$this->assertEquals( $rfc3339, get_post_time( DATE_RFC3339, false, $post_id, true ) );
+		$this->assertEquals( $rfc3339_utc, get_post_time( DATE_RFC3339, true, $post_id, true ) );
+		$this->assertEquals( $rfc3339, get_post_modified_time( DATE_RFC3339, false, $post_id ) );
+		$this->assertEquals( $rfc3339_utc, get_post_modified_time( DATE_RFC3339, true, $post_id ) );
+		$this->assertEquals( $rfc3339, get_post_modified_time( DATE_RFC3339, false, $post_id, true ) );
+		$this->assertEquals( $rfc3339_utc, get_post_modified_time( DATE_RFC3339, true, $post_id, true ) );
+	}
+}
Index: src/wp-includes/general-template.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/wp-includes/general-template.php	(date 1567065163000)
+++ src/wp-includes/general-template.php	(date 1567088990809)
@@ -2562,13 +2562,28 @@
 		return false;
 	}
 
-	if ( $gmt ) {
-		$time = $post->post_date_gmt;
-	} else {
-		$time = $post->post_date;
+	$datetime = get_post_datetime( $post );
+
+	if ( false === $datetime ) {
+		return false;
+	}
+
+	if ( 'U' === $d || 'G' === $d ) {
+
+		$time = $datetime->getTimestamp();
+
+		// Returns a sum of timestamp with timezone offset. Ideally should never be used.
+		if ( ! $gmt ) {
+			$time += $datetime->getOffset();
+		}
+	} elseif ( $translate ) {
+		$time = wp_date( $d, $datetime->getTimestamp(), $gmt ? new DateTimeZone( 'UTC' ) : null );
+	} else {
+		if ( $gmt ) {
+			$datetime = $datetime->setTimezone( new DateTimeZone( 'UTC' ) );
+		}
+		$time = $datetime->format( $d );
 	}
-
-	$time = mysql2date( $d, $time, $translate );
 
 	/**
 	 * Filters the localized time a post was written.
@@ -2583,6 +2598,54 @@
 	return apply_filters( 'get_post_time', $time, $d, $gmt );
 }
 
+/**
+ * Retrieve post published or modified time as `DateTimeImmutable` object instance.
+ *
+ * Object will be set to timezone from WordPress settings.
+ *
+ * @param WP_Post|array|int $post  Optional. WordPress post instance or ID. Defaults to the global `$post`.
+ * @param string            $field Optional. Post field to use. Can be `date` or `modified`.
+ *
+ * @return DateTimeImmutable|false Time object. False on failure.
+ */
+function get_post_datetime( $post = null, $field = 'date' ) {
+
+	$post = get_post( $post );
+
+	if ( ! $post ) {
+		return false;
+	}
+
+	$time = ( 'modified' === $field ) ? $post->post_modified : $post->post_date;
+
+	if ( empty( $time ) || '0000-00-00 00:00:00' === $time ) {
+		return false;
+	}
+
+	return date_create_immutable_from_format( 'Y-m-d H:i:s', $time, wp_timezone() );
+}
+
+/**
+ * Retrieve post published or modified time as Unix timestamp.
+ *
+ * Note that this function returns true Unix timestamp, not summed with time zone offset like older WP functions.
+ *
+ * @param WP_Post|array|int $post  Optional. WordPress post instance or ID. Defaults to the global `$post`.
+ * @param string            $field Optional. Post field to use. Can be `date` or `modified`.
+ *
+ * @return int|false Unix timestamp. False on failure.
+ */
+function get_post_timestamp( $post = null, $field = 'date' ) {
+
+	$datetime = get_post_datetime( $post, $field );
+
+	if ( false === $datetime ) {
+		return false;
+	}
+
+	return $datetime->getTimestamp();
+}
+
 /**
  * Display the time at which the post was last modified.
  *
@@ -2662,13 +2725,28 @@
 		return false;
 	}
 
-	if ( $gmt ) {
-		$time = $post->post_modified_gmt;
+	$datetime = get_post_datetime( $post, 'modified' );
+
+	if ( false === $datetime ) {
+		return false;
+	}
+
+	if ( 'U' === $d || 'G' === $d ) {
+
+		$time = $datetime->getTimestamp();
+
+		// Returns a sum of timestamp with timezone offset. Ideally should never be used.
+		if ( ! $gmt ) {
+			$time += $datetime->getOffset();
+		}
+	} elseif ( $translate ) {
+		$time = wp_date( $d, $datetime->getTimestamp(), $gmt ? new DateTimeZone( 'UTC' ) : null );
 	} else {
-		$time = $post->post_modified;
+		if ( $gmt ) {
+			$datetime = $datetime->setTimezone( new DateTimeZone( 'UTC' ) );
+		}
+		$time = $datetime->format( $d );
 	}
-
-	$time = mysql2date( $d, $time, $translate );
 
 	/**
 	 * Filters the localized time a post was last modified.
