diff --git a/date_popup/date_popup.module b/date_popup/date_popup.module
index a03132e9..f589cf2e 100644
--- a/date_popup/date_popup.module
+++ b/date_popup/date_popup.module
@@ -543,6 +543,10 @@ function date_popup_process_time_part(&$element) {
  * contains a string, after submission it contains an array.
  */
 function date_popup_validate($element, &$form_state) {
+  if (!empty($element['#disabled'])) {
+    // There is no useful state and the result is ignored anyway.
+    return;
+  }
 
   if (date_hidden_element($element)) {
     return;
diff --git a/tests/date_field.test b/tests/date_field.test
index b8aad594..29c9b92a 100644
--- a/tests/date_field.test
+++ b/tests/date_field.test
@@ -12,7 +12,19 @@
    */
   protected function setUp() {
     // Load the date_api module.
-    parent::setUp('field', 'field_ui', 'date_api', 'date', 'date_popup', 'date_tools');
+    $modules = func_get_args();
+    if (isset($modules[0]) && is_array($modules[0])) {
+      $modules = $modules[0];
+    }
+    $modules += array(
+      'field',
+      'field_ui',
+      'date_api',
+      'date',
+      'date_popup',
+      'date_tools',
+    );
+    parent::setUp($modules);
 
     // Create and log in our privileged user.
     $this->privileged_user = $this->drupalCreateUser(
@@ -53,7 +65,7 @@ protected function createDateField($values = array()) {
     $todate = !empty($todate) ? $todate : 'optional';
     $widget_type = !empty($widget_type) ? $widget_type : 'date_select';
     $tz_handling = !empty($tz_handling) ? $tz_handling : 'site';
-    $granularity = !empty($granularity) ? $granularity : array('year', 'month', 'day', 'hour', 'minute');
+    $granularity = !empty($granularity) ? $granularity : array('year', 'month', 'day', 'hour', 'minute', 'second');
     $year_range = !empty($year_range) ? $year_range : '2010:+1';
     $input_format = !empty($input_format) ? $input_format : date_default_format($widget_type);
     $input_format_custom = !empty($input_format_custom) ? $input_format_custom : '';
@@ -280,6 +292,11 @@ protected function deleteDateField($label, $bundle = 'story', $bundle_name = 'St
 
 }
 
+
+
+/**
+ * Functional test of correct handling of disabled field widget elements.
+ */
 class DateFieldTestCase extends DateFieldBasic {
 
   /**
@@ -379,3 +396,132 @@ public function dateForm($field_name, $field_type, $widget_type, $todate = TRUE)
     $this->assertText($should_be, "Found the correct date for a $field_type field using the $widget_type widget displayed using the long date format.");
   }
 }
+
+
+class DateFieldDisabledTestCase extends DateFieldBasic {
+  private $fields = array();
+  private $defaultDateVal1 = '';
+  private $defaultDatestampVal1 = '';
+  private $defaultDatetimeVal1 = '';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Disabled Date Widget Behavior',
+      'description' => 'Test submit or validation behavior when form alterations occur that set #disabled to true.',
+      'group' => 'Date',
+    );
+  }
+
+  protected function setUp() {
+    parent::setUp(array('date_form_behavior_test'));
+    $this->fields = array();
+
+    $this->defaultDateVal1 = date(DATE_FORMAT_ISO);
+    $this->defaultDatestampVal1 = date(DATE_FORMAT_UNIX);
+    $this->defaultDatetimeVal1 = date(DATE_FORMAT_DATETIME);
+
+    $widget_types = array('date_text', 'date_select', 'date_popup');
+    $field_types = array('date', 'datetime', 'datestamp');
+
+    foreach ($widget_types as $widget_type) {
+      foreach ($field_types as $field_type) {
+        $field_name = "{$field_type}_{$widget_type}_disabled";
+        $default_value1_variable_name = "default_{$field_type}_val1";
+
+        $this->fields[] = array(
+          'bundle' => 'date_field_disable',
+          'widget_type' => $widget_type,
+          'label' => t("Field $field_type $widget_type Disabled"),
+          'field_name' => $field_name,
+          'field_type' => $field_type,
+          'increment' => 1,
+        );
+      }
+    }
+
+    array_walk($this->fields, array($this, 'createDateField'));
+  }
+
+  /**
+   * Check to see if two DateObjects are close enough to be considered equal.
+   *
+   * @param DateObject $first
+   *   The first DateObject to check.
+   * @param DateObject $second
+   *   The second DateObject to check.
+   * @param string $message
+   *   The message to display along with the assertion.
+   * @param string $group
+   *   The type of assertion - examples are "Browser", "PHP".
+   * @param int $gap
+   *   The allowed gap, in seconds, between the two dates that will still allow
+   *   them to be considered equivalent. Defaults to 5 seconds.
+   */
+  protected function assertDatesEqual(DateObject $first, DateObject $second, $message = '', $group = 'Other', $gap = 5) {
+    $difference = $first->difference($second);
+    $this->assert($difference < $gap, $message, $group);
+  }
+
+  /**
+   * Functional test to see if disabled date elements behave correctly.
+   *
+   * No validation errors should occur and no field values should be saved
+   * except for field defaults.
+   */
+  public function testDateElementDisabled() {
+    $edit = array();
+
+    $langcode = LANGUAGE_NONE;
+
+    // Display content creation form.
+    $expected_date = new DateObject('now', NULL);
+    $this->drupalGet('node/add/date-field-disable');
+
+    $msg_text = '@fieldname widget found and is disabled';
+    foreach ($this->fields as $field) {
+      $msg_args = array('@fieldname' => $field['field_name']);
+      $this->assertFieldByXPath("//input[starts-with(@name,'{$field['field_name']}') and @disabled]", NULL, format_string($msg_text, $msg_args));
+    }
+
+    $this->drupalPost(NULL, $edit, t('Save'));
+
+    $this->assertNoText("The dates are invalid.", 'Date was not invalid.');
+    $this->assertNoText("There are errors", 'Form error not detected.');
+    $this->assertText("has been created", 'Content was created.');
+
+    // Loop through our fields and verify that we have properly set the values.
+    preg_match('/node\/([0-9]+)\/?/', $this->url, $match);
+    $id = $match[1];
+
+    $entity_type = 'node';
+    $entity = entity_load($entity_type, array($id));
+    // entity_load() gives us an array and we're only after a single one.
+    $entity = reset($entity);
+    $items_present_text = '@fieldname has items.';
+    $value_correct_text = '@fieldname has the correct value.';
+
+    foreach ($this->fields as $index => $test_field) {
+      $msg_args = array('@fieldname' => $test_field['field_name']);
+      $items = field_get_items($entity_type, $entity, $test_field['field_name']);
+      $this->assertNotEqual($items, FALSE, format_string($items_present_text, $msg_args));
+      $actual_date = new DateObject($items[0]['value'], new DateTimeZone("UTC"));
+      $this->assertDatesEqual($expected_date, $actual_date, format_string($value_correct_text, $msg_args));
+
+      // Save this for the next comparison.
+      $this->fields[$index]['default_value'] = $actual_date;
+    }
+
+    // Do another check to make sure defaults are saving on content that already
+    // exists.
+    $this->drupalPost("node/$id/edit", $edit, t('Save'));
+
+    foreach ($this->fields as $test_field) {
+      $msg_args = array('@fieldname' => $test_field['field_name']);
+      $items = field_get_items($entity_type, $entity, $test_field['field_name']);
+      $this->assertNotEqual($items, FALSE, format_string($items_present_text, $msg_args));
+      $actual_date = new DateObject($items[0]['value'], new DateTimeZone("UTC"));
+      $expected_date = $test_field['default_value'];
+      $this->assertDatesEqual($actual_date, $expected_date, format_string($value_correct_text, $msg_args));
+    }
+  }
+}
diff --git a/tests/date_form_behavior_test.info b/tests/date_form_behavior_test.info
new file mode 100644
index 00000000..08129e4b
--- /dev/null
+++ b/tests/date_form_behavior_test.info
@@ -0,0 +1,5 @@
+name = "Date module form behavior tests"
+description = "Support module for widget form testing."
+package = Testing
+core = 7.x
+hidden = TRUE
\ No newline at end of file
diff --git a/tests/date_form_behavior_test.module b/tests/date_form_behavior_test.module
new file mode 100644
index 00000000..97f67b39
--- /dev/null
+++ b/tests/date_form_behavior_test.module
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Helper module for testing Date Field, in cases when widgets are manipulated.
+ *
+ * The module defines
+ * - a node type
+ * - an alter hook that disables field widget elements
+ */
+
+/**
+ * Implements hook_node_info().
+ */
+function date_form_behavior_test_node_info() {
+  return array(
+    'date_field_disable' => array(
+      'name' => t('Date Disabled Widget Node Type'),
+      'base' => 'date_disabled_function_test',
+      'description' => t('date_disabled_function_test node type to test submit and validation behavior when form elements are disabled.'),
+    ),
+  );
+}
+
+
+/**
+ * Implements hook_form_alter().
+ */
+function date_form_behavior_test_form_alter(&$form, &$form_state, $form_id) {
+  if ($form_id == "date_field_disable_node_form") {
+
+    $widget_types = array('date_text', 'date_select', 'date_popup');
+    $field_types = array('date', 'datetime', 'datestamp');
+
+    foreach ($widget_types as $widget_type) {
+      foreach ($field_types as $field_type) {
+        $field_name = "{$field_type}_{$widget_type}_disabled";
+        $form[$field_name]['#disabled'] = TRUE;
+      }
+    }
+  }
+}
