diff --git a/core/modules/datetime/src/Plugin/views/filter/Date.php b/core/modules/datetime/src/Plugin/views/filter/Date.php
index f73a675fef..8140534751 100644
--- a/core/modules/datetime/src/Plugin/views/filter/Date.php
+++ b/core/modules/datetime/src/Plugin/views/filter/Date.php
@@ -105,21 +105,33 @@ protected function opBetween($field) {
     $timezone = $this->getTimezone();
     $origin_offset = $this->getOffset($this->value['min'], $timezone);
 
-    // Although both 'min' and 'max' values are required, default empty 'min'
-    // value as UNIX timestamp 0.
-    $min = (!empty($this->value['min'])) ? $this->value['min'] : '@0';
-
-    // Convert to ISO format and format for query. UTC timezone is used since
-    // dates are stored in UTC.
-    $a = new DateTimePlus($min, new \DateTimeZone($timezone));
-    $a = $this->query->getDateFormat($this->query->getDateField("'" . $this->dateFormatter->format($a->getTimestamp() + $origin_offset, 'custom', DateTimeItemInterface::DATETIME_STORAGE_FORMAT, DateTimeItemInterface::STORAGE_TIMEZONE) . "'", TRUE, $this->calculateOffset), $this->dateFormat, TRUE);
-    $b = new DateTimePlus($this->value['max'], new \DateTimeZone($timezone));
-    $b = $this->query->getDateFormat($this->query->getDateField("'" . $this->dateFormatter->format($b->getTimestamp() + $origin_offset, 'custom', DateTimeItemInterface::DATETIME_STORAGE_FORMAT, DateTimeItemInterface::STORAGE_TIMEZONE) . "'", TRUE, $this->calculateOffset), $this->dateFormat, TRUE);
-
-    // This is safe because we are manually scrubbing the values.
-    $operator = strtoupper($this->operator);
-    $field = $this->query->getDateFormat($this->query->getDateField($field, TRUE, $this->calculateOffset), $this->dateFormat, TRUE);
-    $this->query->addWhereExpression($this->options['group'], "$field $operator $a AND $b");
+    if (!empty($this->value['min']) && !empty($this->value['max'])) {
+      // Convert to ISO format and format for query. UTC timezone is used since
+      // dates are stored in UTC.
+      $a = new DateTimePlus($this->value['min'], new \DateTimeZone($timezone));
+      $a = $this->query->getDateFormat($this->query->getDateField("'" . $this->dateFormatter->format($a->getTimestamp() + $origin_offset, 'custom', DateTimeItemInterface::DATETIME_STORAGE_FORMAT, DateTimeItemInterface::STORAGE_TIMEZONE) . "'", TRUE, $this->calculateOffset), $this->dateFormat, TRUE);
+      $b = new DateTimePlus($this->value['max'], new \DateTimeZone($timezone));
+      $b = $this->query->getDateFormat($this->query->getDateField("'" . $this->dateFormatter->format($b->getTimestamp() + $origin_offset, 'custom', DateTimeItemInterface::DATETIME_STORAGE_FORMAT, DateTimeItemInterface::STORAGE_TIMEZONE) . "'", TRUE, $this->calculateOffset), $this->dateFormat, TRUE);
+
+      // This is safe because we are manually scrubbing the values.
+      $operator = strtoupper($this->operator);
+      $field = $this->query->getDateFormat($this->query->getDateField($field, TRUE, $this->calculateOffset), $this->dateFormat, TRUE);
+      $this->query->addWhereExpression($this->options['group'], "$field $operator $a AND $b");
+    }
+    elseif (empty($this->value['max'])) {
+      $a = new DateTimePlus($this->value['min'], new \DateTimeZone($timezone));
+      $a = $this->query->getDateFormat($this->query->getDateField("'" . $this->dateFormatter->format($a->getTimestamp() + $origin_offset, 'custom', DateTimeItemInterface::DATETIME_STORAGE_FORMAT, DateTimeItemInterface::STORAGE_TIMEZONE) . "'", TRUE, $this->calculateOffset), $this->dateFormat, TRUE);
+
+      $operator = $this->operator === 'between' ? '>=' : '<';
+      $this->query->addWhereExpression($this->options['group'], "$field $operator $a");
+    }
+    elseif (empty($this->value['min'])) {
+      $b = new DateTimePlus($this->value['max'], new \DateTimeZone($timezone));
+      $b = $this->query->getDateFormat($this->query->getDateField("'" . $this->dateFormatter->format($b->getTimestamp() + $origin_offset, 'custom', DateTimeItemInterface::DATETIME_STORAGE_FORMAT, DateTimeItemInterface::STORAGE_TIMEZONE) . "'", TRUE, $this->calculateOffset), $this->dateFormat, TRUE);
+
+      $operator = $this->operator === 'between' ? '<=' : '>';
+      $this->query->addWhereExpression($this->options['group'], "$field $operator $b");
+    }
   }
 
   /**
diff --git a/core/modules/views/src/Plugin/views/filter/Date.php b/core/modules/views/src/Plugin/views/filter/Date.php
index b7d1821bfd..e4efbb9c05 100644
--- a/core/modules/views/src/Plugin/views/filter/Date.php
+++ b/core/modules/views/src/Plugin/views/filter/Date.php
@@ -157,7 +157,7 @@ public function acceptExposedInput($input) {
     elseif ($operators[$operator]['values'] == 2) {
       // When the operator is either between or not between the input contains
       // two values.
-      if ($this->value['min'] == '' || $this->value['max'] == '') {
+      if ($this->value['min'] == '' && $this->value['max'] == '') {
         return FALSE;
       }
     }
@@ -166,19 +166,41 @@ public function acceptExposedInput($input) {
   }
 
   protected function opBetween($field) {
-    $a = intval(strtotime($this->value['min'], 0));
-    $b = intval(strtotime($this->value['max'], 0));
+    if (!empty($this->value['min']) && !empty($this->value['max'])) {
+      $a = intval(strtotime($this->value['min'], 0));
+      $b = intval(strtotime($this->value['max'], 0));
+
+      if ($this->value['type'] === 'offset') {
+        // Keep sign.
+        $a = '***CURRENT_TIME***' . sprintf('%+d', $a);
+        // Keep sign.
+        $b = '***CURRENT_TIME***' . sprintf('%+d', $b);
+      }
+      // This is safe because we are manually scrubbing the values.
+      // It is necessary to do it this way because $a and $b are formulas when using an offset.
+      $operator = strtoupper($this->operator);
+      $this->query->addWhereExpression($this->options['group'], "$field $operator $a AND $b");
+    }
+    elseif (empty($this->value['max'])) {
+      $a = intval(strtotime($this->value['min'], 0));
 
-    if ($this->value['type'] == 'offset') {
-      // Keep sign.
-      $a = '***CURRENT_TIME***' . sprintf('%+d', $a);
-      // Keep sign.
-      $b = '***CURRENT_TIME***' . sprintf('%+d', $b);
+      if ($this->value['type'] === 'offset') {
+        // Keep sign.
+        $a = '***CURRENT_TIME***' . sprintf('%+d', $a);
+      }
+      $operator = $this->operator === 'between' ? '>=' : '<';
+      $this->query->addWhere($this->options['group'], $field, $a, $operator);
+    }
+    elseif (empty($this->value['min'])) {
+      $b = intval(strtotime($this->value['max'], 0));
+
+      if ($this->value['type'] === 'offset') {
+        // Keep sign.
+        $b = '***CURRENT_TIME***' . sprintf('%+d', $b);
+      }
+      $operator = $this->operator === 'between' ? '<=' : '>';
+      $this->query->addWhere($this->options['group'], $field, $b, $operator);
     }
-    // This is safe because we are manually scrubbing the values.
-    // It is necessary to do it this way because $a and $b are formulas when using an offset.
-    $operator = strtoupper($this->operator);
-    $this->query->addWhereExpression($this->options['group'], "$field $operator $a AND $b");
   }
 
   protected function opSimple($field) {
