diff --git a/src/Plugin/facets/facet_source/SearchApiBaseFacetSource.php b/src/Plugin/facets/facet_source/SearchApiBaseFacetSource.php
index a758724..7aab305 100644
--- a/src/Plugin/facets/facet_source/SearchApiBaseFacetSource.php
+++ b/src/Plugin/facets/facet_source/SearchApiBaseFacetSource.php
@@ -132,13 +132,15 @@ abstract class SearchApiBaseFacetSource extends FacetSourcePluginBase {
     // @todo Make this flexible for each data type in Search API.
     switch ($data_type_plugin_id) {
       case 'boolean':
-      case 'date':
       case 'decimal':
       case 'integer':
       case 'string':
       case 'text':
         $query_types['string'] = 'search_api_string';
         break;
+      case 'date':
+        $query_types['date'] = 'search_api_date';
+        break;
     }
 
     // Find out if the backend implemented the Interface to retrieve specific
diff --git a/src/Plugin/facets/query_type/SearchApiDate.php b/src/Plugin/facets/query_type/SearchApiDate.php
new file mode 100644
index 0000000..bc10a1f
--- /dev/null
+++ b/src/Plugin/facets/query_type/SearchApiDate.php
@@ -0,0 +1,212 @@
+<?php
+
+namespace Drupal\facets\Plugin\facets\query_type;
+
+use Drupal\facets\QueryType\QueryTypePluginBase;
+use Drupal\facets\Result\Result;
+
+/**
+ * Support for date facets within the Search API scope.
+ *
+ * This query type supports dates for all possible backends. This specific
+ * implementation of the query type supports a generic solution of adding facets
+ * for dates.
+ *
+ * If you want to have a specific solution for your backend / module to
+ * implement dates, you can alter the ::getQueryTypesForDataType method on the
+ * backendPlugin to return a different class.
+ *
+ * @FacetsQueryType(
+ *   id = "search_api_date",
+ *   label = @Translation("Date"),
+ * )
+ */
+class SearchApiDate extends QueryTypePluginBase {
+
+  const FACETAPI_DATE_YEAR = 6;
+  const FACETAPI_DATE_MONTH = 5;
+  const FACETAPI_DATE_DAY = 4;
+  const FACETAPI_DATE_HOUR = 3;
+  const FACETAPI_DATE_MINUTE = 2;
+  const FACETAPI_DATE_SECOND = 1;
+
+  /**
+   * Add facet info to the query using the backend native query object.
+   */
+  public function execute() {
+    $query = $this->query;
+
+    // Alter the query here.
+    if (!empty($query)) {
+      $options = &$query->getOptions();
+
+      $operator = $this->facet->getQueryOperator();
+      $field_identifier = $this->facet->getFieldIdentifier();
+      $exclude = $this->facet->getExclude();
+      $options['search_api_facets'][$field_identifier] = [
+        'field' => $field_identifier,
+        'limit' => 50,
+        'operator' => 'and',
+        'min_count' => 0,
+        'missing' => FALSE,
+      ];
+
+      // Add the filter to the query if there are active values.
+      $active_items = $this->facet->getActiveItems();
+      $granularity = $this->getGranularity();
+      if (count($active_items)) {
+        foreach ($active_items as $value) {
+          switch ($granularity) {
+            case static::FACETAPI_DATE_YEAR:
+              $dateTime = new \DateTime();
+              $dateTime->setTimestamp($value);
+
+              $startDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y') . '1-1 00:00:00');
+              $stopDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y') . '12-31 23:59:59');
+
+              $value_start = $startDate->format('U');
+              $value_stop = $stopDate->format('U');
+              break;
+            case static::FACETAPI_DATE_MONTH:
+              $dateTime = new \DateTime();
+              $dateTime->setTimestamp($value);
+
+              $startDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y-m') . '-1 00:00:00');
+              $stopDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y-m') . '-31 23:59:59');
+
+              $value_start = $startDate->format('U');
+              $value_stop = $stopDate->format('U');
+              break;
+            case static::FACETAPI_DATE_DAY:
+              $dateTime = new \DateTime();
+              $dateTime->setTimestamp($value);
+
+              $startDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y-m-d') . '00:00:00');
+              $stopDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y-m-d') . '23:59:59');
+
+              $value_start = $startDate->format('U');
+              $value_stop = $stopDate->format('U');
+              break;
+            case static::FACETAPI_DATE_HOUR:
+              $dateTime = new \DateTime();
+              $dateTime->setTimestamp($value);
+
+              $startDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y-m-d H') . '00:00');
+              $stopDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y-m-d H') . '59:59');
+
+              $value_start = $startDate->format('U');
+              $value_stop = $stopDate->format('U');
+              break;
+            case static::FACETAPI_DATE_MINUTE:
+              $dateTime = new \DateTime();
+              $dateTime->setTimestamp($value);
+
+              $startDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y-m-d H:i') . ':00');
+              $stopDate = \DateTime::createFromFormat('Y-m-d H:i:s', $dateTime->format('Y-m-d H:i') . ':59');
+
+              $value_start = $startDate->format('U');
+              $value_stop = $stopDate->format('U');
+              break;
+            case static::FACETAPI_DATE_SECOND:
+            default:
+              $value_start = $value;
+              $value_stop = $value;
+              break;
+          }
+
+          // Add the filter to the query if there are active values.
+          $active_items = $this->facet->getActiveItems();
+
+          if (count($active_items)) {
+            $filter = $query->createConditionGroup($operator, ['facet:' . $field_identifier]);
+            foreach ($active_items as $value) {
+              // Create a condition group for each value, as each one has a
+              // start and condition.
+              $date_filter = $query->createConditionGroup('AND', ['facet:' . $field_identifier]);
+              $date_filter->addCondition($this->facet->getFieldIdentifier(), $value_start, $exclude ? '<' : '>=');
+              $date_filter->addCondition($this->facet->getFieldIdentifier(), $value_stop, $exclude ? '>' : '<=');
+
+              $filter->addConditionGroup($date_filter);
+            }
+            $query->addConditionGroup($filter);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Build the facet information, so it can be rendered.
+   *
+   * @return \Drupal\facetapi\FacetInterface
+   */
+  public function build() {
+    if (!empty ($this->results)) {
+      /** @var \Drupal\facetapi\Result\ResultInterface[] $facet_results */
+      $facet_results = [];
+      /** @var \DateTime[] $dates */
+      $dates = [];
+      /** @var int $granularity */
+      $granularity = $this->getGranularity();
+
+      foreach ($this->results as $result) {
+        if ($result['count']) {
+          $timestamp = trim($result['filter'], '"');
+          $date = new \DateTime();
+          $date->setTimestamp($timestamp);
+          $dates[] = $date;
+        }
+      }
+
+      foreach ($dates as $date) {
+        switch ($granularity) {
+          case static::FACETAPI_DATE_YEAR:
+            $format = 'Y';
+            $count = (isset($facet_results[$date->format($format)]) ? $facet_results[$date->format($format)]->getCount() +1 : 1);
+            $facet_results[$date->format($format)] = new Result($date->format('U'), $date->format('Y'), $count);
+            break;
+          case static::FACETAPI_DATE_MONTH:
+            $format = 'Ym';
+            $count = (isset($facet_results[$date->format($format)]) ? $facet_results[$date->format($format)]->getCount() +1 : 1);
+            $facet_results[$date->format($format)] = new Result($date->format('U'), $date->format('F Y'), $count);
+            break;
+          case static::FACETAPI_DATE_DAY:
+            $format = 'Ymd';
+            $count = (isset($facet_results[$date->format($format)]) ? $facet_results[$date->format($format)]->getCount() +1 : 1);
+            $facet_results[$date->format($format)] = new Result($date->format('U'), $date->format('d F Y'), $count);
+            break;
+          case static::FACETAPI_DATE_HOUR:
+            $format = 'YmdH';
+            $count = (isset($facet_results[$date->format($format)]) ? $facet_results[$date->format($format)]->getCount() +1 : 1);
+            $facet_results[$date->format($format)] = new Result($date->format('U'), $date->format('d/m/Y H\h'), $count);
+            break;
+          case static::FACETAPI_DATE_MINUTE:
+            $format = 'YmdHi';
+            $count = (isset($facet_results[$date->format($format)]) ? $facet_results[$date->format($format)]->getCount() +1 : 1);
+            $facet_results[$date->format($format)] = new Result($date->format('U'), $date->format('d/m/Y H:i'), $count);
+            break;
+          case static::FACETAPI_DATE_SECOND:
+            $format = 'U';
+            $count = (isset($facet_results[$date->format($format)]) ? $facet_results[$date->format($format)]->getCount() +1 : 1);
+            $facet_results[$date->format($format)] = new Result($date->format('U'), $date->format('d/m/Y H:i:s'), $count);
+            break;
+        }
+      }
+
+      $this->facet->setResults($facet_results);
+    }
+    return $this->facet;
+  }
+
+  /**
+   * Looks at the config for this facet to determine the maximum granularity.
+   *
+   * @return int
+   */
+  protected function getGranularity() {
+    // TODO: there is currently no UI to select a granularity for the facet, so
+    // for now hardcode it as month.
+    return static::FACETAPI_DATE_MONTH;
+  }
+
+}
