diff --git a/core/lib/Drupal/Core/Datetime/Element/Datetime.php b/core/lib/Drupal/Core/Datetime/Element/Datetime.php
index a68927a..9d5ad1a 100644
--- a/core/lib/Drupal/Core/Datetime/Element/Datetime.php
+++ b/core/lib/Drupal/Core/Datetime/Element/Datetime.php
@@ -232,6 +232,19 @@ public static function processDatetime(&$element, FormStateInterface $form_state
 
     $element['#tree'] = TRUE;
 
+    // Visibility and disability states need to be applied to the element as a
+    // whole, but the other states apply to the individual parts.
+    if (isset($element['#states']) && is_array($element['#states'])) {
+      $wrapper_states = array_filter($element['#states'], function ($key) {
+        return in_array($key, ['visible', 'invisible', 'disabled', 'enabled']);
+      }, ARRAY_FILTER_USE_KEY);
+      $children_states = array_diff_key($element['#states'], $wrapper_states);
+    }
+    else {
+      $wrapper_states = $children_states = [];
+    }
+    $element['#states'] = $wrapper_states;
+
     if ($element['#date_date_element'] != 'none') {
 
       $date_format = $element['#date_date_element'] != 'none' ? static::getHtml5DateFormat($element) : '';
@@ -269,6 +282,7 @@ public static function processDatetime(&$element, FormStateInterface $form_state
         '#size' => max(12, strlen($element['#value']['date'])),
         '#error_no_message' => TRUE,
         '#date_date_format' => $element['#date_date_format'],
+        '#states' => $children_states,
       );
 
       // Allows custom callbacks to alter the element.
@@ -301,6 +315,7 @@ public static function processDatetime(&$element, FormStateInterface $form_state
         '#required' => $element['#required'],
         '#size' => 12,
         '#error_no_message' => TRUE,
+        '#states' => $children_states,
       );
 
       // Allows custom callbacks to alter the element.
diff --git a/core/misc/states.js b/core/misc/states.js
index 30c938f..615bc63 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -609,13 +609,21 @@
       if (e.value) {
         var label = 'label' + (e.target.id ? '[for=' + e.target.id + ']' : '');
         var $label = $(e.target).attr({'required': 'required', 'aria-required': 'aria-required'}).closest('.js-form-item, .js-form-wrapper').find(label);
+        // A complex form element like 'datetime' (one made up of multiple
+        // sub-elements) may have a label for the element as a whole, which will
+        // not be a true <label>.
+        var $complexLabel = $(e.target).closest('.js-form-wrapper').find('.label');
         // Avoids duplicate required markers on initialization.
         if (!$label.hasClass('js-form-required').length) {
           $label.addClass('js-form-required form-required');
         }
+        if (!$complexLabel.hasClass('js-form-required').length) {
+          $complexLabel.addClass('js-form-required form-required');
+        }
       }
       else {
         $(e.target).removeAttr('required aria-required').closest('.js-form-item, .js-form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required');
+        $(e.target).closest('.js-form-wrapper').find('.label.js-form-required').removeClass('js-form-required form-required');
       }
     }
   });
diff --git a/core/modules/datetime/tests/modules/datetime_states/datetime_states.info.yml b/core/modules/datetime/tests/modules/datetime_states/datetime_states.info.yml
new file mode 100644
index 0000000..75e139f
--- /dev/null
+++ b/core/modules/datetime/tests/modules/datetime_states/datetime_states.info.yml
@@ -0,0 +1,8 @@
+name: 'Datetime #states test'
+type: module
+description: 'Provides an example demonstrating how form #states affect datetime elements.'
+package: Testing
+version: VERSION
+core: 8.x
+dependencies:
+  - datetime
diff --git a/core/modules/datetime/tests/modules/datetime_states/datetime_states.routing.yml b/core/modules/datetime/tests/modules/datetime_states/datetime_states.routing.yml
new file mode 100644
index 0000000..f5e44fe
--- /dev/null
+++ b/core/modules/datetime/tests/modules/datetime_states/datetime_states.routing.yml
@@ -0,0 +1,6 @@
+datetime_states.example:
+  path: '/datetime/states-example'
+  defaults:
+    _form: '\Drupal\datetime_states\Form\StateForm'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/datetime/tests/modules/datetime_states/src/Forms/StateForm.php b/core/modules/datetime/tests/modules/datetime_states/src/Forms/StateForm.php
new file mode 100644
index 0000000..4139057
--- /dev/null
+++ b/core/modules/datetime/tests/modules/datetime_states/src/Forms/StateForm.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\datetime_states\StateForm.
+ */
+
+namespace Drupal\datetime_states;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Defines a settings page for the File Hosting module.
+ */
+class StateForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return "datetime_states_form";
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['toggle_invisible'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Invisible'),
+    );
+    $form['toggle_disabled'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Disabled'),
+    );
+    $form['toggle_required'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Required'),
+    );
+
+
+    $form['date'] = array(
+      '#type' => 'datetime',
+      '#title' => $this->t('Datetime'),
+      '#description' => $this->t('A datetime form element.'),
+      '#states' => [
+        'invisible' => [
+          ':input[name="toggle_invisible"]' => ['checked' => TRUE],
+        ],
+        'disabled' => [
+          ':input[name="toggle_disabled"]' => ['checked' => TRUE],
+        ],
+        'required' => [
+          ':input[name="toggle_required"]' => ['checked' => TRUE],
+        ],
+      ],
+    );
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+
+  }
+
+}
diff --git a/core/themes/bartik/css/components/form.css b/core/themes/bartik/css/components/form.css
index dd5ac0c..85dc868 100644
--- a/core/themes/bartik/css/components/form.css
+++ b/core/themes/bartik/css/components/form.css
@@ -180,7 +180,8 @@ input.form-submit:focus {
   border-color: #bbb;
   color: #717171;
 }
-.form-disabled label {
+.form-disabled label,
+.form-disabled .label {
   color: #717171;
 }
 
diff --git a/core/themes/classy/templates/form/datetime-wrapper.html.twig b/core/themes/classy/templates/form/datetime-wrapper.html.twig
index 3f6aa59..245e8ce 100644
--- a/core/themes/classy/templates/form/datetime-wrapper.html.twig
+++ b/core/themes/classy/templates/form/datetime-wrapper.html.twig
@@ -14,21 +14,29 @@
  */
 #}
 {%
+  set container_classes = [
+    'js-form-wrapper',
+    'form-wrapper',
+  ]
+%}
+{%
   set title_classes = [
     'label',
     required ? 'js-form-required',
     required ? 'form-required',
   ]
 %}
-{% if title %}
-  <h4{{ title_attributes.addClass(title_classes) }}>{{ title }}</h4>
-{% endif %}
-{{ content }}
-{% if errors %}
-  <div class="form-item--error-message">
-    <strong>{{ errors }}</strong>
-  </div>
-{% endif %}
-{% if description %}
-  <div class="description">{{ description }}</div>
-{% endif %}
+<div{{ attributes.addClass(container_classes) }}>
+  {% if title %}
+    <h4{{ title_attributes.addClass(title_classes) }}>{{ title }}</h4>
+  {% endif %}
+  {{ content }}
+  {% if errors %}
+    <div class="form-item--error-message">
+      <strong>{{ errors }}</strong>
+    </div>
+  {% endif %}
+  {% if description %}
+    <div class="description">{{ description }}</div>
+  {% endif %}
+</div>
diff --git a/core/themes/seven/css/components/form.css b/core/themes/seven/css/components/form.css
index f74eb74..02ba78f 100644
--- a/core/themes/seven/css/components/form.css
+++ b/core/themes/seven/css/components/form.css
@@ -52,7 +52,8 @@ label[for] {
 .form-item label.option input {
   vertical-align: middle;
 }
-.form-disabled label {
+.form-disabled label,
+.form-disabled .label {
   color: #737373;
 }
 .form-disabled input.form-text,
@@ -63,6 +64,8 @@ label[for] {
 .form-disabled input.form-number,
 .form-disabled input.form-color,
 .form-disabled input.form-file,
+.form-disabled input.form-date,
+.form-disabled input.form-time,
 .form-disabled textarea.form-textarea,
 .form-disabled select.form-select {
   border-color: #d4d4d4;
