Index: includes/registration.field.inc
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- includes/registration.field.inc	(revision 99dd0c545727912c9892bd86d224979d67e0a360)
+++ includes/registration.field.inc	(revision 110254e979fb72bd34aaee72eae51284d754e002)
@@ -18,14 +18,22 @@
         'default_registration_settings' => array(
           'status' => 0,
           'capacity' => 0,
+          'event' => array(
+            'event_date_field' => NULL,
+          ),
           'scheduling' => array(
+            'scheduling_type' => NULL,
             'open' => NULL,
             'close' => NULL,
+            'open_relative' => NULL,
+            'close_relative' => NULL,
           ),
           'reminder' => array(
             'send_reminder' => 0,
             'reminder_settings' => array(
+              'reminder_type' => NULL,
               'reminder_date' => NULL,
+              'reminder_relative' => NULL,
               'reminder_template' => NULL,
             ),
           ),
@@ -83,6 +91,37 @@
   unset($settings_form['save']);
   $form['default_registration_settings'] += $settings_form;
 
+  // List all parent entity fields suitable for being base date.
+  $parent_field_options = array(NULL => t("- None -"));
+  if (module_exists('date')) {
+    $parent_entity_fields = field_info_instances($instance['entity_type'], $instance['bundle']);
+    foreach ($parent_entity_fields as $field_name => $field_instance) {
+      $field_info = field_info_field($field_name);
+      if (in_array($field_info['type'], array('date', 'datestamp', 'datetime'))) {
+        $parent_field_options[$field_name] = $field_instance['label'];
+      }
+    }
+
+    $form['default_registration_settings']['event'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Event Date'),
+      '#collapsible' => TRUE,
+      '#collapsed' => FALSE,
+      '#tree' => TRUE,
+      '#weight' => 0,
+    );
+
+    // Add a date field selection option for field instance forms.
+    $form['default_registration_settings']['event']['event_date_field'] = array(
+      '#type' => "select",
+      '#title' => "Date field to use for relative dates",
+      '#options' => $parent_field_options,
+      '#default_value' => isset($default_settings['event_date_field']) ? $default_settings['event_date_field'] : 0,
+      '#description' => t("If this entity contains a date field, you can select it here so you can use it for automatic calculation of relative dates."),
+      '#weight' => 0,
+    );
+  }
+
   $form['hide_register_tab'] = array(
     '#type' => 'checkbox',
     '#title' => t('Hide Register Tab'),
@@ -348,20 +387,38 @@
       form_set_error($base_elem_key . 'settings][from_address', t('From email address is invalid.'));
     }
 
+    // If a relative date is set, make sure we have an event date to work with.
+    if (!empty($default_settings['scheduling']['open_relative']) || !empty($default_settings['scheduling']['close_relative']) || $default_settings['reminder']['reminder_settings']['reminder_relative']) {
+      if (empty($default_settings['event']['event_date_field'])) {
+        form_set_error($base_elem_key . 'event][event_date_field', t('Relative dates require an event date field to be set.'));
+      }
+    }
+
     // Validate open date.
     if (!empty($default_settings['scheduling']['open']) && strtotime($default_settings['scheduling']['open']) === FALSE) {
       form_set_error($base_elem_key . 'scheduling][open', t('Date is invalid.'));
     }
 
+    // Validate relative open date.
+    if (!empty($default_settings['scheduling']['open_relative']) && strtotime($default_settings['scheduling']['open_relative']) === FALSE) {
+      form_set_error($base_elem_key . 'scheduling][open_relative', t('Date is invalid.'));
+    }
+
     // Validate close date.
     if (!empty($default_settings['scheduling']['close']) && strtotime($default_settings['scheduling']['close']) === FALSE) {
       form_set_error($base_elem_key . 'scheduling][close', t('Date is invalid.'));
     }
 
+    // Validate relative close date.
+    if (!empty($default_settings['scheduling']['close_relative']) && strtotime($default_settings['scheduling']['close_relative']) === FALSE) {
+      form_set_error($base_elem_key . 'scheduling][close_relative', t('Date is invalid.'));
+    }
+
     // If sending a reminder, ensure date and template are set.
     if ($default_settings['reminder']['send_reminder']
-      && (empty($default_settings['reminder']['reminder_settings']['reminder_date']) ||
-        empty($default_settings['reminder']['reminder_settings']['reminder_template']))) {
+      && (empty($default_settings['reminder']['reminder_settings']['reminder_template'])
+        || !(!empty($default_settings['reminder']['reminder_settings']['reminder_date'])
+          || !empty($default_settings['reminder']['reminder_settings']['reminder_relative'])))) {
       form_set_error($base_elem_key . 'reminder][send_reminder', t('If sending a reminder, provide a date and template.'));
     }
 
@@ -369,6 +426,12 @@
     if (!empty($default_settings['reminder']['reminder_settings']['reminder_date'])
       && strtotime($default_settings['reminder']['reminder_settings']['reminder_date']) === FALSE) {
       form_set_error($base_elem_key . 'reminder][reminder_settings][reminder_date', t('Reminder date is invalid.'));
+    }
+
+    // Validate relative reminder date.
+    if (!empty($default_settings['reminder']['reminder_settings']['reminder_relative'])
+      && strtotime($default_settings['reminder']['reminder_settings']['reminder_relative']) === FALSE) {
+      form_set_error($base_elem_key . 'reminder][reminder_settings][reminder_relative', t('Reminder date is invalid.'));
     }
   }
 }
Index: registration.module
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- registration.module	(revision 99dd0c545727912c9892bd86d224979d67e0a360)
+++ registration.module	(revision 110254e979fb72bd34aaee72eae51284d754e002)
@@ -862,11 +862,14 @@
     if (!$settings) {
       registration_entity_set_default_settings($entity_type, $entity);
     }
+    else {
+      registration_entity_update_relative_dates($entity_type, $entity, $settings);
-  }
-}
+    }
+  }
+}
 
 /**
- * Sets the the registration entity settings to the deafults.
+ * Sets the the registration entity settings to the defaults.
  *
  * @param $entity_type
  * @param $entity
@@ -879,8 +882,55 @@
   ));
   foreach ($registration_instances as $instance) {
     if (isset($instance['settings']['default_registration_settings'])) {
-      $settings = registration_convert_form_settings($instance['settings']['default_registration_settings']);
+      $settings = registration_convert_form_settings($instance['settings']['default_registration_settings'], $entity);
       registration_update_entity_settings($entity_type, $entity_id, $settings);
+    }
+  }
+}
+
+/**
+ * Updates the relative dates on the registration entity settings.
+ *
+ * This function is ran after the base entity that holds the registration (eg. a
+ * node) is updated. The purpose of this function is to synchronize all relative
+ * dates when the base entity date (event date) changes.
+ *
+ * @param $entity_type
+ * @param $entity
+ */
+function registration_entity_update_relative_dates($entity_type, $entity, $settings) {
+  list($entity_id, , $bundle) = entity_extract_ids($entity_type, $entity);
+  $registration_instances = registration_get_registration_instances(array(
+    'entity_type' => $entity_type,
+    'bundle' => $bundle
+  ));
+  foreach ($registration_instances as $instance) {
+    if (isset($instance['settings']['default_registration_settings'])) {
+      // If this registration instance contains a date field.
+      if (!empty($instance['settings']['default_registration_settings']['event']['event_date_field'])) {
+        // Obtain date field value.
+        $date_field_name = $instance['settings']['default_registration_settings']['event']['event_date_field'];
+        $field_items = field_get_items($entity_type, $entity, $date_field_name);
+        $offset_date = new DateObject(
+          $field_items[0]['value'],
+          $field_items[0]['timezone_db']
+        );
+        $event_date = $offset_date->getTimestamp();
+
+        // Store old settings for comparison later.
+        $old_settings = $settings;
+
+        // Calculate new relative dates.
+        registration_convert_relative_date($settings['open'], $event_date, $settings['settings']['open_relative']);
+        registration_convert_relative_date($settings['close'], $event_date, $settings['settings']['close_relative']);
+        registration_convert_relative_date($settings['reminder_date'], $event_date, $settings['settings']['reminder_relative']);
+
+        // If the date fields were changed, update the registration entity.
+        if($settings !== $old_settings) {
+          $settings['settings'] = serialize($settings['settings']);
+          registration_update_entity_settings($entity_type, $entity_id, $settings);
+        }
+      }
     }
   }
 }
Index: includes/registration.forms.inc
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- includes/registration.forms.inc	(revision 99dd0c545727912c9892bd86d224979d67e0a360)
+++ includes/registration.forms.inc	(revision 20fdc5284fc6c2adf7f73135452385128c1d14f1)
@@ -518,14 +518,49 @@
  *
  * @param array $form
  * @param array $form_state
- * @param object $entity_type
- * @param object $entity
+ * @param array $settings
+ * @param string $entity_type
+ * @param integer $entity_id
  *
  * @return array $form
  *
  * @see hook_registration_entity_settings()
  */
 function registration_entity_settings_form($form, &$form_state, $settings, $entity_type = NULL, $entity_id = NULL) {
+  // Prepare the event date value we derive from the entity date field. We need
+  // to set it as a value so it can be used inside registration_convert_form_settings().
+  $form['event_date'] = array(
+    '#type' => 'value',
+    '#value' => '',
+  );
+
+  // Retrieve the date field from the field instance's registration settings.
+  if($entity_type && $entity_id) {
+    // See if there was an event date field on the field instance.
+    $entity = entity_load_single($entity_type, $entity_id);
+    list(, , $entity_bundle) = entity_extract_ids($entity_type, $entity);
+    $registration_instances = registration_get_registration_instances(array(
+      'entity_type' => $entity_type,
+      'bundle' => $entity_bundle,
+    ));
+    foreach ($registration_instances as $instance) {
+      if (isset($instance['settings']['default_registration_settings']['event']['event_date_field'])) {
+        $date_field_name = $instance['settings']['default_registration_settings']['event']['event_date_field'];
+        $field_items = field_get_items($entity_type, $entity, $date_field_name);
+        $offset_date = new DateObject(
+          $field_items[0]['value'],
+          $field_items[0]['timezone_db']
+        );
+        $form['event_date']['#value'] = $offset_date->getTimestamp();
+      }
+    }
+  }
+
+  // Convert the values we stored in the settings back to normal values.
+  foreach($settings['settings'] as $key => $value) {
+    $settings[$key] = $value;
+  }
+
   if ($entity_id) {
     // We'll need this info when we submit the form:
     $form_state['entity'] = array(
@@ -538,12 +573,21 @@
   if (module_exists('date_popup')) {
     $date_popup_installed = TRUE;
   }
+
+  // If there is no date field and we are not editing the field instance, unset the relative date option.
+  $relative_date_disabled = FALSE;
+  if (empty($form['event_date']['#value']) && (!empty($entity_type) && !empty($entity_id))) {
+    $relative_date_disabled = TRUE;
+  }
+
   $form['status'] = array(
     '#type' => 'checkbox',
     '#title' => t('Enable'),
     '#description' => t('Check to enable registrations.'),
     '#default_value' => isset($settings['status']) ? $settings['status'] : -1,
+    '#weight' => -1,
   );
+
   $form['capacity'] = array(
     '#type' => 'textfield',
     '#title' => t('Capacity'),
@@ -552,6 +596,7 @@
     '#maxlength' => 10,
     '#required' => TRUE,
     '#default_value' => isset($settings['capacity']) ? $settings['capacity'] : 0,
+    '#weight' => -1,
   );
 
   $form['scheduling'] = array(
@@ -562,6 +607,40 @@
     '#tree' => TRUE,
   );
 
+  $form['scheduling']['scheduling_type'] = array(
+    '#type' => 'radios',
+    '#title' => t('Date format'),
+    '#default_value' => (isset($settings['scheduling_type']) && empty($relative_date_disabled)) ? $settings['scheduling_type'] : 'absolute',
+    '#options' => array(
+      'absolute' => t('Absolute'),
+      'relative' => t('Relative'),
+    ),
+    '#description' => t('Choose to use a date relative to the event date, or an absolute date.'),
+  );
+  if($relative_date_disabled) {
+    $form['scheduling']['scheduling_type']['relative'] = array(
+      '#disabled' => TRUE,
+      '#title' => $form['scheduling']['scheduling_type']['#options']['relative'] . ' - ' . t('This option is disabled because there is no date field selected on this registration field.'),
+    );
+  }
+
+  $form['scheduling']['open_relative'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Offset for automatic opening of registrations'),
+    '#description' => t("Uses PHP !relative_date_formats relative to the event date. Examples: !examples. You can omit this field if you don't want registrations to !action automatically", array(
+      '!relative_date_formats' => l(t('relative date formats'), 'http://php.net/manual/en/datetime.formats.relative.php'),
+      '!examples' => "'-1 day', '-2 days 14:00', '-7 weekdays', 'first day of this month'", // These can't be translated.
+      '!action' => t('open'),
+    )),
+    '#default_value' => !empty($settings['open_relative']) ? $settings['open_relative'] : '',
+    '#states' => array(
+      'visible' => array('xor',
+        array(':input[name="scheduling[scheduling_type]"]' => array('value' => 'relative')),
+        array(':input[name="instance[settings][default_registration_settings][scheduling][scheduling_type]"]' => array('value' => 'relative')),
+      ),
+    ),
+  );
+
   $form['scheduling']['open'] = array(
     '#type' => 'textfield',
     '#title' => t('Open Date'),
@@ -572,6 +651,12 @@
       )
     ),
     '#default_value' => !empty($settings['open']) ? $settings['open'] : '',
+    '#states' => array(
+      'visible' => array('xor',
+        array(':input[name="scheduling[scheduling_type]"]' => array('value' => 'absolute')),
+        array(':input[name="instance[settings][default_registration_settings][scheduling][scheduling_type]"]' => array('value' => 'absolute')),
+      ),
+    ),
   );
   if ($date_popup_installed) {
     $form['scheduling']['open']['#type'] = 'date_popup';
@@ -582,6 +667,23 @@
     unset($form['scheduling']['open']['#maxlength']);
   }
 
+  $form['scheduling']['close_relative'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Offset for automatic closing of registrations'),
+    '#description' => t("Uses PHP !relative_date_formats relative to the event date. Examples: !examples. You can omit this field if you don't want registrations to !action automatically", array(
+      '!relative_date_formats' => l(t('relative date formats'), 'http://php.net/manual/en/datetime.formats.relative.php'),
+      '!examples' => "'-1 day', '-2 days 14:00', '-7 weekdays', 'first day of this month'", // These can't be translated.
+      '!action' => t('close'),
+    )),
+    '#default_value' => !empty($settings['close_relative']) ? $settings['close_relative'] : '',
+    '#states' => array(
+      'visible' => array('xor',
+        array(':input[name="scheduling[scheduling_type]"]' => array('value' => 'relative')),
+        array(':input[name="instance[settings][default_registration_settings][scheduling][scheduling_type]"]' => array('value' => 'relative')),
+      ),
+    ),
+  );
+
   $form['scheduling']['close'] = array(
     '#type' => 'textfield',
     '#title' => t('Close Date'),
@@ -592,11 +694,17 @@
       )
     ),
     '#default_value' => !empty($settings['close']) ? $settings['close'] : '',
+    '#states' => array(
+      'visible' => array('xor',
+        array(':input[name="scheduling[scheduling_type]"]' => array('value' => 'absolute')),
+        array(':input[name="instance[settings][default_registration_settings][scheduling][scheduling_type]"]' => array('value' => 'absolute')),
+      ),
+    ),
   );
   if ($date_popup_installed) {
     $form['scheduling']['close']['#type'] = 'date_popup';
     $form['scheduling']['close']['#date_format'] = 'Y-m-d H:i:s O';
-    $form['scheduling']['close']['#description'] = t('When to automatically close registrations.. (This uses the !timezone.)', array(
+    $form['scheduling']['close']['#description'] = t('When to automatically close registrations. (This uses the !timezone.)', array(
       '!timezone' => l(t('site default time zone'), 'admin/config/regional/settings'),
       ));
     unset($form['scheduling']['close']['#maxlength']);
@@ -622,12 +730,47 @@
     '#title' => t('Settings'),
     '#collapsible' => FALSE,
     '#states' => array(
-      'visible' => array(
-        ':input[name="send_reminder"]' => array('checked' => TRUE),
+      'visible' => array('xor',
+        array(':input[name="reminder[send_reminder]"]' => array('checked' => TRUE)),
+        array(':input[name="instance[settings][default_registration_settings][reminder][send_reminder]"]' => array('checked' => TRUE)),
       ),
     ),
   );
 
+  $form['reminder']['reminder_settings']['reminder_type'] = array(
+    '#type' => 'radios',
+    '#title' => t('Date format'),
+    '#default_value' => (isset($settings['reminder_type']) && empty($relative_date_disabled)) ? $settings['reminder_type'] : 'absolute',
+    '#options' => array(
+      'absolute' => t('Absolute'),
+      'relative' => t('Relative'),
+    ),
+    '#description' => t('Choose to use a date relative to the event date, or an absolute date.'),
+  );
+  if($relative_date_disabled) {
+    $form['reminder']['reminder_settings']['reminder_type']['relative'] = array(
+      '#disabled' => TRUE,
+      '#title' => $form['reminder']['reminder_settings']['reminder_type']['#options']['relative'] . ' - ' . t('This option is disabled because there is no date field selected on this registration field.'),
+    );
+  }
+
+  $form['reminder']['reminder_settings']['reminder_relative'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Offset for automatic sending of reminders'),
+    '#description' => t("Uses PHP !relative_date_formats relative to the event date. Examples: !examples. You can omit this field if you don't want registrations to !action automatically", array(
+      '!relative_date_formats' => l(t('relative date formats'), 'http://php.net/manual/en/datetime.formats.relative.php'),
+      '!examples' => "'-1 day', '-2 days 14:00', '-7 weekdays', 'first day of this month'", // These can't be translated.
+      '!action' => t('remind'),
+    )),
+    '#default_value' => !empty($settings['reminder_relative']) ? $settings['reminder_relative'] : '',
+    '#states' => array(
+      'visible' => array('xor',
+        array(':input[name="reminder[reminder_settings][reminder_type]"]' => array('value' => 'relative')),
+        array(':input[name="instance[settings][default_registration_settings][reminder][reminder_settings][reminder_type]"]' => array('value' => 'relative')),
+      ),
+    ),
+  );
+
   $form['reminder']['reminder_settings']['reminder_date'] = array(
     '#type' => 'textfield',
     '#title' => t('Reminder Date'),
@@ -638,6 +781,12 @@
       )
     ),
     '#default_value' => !empty($settings['reminder_date']) ? $settings['reminder_date'] : '',
+    '#states' => array(
+      'visible' => array('xor',
+        array(':input[name="reminder[reminder_settings][reminder_type]"]' => array('value' => 'absolute')),
+        array(':input[name="instance[settings][default_registration_settings][reminder][reminder_settings][reminder_type]"]' => array('value' => 'absolute')),
+      ),
+    ),
   );
   if ($date_popup_installed) {
     $form['reminder']['reminder_settings']['reminder_date']['#type'] = 'date_popup';
@@ -785,17 +934,27 @@
     form_set_error('scheduling][open', t('Date is invalid.'));
   }
 
+  // Validate relative open date.
+  if (!empty($form_state['values']['scheduling']['open_relative']) && strtotime($form_state['values']['scheduling']['open_relative']) === FALSE) {
+    form_set_error('scheduling][open_relative', t('Date is invalid.'));
+  }
+
   // Validate close date:
   if (!empty($form_state['values']['scheduling']['close']) && is_string($form_state['values']['scheduling']['close']) && strtotime($form_state['values']['scheduling']['close']) === FALSE) {
     form_set_error('scheduling][close', t('Date is invalid.'));
   }
 
+  // Validate relative close date.
+  if (!empty($form_state['values']['scheduling']['close_relative']) && strtotime($form_state['values']['scheduling']['close_relative']) === FALSE) {
+    form_set_error('scheduling][close_relative', t('Date is invalid.'));
+  }
+
   // If sending a reminder, ensure date and template are set.
   $reminder = $form_state['values']['reminder'];
   if ($reminder['send_reminder']
-    && (empty($reminder['reminder_settings']['reminder_date']) ||
-      empty($reminder['reminder_settings']['reminder_template']))
-  ) {
+    && (empty($reminder['reminder_settings']['reminder_template'])
+      || !(!empty($reminder['reminder_settings']['reminder_date'])
+        || !empty($reminder['reminder_settings']['reminder_relative'])))) {
     form_set_error('reminder][send_reminder', t('If sending a reminder, provide a date and template.'));
   }
 
@@ -807,23 +966,53 @@
     if (!empty($reminder['reminder_settings']['reminder_date'])) {
       form_set_error('reminder][reminder_settings][reminder_date', t('You have provided a reminder date, but not opted to send a reminder. Either check the box to send a reminder, or do not provide a reminder date.'));
     }
+    if (!empty($reminder['reminder_settings']['reminder_relative'])) {
+      form_set_error('reminder][reminder_settings][reminder_relative', t('You have provided a reminder date, but not opted to send a reminder. Either check the box to send a reminder, or do not provide a reminder date.'));
-  }
+    }
+  }
 
   // Validate reminder date:
-  if (!empty($reminder['reminder_settings']['reminder_date'])
+  if (!empty($reminder['reminder_settings']['reminder_date'] && $reminder['reminder_settings']['reminder_type'] == 'absolute')
     && strtotime($reminder['reminder_settings']['reminder_date']) === FALSE
   ) {
     form_set_error('reminder][reminder_settings][reminder_date', t('Reminder date is invalid.'));
   }
 
+  // Validate relative reminder date.
+  if (!empty($reminder['reminder_settings']['reminder_relative'] && $reminder['reminder_settings']['reminder_type'] == 'relative')
+    && strtotime($reminder['reminder_settings']['reminder_relative']) === FALSE) {
+    form_set_error('reminder][reminder_settings][reminder_relative', t('Reminder date is invalid.'));
+  }
+
   // Ensure reminder date is not in the past when "send_reminder" is TRUE:
-  if ($reminder['send_reminder'] && !empty($reminder['reminder_settings']['reminder_date'])) {
+  if ($reminder['send_reminder'] && !empty($reminder['reminder_settings']['reminder_date']) && $reminder['reminder_settings']['reminder_type'] == 'absolute') {
     if (strtotime($reminder['reminder_settings']['reminder_date']) <= time()) {
       form_set_error('reminder][reminder_settings][reminder_date', t('Reminder must be in the future.'));
     }
   }
+
+  // Ensure relative reminder date is not in the past when "send_reminder" is TRUE:
+  if ($reminder['send_reminder'] && !empty($reminder['reminder_settings']['reminder_relative']) && $reminder['reminder_settings']['reminder_type'] == 'relative') {
+    if (strtotime($reminder['reminder_settings']['reminder_date'], $form_state['values']['event_date']) <= time()) {
+      form_set_error('reminder][reminder_settings][reminder_relative', t('Reminder must be in the future.'));
-}
+    }
+  }
 
+  // Ensure none of the relative dates is set later then the event date
+  registration_convert_relative_date($relative_open, $form_state['values']['event_date'], $form_state['values']['scheduling']['open_relative']);
+  if(strtotime($relative_open) > $form_state['values']['event_date']) {
+    form_set_error('scheduling][open_relative', t('Date is set later then the event date.'));
+  }
+  registration_convert_relative_date($relative_close, $form_state['values']['event_date'], $form_state['values']['scheduling']['close_relative']);
+  if(strtotime($relative_close) > $form_state['values']['event_date']) {
+    form_set_error('scheduling][close_relative', t('Date is set later then the event date.'));
+  }
+  registration_convert_relative_date($relative_reminder, $form_state['values']['event_date'], $reminder['reminder_settings']['reminder_relative']);
+  if(strtotime($relative_reminder) > $form_state['values']['event_date']) {
+    form_set_error('reminder][reminder_settings][reminder_relative', t('Date is set later then the event date.'));
+  }
+}
+
 /**
  * Submit handler for registration_entity_settings_form().
  *
@@ -833,7 +1022,7 @@
 function registration_entity_settings_form_submit($form, &$form_state) {
   $entity = $form_state['entity'];
 
-  $fields = registration_convert_form_settings($form_state['values']);
+  $fields = registration_convert_form_settings($form_state['values'], $entity);
 
   registration_update_entity_settings($entity['entity_type'], $entity['entity_id'], $fields);
 
@@ -849,7 +1038,14 @@
  *
  * @return array
  */
-function registration_convert_form_settings($values) {
+function registration_convert_form_settings($values, $entity) {
+  // Add additional settings for relative date processing to settings.
+  $values['settings']['scheduling_type'] = isset($values['scheduling']['scheduling_type']) ? $values['scheduling']['scheduling_type'] : NULL;
+  $values['settings']['open_relative'] = isset($values['scheduling']['open_relative']) ? $values['scheduling']['open_relative'] : NULL;
+  $values['settings']['close_relative'] = isset($values['scheduling']['close_relative']) ? $values['scheduling']['close_relative'] : NULL;
+  $values['settings']['reminder_type'] = isset($values['reminder']['reminder_settings']['reminder_type']) ? $values['reminder']['reminder_settings']['reminder_type'] : NULL;
+  $values['settings']['reminder_relative'] = isset($values['reminder']['reminder_settings']['reminder_relative']) ? $values['reminder']['reminder_settings']['reminder_relative'] : NULL;
+
   $fields = array(
     'status' => $values['status'],
     'capacity' => $values['capacity'],
@@ -862,21 +1058,43 @@
   );
 
   // Reminder: Reminder Date:
-  if (!empty($values['reminder']['reminder_settings']['reminder_date'])) {
+  if (!empty($values['reminder']['reminder_settings']['reminder_date']) && $values['reminder']['reminder_settings']['reminder_type'] == 'absolute') {
     $fields['reminder_date'] = date('Y-m-d H:i:s', strtotime($values['reminder']['reminder_settings']['reminder_date']));
   }
+  elseif (!empty($values['reminder']['reminder_settings']['reminder_relative']) && $values['reminder']['reminder_settings']['reminder_type'] == 'relative') {
+    registration_convert_relative_date($fields['reminder_date'], $values['event_date'], $values['reminder']['reminder_settings']['reminder_relative']);
+  }
 
   // Scheduling: open date:
-  if (!empty($values['scheduling']['open'])) {
+  if (!empty($values['scheduling']['open']) && $values['scheduling']['scheduling_type'] == 'absolute') {
     $fields['open'] = date('Y-m-d H:i:s', strtotime($values['scheduling']['open']));
   }
+  elseif (!empty($values['scheduling']['open_relative']) && $values['scheduling']['scheduling_type'] == 'relative') {
+    registration_convert_relative_date($fields['open'], $values['event_date'], $values['scheduling']['open_relative']);
+  }
 
   // Scheduling: close date:
-  if (!empty($values['scheduling']['close'])) {
+  if (!empty($values['scheduling']['close']) && $values['scheduling']['scheduling_type'] == 'absolute') {
     $fields['close'] = date('Y-m-d H:i:s', strtotime($values['scheduling']['close']));
   }
+  elseif (!empty($values['scheduling']['close_relative']) && $values['scheduling']['scheduling_type'] == 'relative') {
+    registration_convert_relative_date($fields['close'], $values['event_date'], $values['scheduling']['close_relative']);
+  }
 
   return $fields;
+}
+
+/**
+ * Combines a relative date with the event date into a new date value.
+ *
+ * @param $field Variable to receive the result.
+ * @param $event_date Date of the event (base date for relative calculations).
+ * @param $relative_date Relative date.
+ */
+function registration_convert_relative_date(&$field, $event_date, $relative_date) {
+  if(!empty($relative_date)) {
+    $field = date('Y-m-d H:i:s', strtotime($relative_date, $event_date));
+  }
 }
 
 /**
