diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
index 02314e88e869401bd4e295a0b0ad888bb074a804..4c221e1ce91319983fcf457baccb384e3a7c0345 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
@@ -164,23 +164,35 @@ protected function createForumTopics($count = 5) {
       // Generate a random subject/body.
       $title = $this->randomName(20);
       $body = $this->randomName(200);
-      // Forum posts are ordered by timestamp, so force a unique timestamp by
-      // changing the date.
-      $date->modify('+1 minute');
 
       $langcode = LANGUAGE_NOT_SPECIFIED;
       $edit = array(
         'title' => $title,
         "body[$langcode][0][value]" => $body,
-        // Forum posts are ordered by timestamp, so force a unique timestamp by
-        // adding the index.
-        'date[date]' => $date->format('Y-m-d'),
-        'date[time]' => $date->format('H:i:s'),
       );
 
       // Create the forum topic, preselecting the forum ID via a URL parameter.
       $this->drupalPost('node/add/forum/1', $edit, t('Save and publish'));
       $topics[] = $title;
+
+      // Get the node from the topic title.
+      $node = $this->drupalGetNodeByTitle($title);
+      // Forum posts are ordered by the created timestamp, so force a unique
+      // timestamp by changing the date.
+      $timestamp = $date->modify('+1 minute')->getTimestamp();
+      db_update('node')
+        ->fields( array(
+          'created' => $timestamp,
+        ))
+        ->condition('nid', $node->nid)
+        ->execute();
+      db_update('forum_index')
+        ->fields( array(
+          'created' => $timestamp,
+          'last_comment_timestamp' => $timestamp,
+        ))
+        ->condition('nid', $node->nid)
+        ->execute();
     }
 
     return $topics;
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 63b41892917d1ec9fa9ea88605692be7c2aea3d9..f9db33d5a5bf36bba9ad890fc8986e1b06862568 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -41,7 +41,6 @@ protected function prepareEntity(EntityInterface $node) {
       $node->created = REQUEST_TIME;
     }
     else {
-      $node->date = new DrupalDateTime($node->created);
       // Remove the log message from the original node entity.
       $node->log = NULL;
     }
@@ -186,11 +185,11 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
       '#description' => t('Leave blank for %anonymous.', array('%anonymous' => $user_config->get('anonymous'))),
     );
     $format = variable_get('date_format_html_date', 'Y-m-d') . ' ' . variable_get('date_format_html_time', 'H:i:s');
-    $form['author']['date'] = array(
+    $form['author']['published_date'] = array(
       '#type' => 'datetime',
-      '#title' => t('Authored on'),
-      '#description' => t('Format: %format. Leave blank to use the time of form submission.', array('%format' => datetime_format_example($format))),
-      '#default_value' => !empty($node->date) ? $node->date : '',
+      '#title' => t('First published on'),
+      '#description' => t('Format: %format.  Leave blank to use the time of form submission when published.', array('%format' => datetime_format_example($format))),
+      '#default_value' => empty($node->published) ? '' : new DrupalDateTime($node->published),
     );
 
     // Node options for administrators.
@@ -329,10 +328,10 @@ public function validate(array $form, array &$form_state) {
       form_set_error('name', t('The username %name does not exist.', array('%name' => $node->name)));
     }
 
-    // Validate the "authored on" field.
-    // The date element contains the date object.
-    if ($node->date instanceOf DrupalDateTime && $node->date->hasErrors()) {
-      form_set_error('date', t('You have to specify a valid date.'));
+    // Validate the "first published on" field.
+    // The published_date element contains the date object.
+    if (!empty($node->published_date) && $node->published_date instanceOf DrupalDateTime && $node->published_date->hasErrors()) {
+      form_set_error('published_date', t('You have to specify a valid publication date.'));
     }
 
     // Invoke hook_validate() for node type specific validation and
diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php
index d855384e95a821682ff64e63e5bf5a926ed66920..d2fe03363af1e2be31c017684618eb696aced2ef 100644
--- a/core/modules/node/lib/Drupal/node/NodeStorageController.php
+++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php
@@ -93,8 +93,14 @@ protected function invokeHook($hook, EntityInterface $node) {
    * Overrides Drupal\Core\Entity\DatabaseStorageController::preSave().
    */
   protected function preSave(EntityInterface $node) {
-    // Before saving the node, set changed and revision times.
+    // Before saving the node, set created and changed times.
+    $node->created = empty($node->created) ? REQUEST_TIME : $node->created;
     $node->changed = REQUEST_TIME;
+
+    // If this is being published for the first time, set the published time.
+    if ($node->status == NODE_PUBLISHED && empty($node->published)) {
+      $node->published = REQUEST_TIME;
+    }
   }
 
   /**
diff --git a/core/modules/node/lib/Drupal/node/NodeTranslationController.php b/core/modules/node/lib/Drupal/node/NodeTranslationController.php
index a9e6b7cf5025bb7e071c6c94357440b35ceb1bc0..de33b2597e8dbb0653deb6e2a812f267ef375533 100644
--- a/core/modules/node/lib/Drupal/node/NodeTranslationController.php
+++ b/core/modules/node/lib/Drupal/node/NodeTranslationController.php
@@ -63,7 +63,8 @@ public function entityFormEntityBuild($entity_type, EntityInterface $entity, arr
       $translation = &$form_state['values']['translation_entity'];
       $translation['status'] = $form_controller->getEntity($form_state)->status;
       $translation['name'] = $form_state['values']['name'];
-      $translation['created'] = $form_state['values']['date'];
+      $translation['created'] = $form_state['values']['created'];
+      $translation['published'] = $form_state['values']['published_date'];
     }
     parent::entityFormEntityBuild($entity_type, $entity, $form, $form_state);
   }
diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
index a4cf26428c2025a34ec1e0d00fd8c705ac321981..4ba763ce5482a97610ff9c66594bcf8f4fed72bb 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
@@ -129,6 +129,13 @@ class Node extends Entity implements ContentEntityInterface {
   public $changed;
 
   /**
+   * The node publication timestamp.
+   *
+   * @var integer
+   */
+  public $published;
+
+  /**
    * The node comment status indicator.
    *
    * COMMENT_NODE_HIDDEN => no comments
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeSaveTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeSaveTest.php
index f86bc522c1ad694d8b094d417010b7b26e26a82b..f6f488071cea0b100df45f14bea1af0e5d12fed4 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeSaveTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeSaveTest.php
@@ -72,7 +72,7 @@ function testImport() {
   }
 
   /**
-   * Verifies accuracy of the "created" and "changed" timestamp functionality.
+   * Verifies the "created", "changed" and "published" timestamp functionality.
    */
   function testTimestamps() {
     // Use the default timestamps.
@@ -80,20 +80,24 @@ function testTimestamps() {
       'uid' => $this->web_user->uid,
       'type' => 'article',
       'title' => $this->randomName(8),
+      'status' => NODE_PUBLISHED,
     );
 
     entity_create('node', $edit)->save();
     $node = $this->drupalGetNodeByTitle($edit['title']);
     $this->assertEqual($node->created, REQUEST_TIME, 'Creating a node sets default "created" timestamp.');
     $this->assertEqual($node->changed, REQUEST_TIME, 'Creating a node sets default "changed" timestamp.');
+    $this->assertEqual($node->published, REQUEST_TIME, 'Creating a published node sets default "published" timestamp.');
 
     // Store the timestamps.
     $created = $node->created;
     $changed = $node->changed;
+    $published = $node->published;
 
     $node->save();
     $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
     $this->assertEqual($node->created, $created, 'Updating a node preserves "created" timestamp.');
+    $this->assertEqual($node->published, $published, 'Updating a node preserves "published" timestamp.');
 
     // Programmatically set the timestamps using hook_node_presave.
     $node->title = 'testing_node_presave';
@@ -102,29 +106,75 @@ function testTimestamps() {
     $node = $this->drupalGetNodeByTitle('testing_node_presave', TRUE);
     $this->assertEqual($node->created, 280299600, 'Saving a node uses "created" timestamp set in presave hook.');
     $this->assertEqual($node->changed, 979534800, 'Saving a node uses "changed" timestamp set in presave hook.');
+    $this->assertEqual($node->published, 946684800, 'Saving a node uses "published" timestamp set in presave hook.');
 
     // Programmatically set the timestamps on the node.
     $edit = array(
       'uid' => $this->web_user->uid,
       'type' => 'article',
       'title' => $this->randomName(8),
+      'status' => NODE_PUBLISHED,
       'created' => 280299600, // Sun, 19 Nov 1978 05:00:00 GMT
       'changed' => 979534800, // Drupal 1.0 release.
+      'published' => 946684800, // Sat, 1 Jan 2000 00:00:00 GMT
     );
 
     entity_create('node', $edit)->save();
     $node = $this->drupalGetNodeByTitle($edit['title']);
     $this->assertEqual($node->created, 280299600, 'Creating a node uses user-set "created" timestamp.');
     $this->assertNotEqual($node->changed, 979534800, 'Creating a node does not use user-set "changed" timestamp.');
+    $this->assertEqual($node->published, 946684800, 'Creating a node uses user-set "published" timestamp.');
 
     // Update the timestamps.
     $node->created = 979534800;
-    $node->changed = 280299600;
+    $node->changed = 946684800;
+    $node->published = 280299600;
 
     $node->save();
     $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
     $this->assertEqual($node->created, 979534800, 'Updating a node uses user-set "created" timestamp.');
-    $this->assertNotEqual($node->changed, 280299600, 'Updating a node does not use user-set "changed" timestamp.');
+    $this->assertNotEqual($node->changed, 946684800, 'Updating a node does not use user-set "changed" timestamp.');
+    $this->assertEqual($node->published, 280299600, 'Updating a node uses user-set "published" timestamp.');
+
+    // Save an unpublished node.
+    $edit = array(
+      'uid' => $this->web_user->uid,
+      'type' => 'article',
+      'title' => $this->randomName(8),
+      'status' => NODE_NOT_PUBLISHED,
+    );
+
+    entity_create('node', $edit)->save();
+    $node = $this->drupalGetNodeByTitle($edit['title']);
+    $this->assertFalse($node->published, 'Creating an unpublished node does not set "published" timestamp.');
+
+    $node->save();
+    $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
+    $this->assertFalse($node->published, 'Updating an unpublished node does not set "published" timestamp.');
+
+    // Publish the node.
+    $node->status = NODE_PUBLISHED;
+
+    $node->save();
+    $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
+    $this->assertEqual($node->published, REQUEST_TIME, 'Publishing a node sets default "published" timestamp.');
+
+    // Store "published" timestamp.
+    $published = $node->published;
+
+    // Unpublish the node.
+    $node->status = NODE_NOT_PUBLISHED;
+
+    $node->save();
+    $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
+    $this->assertEqual($node->published, $published, 'Unpublishing a node preserves "published" timestamp.');
+
+    // Publish the node again.
+    $node->status = NODE_PUBLISHED;
+
+    $node->save();
+    $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
+    $this->assertEqual($node->published, $published, 'Re-publishing a node preserves "published" timestamp.');
   }
 
   /**
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
index 8a744ecaa128a49fc7416d0651fe3ac66cc9be9a..5a90a21da2d6ee513f6db161655e635b07956784 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
@@ -117,12 +117,12 @@ protected function assertAuthoringInfo() {
       $user = $this->drupalCreateUser();
       $values[$langcode] = array(
         'uid' => $user->uid,
-        'created' => REQUEST_TIME - mt_rand(0, 1000),
+        'published' => REQUEST_TIME - mt_rand(0, 1000),
       );
       $edit = array(
         'name' => $user->name,
-        'date[date]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d'),
-        'date[time]' => format_date($values[$langcode]['created'], 'custom', 'H:i:s'),
+        'published_date[date]' => format_date($values[$langcode]['published'], 'custom', 'Y-m-d'),
+        'published_date[time]' => format_date($values[$langcode]['published'], 'custom', 'H:i:s'),
       );
       $this->drupalPost($path, $edit, $this->getFormSubmitAction(), array('language' => $languages[$langcode]));
     }
@@ -130,7 +130,7 @@ protected function assertAuthoringInfo() {
     $entity = entity_load($this->entityType, $this->entityId, TRUE);
     foreach ($this->langcodes as $langcode) {
       $this->assertEqual($entity->translation[$langcode]['uid'] == $values[$langcode]['uid'], 'Translation author correctly stored.');
-      $this->assertEqual($entity->translation[$langcode]['created'] == $values[$langcode]['created'], 'Translation date correctly stored.');
+      $this->assertEqual($entity->translation[$langcode]['published'] == $values[$langcode]['published'], 'Translation date correctly stored.');
     }
   }
 
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index 0e755b566391677cfc4ee0605a5fae8c56bfa19f..d12b571ee70233c24960b01e949003940fad8c97 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -79,6 +79,12 @@ function node_schema() {
         'not null' => TRUE,
         'default' => 0,
       ),
+      'published' => array(
+        'description' => 'The Unix timestamp when the node was first published.',
+        'type' => 'int',
+        'not null' => FALSE,
+        'default' => NULL,
+      ),
       'comment' => array(
         'description' => 'Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write).',
         'type' => 'int',
@@ -114,6 +120,7 @@ function node_schema() {
     'indexes' => array(
       'node_changed'        => array('changed'),
       'node_created'        => array('created'),
+      'node_published'      => array('published'),
       'node_frontpage'      => array('promote', 'status', 'sticky', 'created'),
       'node_status_type'    => array('status', 'type', 'nid'),
       'node_title_type'     => array('title', array('type', 4)),
@@ -714,6 +721,97 @@ function node_update_8014() {
 }
 
 /**
+ * Create a published column for nodes.
+ */
+function node_update_8015(&$sandbox) {
+  // This is a multi-pass update. On the first call we need to update the
+  // database schema and initialize some variables.
+  if (!isset($sandbox['total'])) {
+    // Add a published column to the node table.
+    $spec = array(
+      'description' => 'The Unix timestamp when the node was first published.',
+      'type' => 'int',
+      'not null' => FALSE,
+      'default' => NULL,
+    );
+    $keys = array(
+      'indexes' => array(
+        'node_published' => array('published'),
+      ),
+    );
+    db_add_field('node', 'published', $spec, $keys);
+
+    // Create a table to store temporary data for this update.
+    db_create_table('node_update_8015', array(
+      'description' => 'Stores temporary data for node_update_8015.',
+      'fields' => array(
+        'nid' => array(
+          'type' => 'int',
+          'unsigned' => TRUE,
+          'not null' => TRUE,
+        ),
+        'timestamp' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'created' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'primary key' => array('nid'),
+    ));
+
+    // Get the nid and timestamp of the first revision with a status of 1 for
+    // each node that has one, along with the created date for that node. Store
+    // this data in the temporary table.
+    $query = db_select('node_revision', 'r');
+    $query->leftJoin('node', 'n', 'r.nid = n.nid');
+    $query
+      ->fields('r', array('nid', 'timestamp'))
+      ->fields('n', array('created'))
+      ->condition('r.status', 1)
+      ->groupBy('r.nid');
+    db_insert('node_update_8015')
+      ->from($query)
+      ->execute();
+
+    // Initialize update variables.
+    $sandbox['last'] = 0;
+    $sandbox['count'] = 0;
+    $sandbox['total'] = db_query('SELECT COUNT(*) FROM {node_update_8015}')->fetchField();
+  }
+  else {
+    // We do each pass in batches of 1000.
+    $batch = 1000;
+
+    $result = db_query_range('SELECT * FROM {node_update_8015}', $sandbox['last'], $batch)->fetchAllAssoc('nid');
+    foreach ($result as $nid => $record) {
+      $sandbox['count'] += 1;
+      // See if the node has multiple revisions. If it does, use the revision
+      // timestamp. If not then use the node created date.
+      $revisions = db_query('SELECT COUNT(*) FROM {node_revision} WHERE nid = :nid', array(':nid' => $nid))->fetchField();
+      $published = ($revisions > 1) ? $record->timestamp : $record->created;
+      db_update('node')
+        ->condition('nid', $nid)
+        ->fields(array('published' => $published))
+        ->execute();
+    }
+    $sandbox['last'] += $batch;
+  }
+
+  if ($sandbox['count'] < $sandbox['total']) {
+    $sandbox['#finished'] = FALSE;
+  }
+  else {
+    db_drop_table('node_update_8015');
+    $sandbox['#finished'] = TRUE;
+  }
+}
+
+/**
  * @} End of "addtogroup updates-7.x-to-8.x"
  * The next series of updates should start at 9000.
  */
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index ad79f6d392e10533b0678c70b3a4bb9dcbc54668..f2bd8ba65d63e5276d58678d96c1dce1e3236fc4 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -982,7 +982,7 @@ function node_revision_load($vid = NULL) {
 }
 
 /**
- * Prepares a node for saving by populating the author and creation date.
+ * Prepares a node for saving by populating the author and published date.
  *
  * @param Drupal\node\Node $node
  *   A node object.
@@ -1009,7 +1009,7 @@ function node_submit(Node $node) {
     $node->revision_uid = $user->uid;
   }
 
-  $node->created = !empty($node->date) && $node->date instanceOf DrupalDateTime ? $node->date->getTimestamp() : REQUEST_TIME;
+  $node->published = !empty($node->published_date) && $node->published_date instanceOf DrupalDateTime ? $node->published_date->getTimestamp() : NULL;
   $node->validated = TRUE;
 
   return $node;
@@ -1144,7 +1144,7 @@ function template_preprocess_node(&$variables) {
   $variables['node'] = $variables['elements']['#node'];
   $node = $variables['node'];
 
-  $variables['date']      = format_date($node->created);
+  $variables['date']      = (!empty($node->published)) ? format_date($node->published) : format_date($node->created);
   $variables['name']      = theme('username', array(
     'account' => $node,
     'link_attributes' => array('rel' => 'author'),
@@ -1159,7 +1159,7 @@ function template_preprocess_node(&$variables) {
   // @todo: The comment properties only exist if comment.module is enabled, but
   //   are documented in node.tpl.php, so we make sure that they are set.
   //   Consider removing them.
-  $properties = array('type', 'comment_count', 'uid', 'created', 'promote', 'sticky', 'status', 'comment');
+  $properties = array('type', 'comment_count', 'uid', 'created', 'published', 'promote', 'sticky', 'status', 'comment');
   foreach ($properties as $property) {
     $variables[$property] = isset($node->$property) ? $node->$property : NULL;
   }
@@ -2200,11 +2200,11 @@ function node_view_multiple($nodes, $view_mode = 'teaser', $langcode = NULL) {
 function node_page_default() {
   $site_config = config('system.site');
   $select = db_select('node', 'n')
-    ->fields('n', array('nid', 'sticky', 'created'))
+    ->fields('n', array('nid', 'sticky', 'published'))
     ->condition('n.promote', 1)
     ->condition('n.status', 1)
     ->orderBy('n.sticky', 'DESC')
-    ->orderBy('n.created', 'DESC')
+    ->orderBy('n.published', 'DESC')
     ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
     ->limit(config('node.settings')->get('items_per_page'))
     ->addTag('node_access');
diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc
index c882450217afc71b2fcee950cec63ae3d8735c1c..a0e5e3c5eef1f0fd30f0723eecb640a95b3f03e8 100644
--- a/core/modules/node/node.tokens.inc
+++ b/core/modules/node/node.tokens.inc
@@ -74,6 +74,11 @@ function node_token_info() {
     'description' => t("The date the node was most recently updated."),
     'type' => 'date',
   );
+  $node['published'] = array(
+    'name' => t("Date published"),
+    'description' => t("The date the node was first published."),
+    'type' => 'date',
+  );
   $node['author'] = array(
     'name' => t("Author"),
     'description' => t("The author of the node."),
@@ -194,6 +199,10 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
         case 'changed':
           $replacements[$original] = format_date($node->changed, 'medium', '', NULL, $langcode);
           break;
+
+        case 'published':
+          $replacements[$original] = format_date($node->published, 'medium', '', NULL, $langcode);
+          break;
       }
     }
 
@@ -209,6 +218,10 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
     if ($changed_tokens = token_find_with_prefix($tokens, 'changed')) {
       $replacements += token_generate('date', $changed_tokens, array('date' => $node->changed), $options);
     }
+
+    if ($published_tokens = token_find_with_prefix($tokens, 'published')) {
+      $replacements += token_generate('date', $published_tokens, array('date' => $node->published), $options);
+    }
   }
 
   return $replacements;
diff --git a/core/modules/node/node.views.inc b/core/modules/node/node.views.inc
index cd6575ef8bda8658b3170736f9ed5350a7c4eced..3c931f197032fcec04fb0e943a996ecfd164cf77 100644
--- a/core/modules/node/node.views.inc
+++ b/core/modules/node/node.views.inc
@@ -114,6 +114,22 @@ function node_views_data() {
     ),
   );
 
+  // published field
+  $data['node']['published'] = array(
+    'title' => t('Published date'),
+    'help' => t('The date the content was first published.'),
+    'field' => array(
+      'id' => 'date',
+      'click sortable' => TRUE,
+    ),
+    'sort' => array(
+      'id' => 'date'
+    ),
+    'filter' => array(
+      'id' => 'date',
+    ),
+  );
+
   // Content type
   $data['node']['type'] = array(
     'title' => t('Type'), // The item it appears as on the UI,
@@ -385,6 +401,60 @@ function node_views_data() {
     ),
   );
 
+  $data['node']['published_fulldate'] = array(
+    'title' => t('Published date'),
+    'help' => t('Date in the form of CCYYMMDD.'),
+    'argument' => array(
+      'field' => 'published',
+      'id' => 'created_fulldate',
+    ),
+  );
+
+  $data['node']['published_year_month'] = array(
+    'title' => t('Published year + month'),
+    'help' => t('Date in the form of YYYYMM.'),
+    'argument' => array(
+      'field' => 'published',
+      'id' => 'created_year_month',
+    ),
+  );
+
+  $data['node']['published_year'] = array(
+    'title' => t('Published year'),
+    'help' => t('Date in the form of YYYY.'),
+    'argument' => array(
+      'field' => 'published',
+      'id' => 'created_year',
+    ),
+  );
+
+  $data['node']['published_month'] = array(
+    'title' => t('Published month'),
+    'help' => t('Date in the form of MM (01 - 12).'),
+    'argument' => array(
+      'field' => 'published',
+      'id' => 'created_month',
+    ),
+  );
+
+  $data['node']['published_day'] = array(
+    'title' => t('Published day'),
+    'help' => t('Date in the form of DD (01 - 31).'),
+    'argument' => array(
+      'field' => 'published',
+      'id' => 'created_day',
+    ),
+  );
+
+  $data['node']['published_week'] = array(
+    'title' => t('Published week'),
+    'help' => t('Date in the form of WW (01 - 53).'),
+    'argument' => array(
+      'field' => 'published',
+      'id' => 'created_week',
+    ),
+  );
+
   // uid field
   $data['node']['uid'] = array(
     'title' => t('Author uid'),
diff --git a/core/modules/node/templates/node.tpl.php b/core/modules/node/templates/node.tpl.php
index 196d26fbcafc25f2f030cd5aae6d89b102962f9e..cf72d6a112b4ebdb95a055c386c20f8a9fe44368 100644
--- a/core/modules/node/templates/node.tpl.php
+++ b/core/modules/node/templates/node.tpl.php
@@ -11,8 +11,9 @@
  *   hide($content['field_example']) to temporarily suppress the printing of a
  *   given element.
  * - $user_picture: The node author's picture. Use render() to print it.
- * - $date: Formatted creation date. Preprocess functions can reformat it by
- *   calling format_date() with the desired parameters on the $created variable.
+ * - $date: Formatted publication date. Preprocess functions can reformat it by
+ *   calling format_date() with the desired parameters on the $published
+ *   variable.
  * - $name: Themed username of node author output from theme_username().
  * - $node_url: Direct URL of the current node.
  * - $display_submitted: Whether submission information should be displayed.
@@ -45,7 +46,8 @@
  * - $type: Node type; for example, page, article, etc.
  * - $comment_count: Number of comments attached to the node.
  * - $uid: User ID of the node author.
- * - $created: Time the node was published formatted in Unix timestamp.
+ * - $created: Time the node was created formatted in Unix timestamp.
+ * - $published: Time the node was published formatted in Unix timestamp.
  * - $zebra: Outputs either "even" or "odd". Useful for zebra striping in
  *   teaser listings.
  * - $id: Position of the node. Increments each time it's output.
diff --git a/core/modules/node/tests/modules/node_test/node_test.module b/core/modules/node/tests/modules/node_test/node_test.module
index 36b59c9122d41bfeeedd7898b695cec47a09b257..0c2fd99278aafeb73c15d49da1c75f782f12c436 100644
--- a/core/modules/node/tests/modules/node_test/node_test.module
+++ b/core/modules/node/tests/modules/node_test/node_test.module
@@ -134,6 +134,8 @@ function node_test_node_presave(Node $node) {
     $node->created = 280299600;
     // Drupal 1.0 release.
     $node->changed = 979534800;
+    // Sat, 1 Jan 2000 00:00:00 GMT
+    $node->published = 946684800;
   }
   // Determine changes.
   if (!empty($node->original) && $node->original->title == 'test_changes') {
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php b/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php
index dd462d5c438bb3e1cc1390337066e6ee693a552c..7c65b0abfc4011730866fb6d3d797eae8b4138a7 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/DateTimeTest.php
@@ -51,11 +51,11 @@ function testTimeZoneHandling() {
       ->set('formats.medium.pattern.php', 'Y-m-d H:i:s O')
       ->save();
 
-    // Create some nodes with different authored-on dates.
+    // Create some nodes with different published-on dates.
     $date1 = '2007-01-31 21:00:00 -1000';
     $date2 = '2007-07-31 21:00:00 -1000';
-    $node1 = $this->drupalCreateNode(array('created' => strtotime($date1), 'type' => 'article'));
-    $node2 = $this->drupalCreateNode(array('created' => strtotime($date2), 'type' => 'article'));
+    $node1 = $this->drupalCreateNode(array('published' => strtotime($date1), 'type' => 'article'));
+    $node2 = $this->drupalCreateNode(array('published' => strtotime($date2), 'type' => 'article'));
 
     // Confirm date format and time zone.
     $this->drupalGet("node/$node1->nid");
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/NodePublishUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/NodePublishUpgradePathTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff06f10856ae53a7270c320720ade41a3fc054e4
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/NodePublishUpgradePathTest.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Upgrade\NodePublishUpgradePathTest.
+ */
+
+namespace Drupal\system\Tests\Upgrade;
+
+/**
+ * Performs major version release upgrade tests on a populated database.
+ *
+ * Loads an installation of Drupal 7.x and runs the upgrade process on it.
+ *
+ * The install contains the minimal profile modules (along with generated
+ * content) so that an update of a site under this profile may be tested.
+ */
+class NodePublishUpgradePathTest extends UpgradePathTestBase {
+  public static function getInfo() {
+    return array(
+      'name'  => 'Node Publishing Upgrade Path Test',
+      'description'  => 'Upgrade tests for adding published timestamp.',
+      'group' => 'Upgrade path',
+    );
+  }
+
+  public function setUp() {
+    // Path to the database dump files.
+    $this->databaseDumpFiles = array(
+      drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.filled.standard_all.database.php.gz',
+    );
+    parent::setUp();
+  }
+
+  /**
+   * Tests that node.published column was added and filled with expected data.
+   */
+  public function testNodePublishedTimestampUpgrade() {
+    $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
+    $nodes = node_load_multiple(NULL);
+    foreach ($nodes as $node) {
+      $revisions = db_query('SELECT COUNT(*) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField();
+      $timestamp = '';
+      if ($revisions > 1) {
+        $timestamp = db_query('SELECT timestamp FROM {node_revision} WHERE nid = :nid AND status = 1 GROUP BY nid', array(':nid' => $node->nid))->fetchField();
+      }
+      else {
+        $timestamp = db_query('SELECT created FROM {node} WHERE nid = :nid AND status = 1', array(':nid' => $node->nid))->fetchField();
+      }
+      if (!empty($timestamp)) {
+        $this->assertEqual($timestamp, $node->published, 'Published content has published timestamp.');
+      }
+      else {
+        $this->assertEqual(NULL, $node->published, 'Unpublished content does not have published timestamp.');
+      }
+    }
+  }
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
index 778b1a06807873883942676f4bc6ff27113399f1..a633eee0da9bf0bce3670cf55a8df9e3cfd64d82 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
@@ -39,13 +39,13 @@ function testTaxonomyLegacyNode() {
     $date = new DrupalDateTime('1969-01-01 00:00:00');
     $edit = array();
     $edit['title'] = $this->randomName();
-    $edit['date[date]'] = $date->format('Y-m-d');
-    $edit['date[time]'] = $date->format('H:i:s');
+    $edit['published_date[date]'] = $date->format('Y-m-d');
+    $edit['published_date[time]'] = $date->format('H:i:s');
     $edit["body[$langcode][0][value]"] = $this->randomName();
     $edit["field_tags[$langcode]"] = $this->randomName();
     $this->drupalPost('node/add/article', $edit, t('Save and publish'));
     // Checks that the node has been saved.
     $node = $this->drupalGetNodeByTitle($edit['title']);
-    $this->assertEqual($node->created, $date->getTimestamp(), 'Legacy node was saved with the right date.');
+    $this->assertEqual($node->published, $date->getTimestamp(), 'Legacy node was saved with the right date.');
   }
 }
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserTimeZoneTest.php b/core/modules/user/lib/Drupal/user/Tests/UserTimeZoneTest.php
index 8b779151d0677300622bd693b890bf6253025966..3ef12f13d6af3a8582b5f44b249e239bff626e43 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserTimeZoneTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserTimeZoneTest.php
@@ -38,15 +38,15 @@ function testUserTimeZone() {
     $web_user = $this->drupalCreateUser();
     $this->drupalLogin($web_user);
 
-    // Create some nodes with different authored-on dates.
+    // Create some nodes with different published-on dates.
     // Two dates in PST (winter time):
     $date1 = '2007-03-09 21:00:00 -0800';
     $date2 = '2007-03-11 01:00:00 -0800';
     // One date in PDT (summer time):
     $date3 = '2007-03-20 21:00:00 -0700';
-    $node1 = $this->drupalCreateNode(array('created' => strtotime($date1), 'type' => 'article'));
-    $node2 = $this->drupalCreateNode(array('created' => strtotime($date2), 'type' => 'article'));
-    $node3 = $this->drupalCreateNode(array('created' => strtotime($date3), 'type' => 'article'));
+    $node1 = $this->drupalCreateNode(array('published' => strtotime($date1), 'type' => 'article'));
+    $node2 = $this->drupalCreateNode(array('published' => strtotime($date2), 'type' => 'article'));
+    $node3 = $this->drupalCreateNode(array('published' => strtotime($date3), 'type' => 'article'));
 
     // Confirm date format and time zone.
     $this->drupalGet("node/$node1->nid");
diff --git a/core/modules/views/config/views.view.frontpage.yml b/core/modules/views/config/views.view.frontpage.yml
index 638387cba427b7a7d704af81dc7d8f89746b034a..ea083245e73fde6cd0be51374866090a3d20c2b7 100644
--- a/core/modules/views/config/views.view.frontpage.yml
+++ b/core/modules/views/config/views.view.frontpage.yml
@@ -38,10 +38,10 @@ display:
           field: sticky
           order: DESC
           plugin_id: standard
-        created:
-          id: created
+        published:
+          id: published
           table: node
-          field: created
+          field: published
           order: DESC
           plugin_id: date
       filters:
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php
index ce3f52f72389ac20612fafad0416c650a83cd8b7..6186afd1ebe0d6892b0153835359cd6bd5e3d3a8 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php
@@ -43,7 +43,9 @@ function default_argument_form(&$form, &$form_state) {
     parent::default_argument_form($form, $form_state);
     $form['default_argument_type']['#options'] += array('date' => t('Current date'));
     $form['default_argument_type']['#options'] += array('node_created' => t("Current node's creation time"));
-    $form['default_argument_type']['#options'] += array('node_changed' => t("Current node's update time"));  }
+    $form['default_argument_type']['#options'] += array('node_changed' => t("Current node's update time"));
+    $form['default_argument_type']['#options'] += array('node_published' => t("Current node's publish time"));
+  }
 
   /**
    * Set the empty argument value to the current date,
@@ -53,7 +55,7 @@ function get_default_argument($raw = FALSE) {
     if (!$raw && $this->options['default_argument_type'] == 'date') {
       return date($this->definition['format'], REQUEST_TIME);
     }
-    elseif (!$raw && in_array($this->options['default_argument_type'], array('node_created', 'node_changed'))) {
+    elseif (!$raw && in_array($this->options['default_argument_type'], array('node_created', 'node_changed', 'node_published'))) {
       foreach (range(1, 3) as $i) {
         $node = menu_get_object('node', $i);
         if (!empty($node)) {
@@ -74,6 +76,9 @@ function get_default_argument($raw = FALSE) {
       elseif ($this->options['default_argument_type'] == 'node_changed') {
         return date($this->definition['format'], $node->changed);
       }
+      elseif ($this->options['default_argument_type'] == 'node_published') {
+        return date($this->definition['format'], $node->published);
+      }
     }
 
     return parent::get_default_argument($raw);
diff --git a/core/themes/bartik/templates/node.tpl.php b/core/themes/bartik/templates/node.tpl.php
index d32f9ace466dd83af1f58a83a85c604c30578672..d6bbc8dc6d029d5bb8e152ed123fae380e94be22 100644
--- a/core/themes/bartik/templates/node.tpl.php
+++ b/core/themes/bartik/templates/node.tpl.php
@@ -11,8 +11,9 @@
  *   hide($content['field_example']) to temporarily suppress the printing of a
  *   given element.
  * - $user_picture: The node author's picture. Use render() when printing.
- * - $date: Formatted creation date. Preprocess functions can reformat it by
- *   calling format_date() with the desired parameters on the $created variable.
+ * - $date: Formatted publication date. Preprocess functions can reformat it by
+ *   calling format_date() with the desired parameters on the $published
+ *   variable.
  * - $name: Themed username of node author output from theme_username().
  * - $node_url: Direct URL of the current node.
  * - $display_submitted: Whether submission information should be displayed.
@@ -45,7 +46,8 @@
  * - $type: Node type; for example, page, article, etc.
  * - $comment_count: Number of comments attached to the node.
  * - $uid: User ID of the node author.
- * - $created: Time the node was published formatted in Unix timestamp.
+ * - $created: Time the node was created formatted in Unix timestamp.
+ * - $published: Time the node was published formatted in Unix timestamp.
  * - $zebra: Outputs either "even" or "odd". Useful for zebra striping in
  *   teaser listings.
  * - $id: Position of the node. Increments each time it's output.
