diff --git a/modules/recurring_events_registration/recurring_events_registration.install b/modules/recurring_events_registration/recurring_events_registration.install
index aab9be8a4f3d96cf543f48381a1034e3f0bc1447..7ebb81aa6d7f7bd8bd6e3c34a861f850f01b73ee 100644
--- a/modules/recurring_events_registration/recurring_events_registration.install
+++ b/modules/recurring_events_registration/recurring_events_registration.install
@@ -78,3 +78,100 @@ function recurring_events_registration_update_8002() {
 
   \Drupal::entityDefinitionUpdateManager()->installFieldStorageDefinition('bundle', 'registrant', 'registrant', $registrant_type);
 }
+
+/**
+ * Update the event_registration field type to add new settings.
+ */
+function recurring_events_registration_update_8003() {
+  $entity_type_manager = \Drupal::entityTypeManager();
+
+  $storage = $entity_type_manager->getStorage('eventseries');
+  $bundle_definition = $entity_type_manager->getDefinition('eventseries');
+
+  $id_key = $bundle_definition->getKey('id');
+  $revision_key = $bundle_definition->getKey('revision');
+
+  $table_name = $storage->getDataTable() ?: $storage->getBaseTable();
+  $revision_table_name = $storage->getRevisionDataTable() ?: $storage->getRevisionTable();
+
+  $database = \Drupal::database();
+  $definition_manager = \Drupal::entityDefinitionUpdateManager();
+
+  $reg_fields = [
+    'event_registration__value',
+    'event_registration__end_value',
+    'event_registration__registration',
+    'event_registration__registration_type',
+    'event_registration__registration_dates',
+    'event_registration__capacity',
+    'event_registration__waitlist',
+    'event_registration__time_amount',
+    'event_registration__time_type',
+  ];
+
+  $reg_field_mappings = [
+    'event_registration__time_amount' =>'event_registration__instance_schedule_open_amount',
+    'event_registration__time_type' => 'event_registration__instance_schedule_open_units',
+  ];
+
+  $registration_values = $database->select($table_name)
+    ->fields($table_name, [$id_key, $revision_key] + $reg_fields)
+    ->execute()
+    ->fetchAll();
+
+  $update_fields = array_fill_keys($reg_fields, NULL);
+
+  $database->update($table_name)
+    ->fields($update_fields)
+    ->execute();
+
+  $field_storage_definition = $definition_manager->getFieldStorageDefinition('event_registration', 'eventseries');
+  $definition_manager->uninstallFieldStorageDefinition($field_storage_definition);
+
+  $storage_definition = BaseFieldDefinition::create('event_registration')
+    ->setName('event_registration')
+    ->setLabel(t('Event Registration'))
+    ->setDescription('The event registration configuration.')
+    ->setDisplayConfigurable('form', TRUE)
+    ->setDisplayConfigurable('view', TRUE)
+    ->setRevisionable(TRUE)
+    ->setTranslatable(FALSE)
+    ->setCardinality(1)
+    ->setRequired(FALSE)
+    ->setDisplayOptions('form', [
+      'type' => 'event_registration',
+      'weight' => 10,
+    ]);
+
+  \Drupal::entityDefinitionUpdateManager()
+    ->installFieldStorageDefinition('event_registration', 'eventseries', 'eventseries', $storage_definition);
+
+  if (!empty($registration_values)) {
+    foreach ($registration_values as $value) {
+      $values_to_restore = [
+        $id_key => $value->{$id_key},
+        $revision_key => $value->{$revision_key},
+      ];
+      foreach ($reg_fields as $field) {
+        $key = $field;
+        if (isset($reg_field_mappings[$field])) {
+          $key = $reg_field_mappings[$field];
+        }
+        $values_to_restore[$key] = rtrim($value->{$field}, 's');
+        $values_to_restore += [
+          'event_registration__instance_schedule_open' => 'custom',
+          'event_registration__instance_schedule_close' => 'start',
+        ];
+      }
+      $database->update($table_name)
+        ->fields($values_to_restore)
+        ->condition($id_key, $value->{$id_key})
+        ->execute();
+
+      $database->update($revision_table_name)
+        ->fields($values_to_restore)
+        ->condition($id_key, $value->{$id_key})
+        ->execute();
+    }
+  }
+}
diff --git a/modules/recurring_events_registration/src/Plugin/Field/FieldType/EventRegistration.php b/modules/recurring_events_registration/src/Plugin/Field/FieldType/EventRegistration.php
index 12990d206cab271fa5839352a0d48c465cb77e61..c0736684339847949bf276d415e4574de73a1c84 100644
--- a/modules/recurring_events_registration/src/Plugin/Field/FieldType/EventRegistration.php
+++ b/modules/recurring_events_registration/src/Plugin/Field/FieldType/EventRegistration.php
@@ -52,12 +52,39 @@ class EventRegistration extends DateRangeItem {
       'unsigned' => TRUE,
     ];
 
-    $schema['columns']['time_amount'] = [
+    $schema['columns']['instance_schedule_open'] = [
+      'type' => 'varchar',
+      'length' => 255,
+    ];
+
+    $schema['columns']['instance_schedule_open_amount'] = [
       'type' => 'int',
+      'default' => 0,
       'unsigned' => TRUE,
     ];
 
-    $schema['columns']['time_type'] = [
+    $schema['columns']['instance_schedule_open_units'] = [
+      'type' => 'varchar',
+      'length' => 255,
+    ];
+
+    $schema['columns']['instance_schedule_close'] = [
+      'type' => 'varchar',
+      'length' => 255,
+    ];
+
+    $schema['columns']['instance_schedule_close_amount'] = [
+      'type' => 'int',
+      'default' => 0,
+      'unsigned' => TRUE,
+    ];
+
+    $schema['columns']['instance_schedule_close_units'] = [
+      'type' => 'varchar',
+      'length' => 255,
+    ];
+
+    $schema['columns']['instance_schedule_close_type'] = [
       'type' => 'varchar',
       'length' => 255,
     ];
@@ -74,11 +101,19 @@ class EventRegistration extends DateRangeItem {
     $registration_dates = $this->get('registration_dates')->getValue();
     $capacity = $this->get('capacity')->getValue();
     $waitlist = $this->get('waitlist')->getValue();
-    $time_amount = $this->get('time_amount')->getValue();
-    $time_type = $this->get('time_type')->getValue();
+    $instance_schedule_open = $this->get('instance_schedule_open')->getValue();
+    $instance_schedule_open_amount = $this->get('instance_schedule_open_amount')->getValue();
+    $instance_schedule_open_units = $this->get('instance_schedule_open_units')->getValue();
+    $instance_schedule_close = $this->get('instance_schedule_close')->getValue();
+    $instance_schedule_close_amount = $this->get('instance_schedule_close_amount')->getValue();
+    $instance_schedule_close_units = $this->get('instance_schedule_close_units')->getValue();
+    $instance_schedule_close_type = $this->get('instance_schedule_close_type')->getValue();
     return parent::isEmpty() && empty($registration) && empty($registration_type)
       && empty($registration_dates) && empty($capacity) && empty($waitlist)
-      && empty($time_amount) && empty($time_type);
+      && empty($instance_schedule_open) && empty($instance_schedule_open_amount)
+      && empty($instance_schedule_open_units) && empty($instance_schedule_close)
+      && empty($instance_schedule_close_amount) && empty($instance_schedule_close_units)
+      && empty($instance_schedule_close_type);
   }
 
   /**
@@ -107,13 +142,33 @@ class EventRegistration extends DateRangeItem {
       ->setLabel(t('Waitlist'))
       ->setDescription(t('Select whether to enable a waitlist.'));
 
-    $properties['time_amount'] = DataDefinition::create('integer')
-      ->setLabel(t('Registration Time Amount'))
-      ->setDescription(t('Select how many days or hours before the event registration opens.'));
+    $properties['instance_schedule_open'] = DataDefinition::create('string')
+      ->setLabel(t('Instance Registration Open'))
+      ->setDescription(t('Select when to open registrations.'));
+
+    $properties['instance_schedule_open_amount'] = DataDefinition::create('integer')
+      ->setLabel(t('Instance Registration Open Time'))
+      ->setDescription(t('Select when to open registrations (number).'));
+
+    $properties['instance_schedule_open_units'] = DataDefinition::create('string')
+      ->setLabel(t('Instance Registration Open Unit'))
+      ->setDescription(t('Select when to open registrations (units).'));
+
+    $properties['instance_schedule_close'] = DataDefinition::create('string')
+      ->setLabel(t('Instance Registration Close'))
+      ->setDescription(t('Select when to close registrations.'));
+
+    $properties['instance_schedule_close_amount'] = DataDefinition::create('integer')
+      ->setLabel(t('Instance Registration Close Time'))
+      ->setDescription(t('Select when to close registrations (number).'));
+
+    $properties['instance_schedule_close_units'] = DataDefinition::create('string')
+      ->setLabel(t('Instance Registration Close Unit'))
+      ->setDescription(t('Select when to close registrations (units).'));
 
-    $properties['time_type'] = DataDefinition::create('string')
-      ->setLabel(t('Registration Time Type'))
-      ->setDescription(t('Select either days or hours.'));
+    $properties['instance_schedule_close_type'] = DataDefinition::create('string')
+      ->setLabel(t('Instance Registration Close Type'))
+      ->setDescription(t('Select when to close registrations (type).'));
 
     return $properties;
   }
diff --git a/modules/recurring_events_registration/src/Plugin/Field/FieldWidget/EventRegistrationWidget.php b/modules/recurring_events_registration/src/Plugin/Field/FieldWidget/EventRegistrationWidget.php
index 15fcb2540f23bd8b9eb343f7f3f73282bcbd1c12..a2d8f183ea71a1aafbb38aa4331110bd4970005a 100644
--- a/modules/recurring_events_registration/src/Plugin/Field/FieldWidget/EventRegistrationWidget.php
+++ b/modules/recurring_events_registration/src/Plugin/Field/FieldWidget/EventRegistrationWidget.php
@@ -58,7 +58,7 @@ class EventRegistrationWidget extends DateRangeDefaultWidget {
     $element['registration_dates'] = [
       '#type' => 'radios',
       '#title' => $this->t('Registration Dates'),
-      '#description' => $this->t('Choose between open or scheduled registration.'),
+      '#description' => $this->t('Choose between open or scheduled registration. Open registration ends when the event begins.'),
       '#weight' => 2,
       '#default_value' => $items[$delta]->registration_dates ?: 'open',
       '#options' => [
@@ -106,24 +106,114 @@ class EventRegistrationWidget extends DateRangeDefaultWidget {
       ],
     ];
 
-    $element['instance_registration']['time_amount'] = [
-      '#type' => 'number',
-      '#title' => $this->t('Registration Time Amount'),
-      '#description' => $this->t('Enter the amount of time in days or hours before the event(s) start time(s) that registration should open.'),
+    $element['instance_registration']['instance_schedule_open'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Registration Opens'),
+      '#description' => $this->t('Select when to open registration'),
       '#weight' => 0,
-      '#default_value' => $items[$delta]->time_amount ?: '',
+      '#default_value' => $items[$delta]->instance_schedule_open,
+      '#options' => [
+        'now' => $this->t('Now'),
+        'start' => $this->t('At the start of the event'),
+        'custom' => $this->t('Custom schedule'),
+      ],
+    ];
+
+    $element['instance_registration']['open_registration'] = [
+      '#type' => 'container',
+      '#weight' => 1,
+      '#states' => [
+        'visible' => [
+          ':input[name="event_registration[0][instance_registration][instance_schedule_open]"]' => ['value' => 'custom'],
+        ],
+      ],
+      '#attributes' => [
+        'class' => 'container-inline',
+      ],
+    ];
+
+    $element['instance_registration']['open_registration']['instance_schedule_open_amount'] = [
+      '#type' => 'number',
+      '#title' => '',
+      '#weight' => 1,
+      '#default_value' => $items[$delta]->instance_schedule_open_amount ?? '1',
       '#min' => 0,
     ];
 
-    $element['instance_registration']['time_type'] = [
+    $element['instance_registration']['open_registration']['instance_schedule_open_units'] = [
       '#type' => 'select',
-      '#title' => $this->t('Registration Time Type'),
-      '#description' => $this->t("Select either Days or Hours to choose how long before which an event's registration will open."),
+      '#title' => '',
+      '#weight' => 2,
+      '#default_value' => $items[$delta]->instance_schedule_open_units ?? 'month',
+      '#options' => [
+        'month' => $this->t('months'),
+        'week' => $this->t('weeks'),
+        'day' => $this->t('days'),
+        'hour' => $this->t('hours'),
+        'minute' => $this->t('minutes'),
+        'second' => $this->t('seconds'),
+      ],
+      '#suffix' => $this->t('before the event starts'),
+    ];
+
+    $element['instance_registration']['instance_schedule_close'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Registration Closes'),
+      '#description' => $this->t('Select when to close registration'),
+      '#weight' => 3,
+      '#default_value' => $items[$delta]->instance_schedule_close,
+      '#options' => [
+        'start' => $this->t('At the start of the event'),
+        'end' => $this->t('At the end of the event'),
+        'custom' => $this->t('Custom schedule'),
+      ],
+    ];
+
+    $element['instance_registration']['close_registration'] = [
+      '#type' => 'container',
+      '#weight' => 4,
+      '#states' => [
+        'visible' => [
+          ':input[name="event_registration[0][instance_registration][instance_schedule_close]"]' => ['value' => 'custom'],
+        ],
+      ],
+      '#attributes' => [
+        'class' => 'container-inline',
+      ],
+    ];
+
+    $element['instance_registration']['close_registration']['instance_schedule_close_amount'] = [
+      '#type' => 'number',
+      '#title' => '',
       '#weight' => 1,
-      '#default_value' => $items[$delta]->time_type ?: '',
+      '#default_value' => $items[$delta]->instance_schedule_close_amount ?? '1',
+      '#min' => 0,
+    ];
+
+    $element['instance_registration']['close_registration']['instance_schedule_close_units'] = [
+      '#type' => 'select',
+      '#title' => '',
+      '#weight' => 2,
+      '#default_value' => $items[$delta]->instance_schedule_close_units ?? 'week',
+      '#min' => 0,
+      '#options' => [
+        'month' => $this->t('months'),
+        'week' => $this->t('weeks'),
+        'day' => $this->t('days'),
+        'hour' => $this->t('hours'),
+        'minute' => $this->t('minutes'),
+        'second' => $this->t('seconds'),
+      ],
+    ];
+
+    $element['instance_registration']['close_registration']['instance_schedule_close_type'] = [
+      '#type' => 'select',
+      '#title' => '',
+      '#weight' => 3,
+      '#default_value' => $items[$delta]->instance_schedule_close_type ?: '',
       '#options' => [
-        'days' => $this->t('Days'),
-        'hours' => $this->t('Hours'),
+        'before' => $this->t('before the event starts'),
+        'after' => $this->t('after the event starts'),
       ],
     ];
 
@@ -131,7 +221,7 @@ class EventRegistrationWidget extends DateRangeDefaultWidget {
       '#type' => 'number',
       '#title' => $this->t('Total Number of Spaces Available'),
       '#description' => $this->t('Maximum number of attendees available for each series, or individual event. Leave blank for unlimited.'),
-      '#weight' => 4,
+      '#weight' => 5,
       '#default_value' => $items[$delta]->capacity ?: '',
       '#min' => 0,
       '#states' => [
@@ -145,7 +235,7 @@ class EventRegistrationWidget extends DateRangeDefaultWidget {
       '#type' => 'checkbox',
       '#title' => $this->t('Enable Waiting List'),
       '#description' => $this->t('Enable a waiting list if the number of registrations reaches capacity.'),
-      '#weight' => 5,
+      '#weight' => 6,
       '#default_value' => $items[$delta]->waitlist ?: '',
       '#states' => [
         'visible' => [
@@ -164,8 +254,13 @@ class EventRegistrationWidget extends DateRangeDefaultWidget {
     foreach ($values as &$item) {
       $item['value'] = $item['series_registration']['value'];
       $item['end_value'] = $item['series_registration']['end_value'];
-      $item['time_amount'] = (int) $item['instance_registration']['time_amount'];
-      $item['time_type'] = $item['instance_registration']['time_type'];
+      $item['instance_schedule_open'] = $item['instance_registration']['instance_schedule_open'];
+      $item['instance_schedule_open_amount'] = (int) $item['instance_registration']['open_registration']['instance_schedule_open_amount'];
+      $item['instance_schedule_open_units'] = $item['instance_registration']['open_registration']['instance_schedule_open_units'];
+      $item['instance_schedule_close'] = $item['instance_registration']['instance_schedule_close'];
+      $item['instance_schedule_close_amount'] = (int) $item['instance_registration']['close_registration']['instance_schedule_close_amount'];
+      $item['instance_schedule_close_units'] = $item['instance_registration']['close_registration']['instance_schedule_close_units'];
+      $item['instance_schedule_close_type'] = $item['instance_registration']['close_registration']['instance_schedule_close_type'];
       $item['capacity'] = (int) $item['capacity'];
       unset($item['series_registration']);
       unset($item['instance_registration']);
@@ -198,12 +293,32 @@ class EventRegistrationWidget extends DateRangeDefaultWidget {
         $item['waitlist'] = 0;
       }
 
-      if (empty($item['time_amount'])) {
-        $item['time_amount'] = 0;
+      if (empty($item['instance_schedule_open'])) {
+        $item['instance_schedule_open'] = '';
+      }
+
+      if (empty($item['instance_schedule_open_amount'])) {
+        $item['instance_schedule_open_amount'] = 0;
+      }
+
+      if (empty($item['instance_schedule_open_units'])) {
+        $item['instance_schedule_open_units'] = '';
+      }
+
+      if (empty($item['instance_schedule_close'])) {
+        $item['instance_schedule_close'] = '';
+      }
+
+      if (empty($item['instance_schedule_close_amount'])) {
+        $item['instance_schedule_close_amount'] = 0;
+      }
+
+      if (empty($item['instance_schedule_close_units'])) {
+        $item['instance_schedule_close_units'] = '';
       }
 
-      if (empty($item['time_type'])) {
-        $item['time_type'] = '';
+      if (empty($item['instance_schedule_close_type'])) {
+        $item['instance_schedule_close_type'] = '';
       }
 
     }
diff --git a/modules/recurring_events_registration/src/RegistrationCreationService.php b/modules/recurring_events_registration/src/RegistrationCreationService.php
index c2f3e017284f756658b9d82018058141b57271f8..f4e29639b078eddc8ed6701f16484b13b19dfac3 100644
--- a/modules/recurring_events_registration/src/RegistrationCreationService.php
+++ b/modules/recurring_events_registration/src/RegistrationCreationService.php
@@ -344,6 +344,38 @@ class RegistrationCreationService {
     return $type;
   }
 
+  /**
+   * Get instance registration open schedule type.
+   *
+   * @return string
+   *   The type of open registration schedule: now, start, or custom.
+   */
+  public function getInstanceRegistrationOpenScheduleType() {
+    $type = FALSE;
+
+    if (!empty($this->eventSeries->event_registration->instance_schedule_open)) {
+      $type = $this->eventSeries->event_registration->instance_schedule_open;
+    }
+
+    return $type;
+  }
+
+  /**
+   * Get instance registration close schedule type.
+   *
+   * @return string
+   *   The type of close registration schedule: start, end, or custom.
+   */
+  public function getInstanceRegistrationCloseScheduleType() {
+    $type = FALSE;
+
+    if (!empty($this->eventSeries->event_registration->instance_schedule_close)) {
+      $type = $this->eventSeries->event_registration->instance_schedule_close;
+    }
+
+    return $type;
+  }
+
   /**
    * Get registration dates type.
    *
@@ -361,32 +393,75 @@ class RegistrationCreationService {
   }
 
   /**
-   * Get registration time.
+   * Get instance registration open time modifier.
    *
    * @return string
-   *   The time before each event that registration opens.
+   *   The modifier for the opening time relative to the event start.
    */
-  public function getRegistrationTime() {
-    $time = FALSE;
+  public function getInstanceRegistrationOpenTimeModifier() {
+    $modifier = FALSE;
 
-    if (!empty($this->eventSeries->event_registration->time_amount) && !empty($this->getRegistrationTimeUnit())) {
-      $time = $this->eventSeries->event_registration->time_amount . ' ' . $this->getRegistrationTimeUnit();
+    if (!empty($this->eventSeries->event_registration->instance_schedule_open_amount) && !empty($this->getInstanceRegistrationOpenTimeUnit())) {
+      $modifier = $this->eventSeries->event_registration->instance_schedule_open_amount . ' ' . $this->getInstanceRegistrationOpenTimeUnit();
+      $modifier = '- ' . $modifier;
     }
 
-    return $time;
+    return $modifier;
   }
 
   /**
-   * Get registration time unit.
+   * Get instance registration open time unit.
    *
    * @return string
-   *   The unit used to define the registration time, days or hours.
+   *   The unit used to define the open registration time.
    */
-  public function getRegistrationTimeUnit() {
+  public function getInstanceRegistrationOpenTimeUnit() {
     $unit = FALSE;
 
-    if (!empty($this->eventSeries->event_registration->time_type)) {
-      $unit = $this->eventSeries->event_registration->time_type;
+    if (!empty($this->eventSeries->event_registration->instance_schedule_open_units)) {
+      $unit = $this->eventSeries->event_registration->instance_schedule_open_units;
+    }
+
+    return $unit;
+  }
+
+  /**
+   * Get instance registration close time modifier.
+   *
+   * @return string
+   *   The modifier for the closing time relative to the event start.
+   */
+  public function getInstanceRegistrationCloseTimeModifier() {
+    $modifier = FALSE;
+
+    if (!empty($this->eventSeries->event_registration->instance_schedule_close_amount) && !empty($this->getInstanceRegistrationCloseTimeUnit())) {
+      $modifier = $this->eventSeries->event_registration->instance_schedule_close_amount . ' ' . $this->getInstanceRegistrationCloseTimeUnit();
+      switch ($this->eventSeries->event_registration->instance_schedule_close_type) {
+        case 'after':
+          $modifier = '+ ' . $modifier;
+          break;
+
+        case 'before':
+        default:
+          $modifier = '- ' . $modifier;
+          break;
+      }
+    }
+
+    return $modifier;
+  }
+
+  /**
+   * Get instance registration close time unit.
+   *
+   * @return string
+   *   The unit used to define the close registration time.
+   */
+  public function getInstanceRegistrationCloseTimeUnit() {
+    $unit = FALSE;
+
+    if (!empty($this->eventSeries->event_registration->instance_schedule_close_units)) {
+      $unit = $this->eventSeries->event_registration->instance_schedule_close_units;
     }
 
     return $unit;
@@ -473,17 +548,43 @@ class RegistrationCreationService {
               break;
 
             case 'instance':
-              $reg_time_string = $this->getRegistrationTime();
-
-              if (!empty($reg_time_string)) {
-                $event_date = $this->eventInstance->date->start_date;
-
-                $reg_end = clone $event_date;
-                $reg_start = clone $event_date;
+              $event_start_date = $this->eventInstance->date->start_date;
+              $event_end_date = $this->eventInstance->date->end_date;
+
+              // Calculate registration opening time.
+              switch ($this->getInstanceRegistrationOpenScheduleType()) {
+                case 'now':
+                  $reg_start = new DrupalDateTime();
+                  break;
+
+                case 'start':
+                  $reg_start = clone $event_start_date;
+                  break;
+
+                case 'custom':
+                  $open_time_modifier = $this->getInstanceRegistrationOpenTimeModifier();
+                  $reg_start = clone $event_start_date;
+                  $reg_start->modify($open_time_modifier);
+                  break;
+              }
 
-                // Subtract the number of days/hours from the event start date.
-                $reg_start->modify('-' . $reg_time_string);
+              // Calculate registration closing time.
+              switch ($this->getInstanceRegistrationCloseScheduleType()) {
+                case 'start':
+                  $reg_end = clone $event_start_date;
+                  break;
+
+                case 'end':
+                  $reg_end = clone $event_end_date;
+                  break;
+
+                case 'custom':
+                  $close_time_modifier = $this->getInstanceRegistrationCloseTimeModifier();
+                  $reg_end = clone $event_start_date;
+                  $reg_end->modify($close_time_modifier);
+                  break;
               }
+
               break;
           }