diff --git a/fullcalendar.info b/fullcalendar.info
index 7dfbc7e..147cf75 100644
--- a/fullcalendar.info
+++ b/fullcalendar.info
@@ -13,3 +13,4 @@ files[] = includes/views/handlers/fullcalendar_handler_field_gcal.inc
 files[] = includes/views/plugins/fullcalendar_plugin_display_page.inc
 files[] = includes/views/plugins/fullcalendar_plugin_row_fields.inc
 files[] = includes/views/plugins/fullcalendar_plugin_style_fullcalendar.inc
+files[] = includes/views/plugins/fullcalendar_plugin_pager.inc
diff --git a/fullcalendar.module b/fullcalendar.module
index b588b64..cfe8cc5 100644
--- a/fullcalendar.module
+++ b/fullcalendar.module
@@ -344,20 +344,25 @@ function fullcalendar_date_fields($fields) {
  *
  * @param $display
  *   Object representing the View display.
+ * @param $unique
+ *   Boolean to instead return a unique array of date fields.
  *
  * @return
  *  Array of date field labels, keyed by field_name.
  */
-function _fullcalendar_parse_fields($display) {
+function _fullcalendar_parse_fields($display, $unique = NULL) {
   $field_options = array();
   foreach ($display->get_handlers('field') as $id => $field) {
     if (isset($field->definition['field_name'])) {
       $field_options[$id] = $field->definition['field_name'];
     }
     else {
-      $field_options[$id] = $field->definition['title'];
+      $field_options[$id] = $id;
     }
   }
+  if ($unique) {
+    return array_unique(fullcalendar_date_fields($field_options));
+  }
   return array_intersect_key($display->get_field_labels(), fullcalendar_date_fields($field_options));
 }
 
diff --git a/includes/views/fullcalendar.views.inc b/includes/views/fullcalendar.views.inc
index 6298907..fcb87e3 100644
--- a/includes/views/fullcalendar.views.inc
+++ b/includes/views/fullcalendar.views.inc
@@ -56,6 +56,15 @@ function fullcalendar_views_plugins() {
         'type' => 'normal',
       ),
     ),
+    'pager' => array(
+      'fullcalendar' => array(
+        'title' => t('FullCalendar'),
+        'help' => t('Page by date.'),
+        'handler' => 'fullcalendar_plugin_pager',
+        'path' => $path,
+        'uses options' => TRUE,
+      ),
+    ),
   );
 }
 
diff --git a/includes/views/plugins/fullcalendar_plugin_pager.inc b/includes/views/plugins/fullcalendar_plugin_pager.inc
new file mode 100644
index 0000000..ae3f7ec
--- /dev/null
+++ b/includes/views/plugins/fullcalendar_plugin_pager.inc
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * Example plugin to handle paging by month.
+ */
+class fullcalendar_plugin_pager extends views_plugin_pager {
+  /**
+   * This kind of pager does not need to count the number of records.
+   */
+  function use_count_query() {
+    return FALSE;
+  }
+
+  /**
+   * Because we don't know how many pages there are, we never believe there
+   * are more records.
+   */
+  function has_more_records() {
+    return FALSE;
+  }
+
+  /*
+   * Tell Views what this pager's title is.
+   */
+  function summary_title() {
+    return t('By month');
+  }
+
+  /**
+   * Tell Views what options this plugin can store.
+   */
+  function option_definition() {
+    $options = parent::option_definition();
+
+    // Provide options for what $_GET keys to fetch the month and year from.
+    $options['month'] = array('default' => 'month');
+    $options['year'] = array('default' => 'year');
+
+    return $options;
+  }
+
+  /*
+   * Provide the form for setting options.
+   */
+  function options_form(&$form, &$form_state) {
+    $form['month'] = array(
+      '#title' => t('Month attribute'),
+      '#type' => 'textfield',
+      '#description' => t('The query attribute to fetch month data from in the URL.'),
+      '#default_value' => $this->options['month'],
+      '#required' => TRUE,
+    );
+
+    $form['year'] = array(
+      '#title' => t('Year attribute'),
+      '#type' => 'textfield',
+      '#description' => t('The query attribute to fetch year data from in the URL.'),
+      '#default_value' => $this->options['year'],
+      '#required' => TRUE,
+    );
+  }
+
+  /**
+   * This is the heart and soul of the pager.
+   *
+   * This determines what "page" we're on (year and month) and then
+   * modifies the query. Because this is a very naive version, the
+   * code is annotated where it is known that it should be improved to
+   * be a good working pager.
+   */
+  function query() {
+    // First, make sure that there is actually a node available. If not
+    // we will bail immediately.
+    $this->table_alias = $this->view->query->ensure_table('node');
+    if (empty($this->table_alias)) {
+      return;
+    }
+
+    // By fetching our data from the exposed input, it is possible to
+    // feed pager data through some method other than $_GET.
+    $input = $this->view->get_exposed_input();
+
+    // We store the month and year on $this to make it easy for the
+    // renderer to see what ended up selected.
+
+    // Currently we are using only year in the form of YYYY.
+    if (empty($input[$this->options['year']])) {
+      $this->year = format_date(time(), 'custom', 'Y', NULL);
+    }
+    else {
+      $this->year = $input[$this->options['year']];
+    }
+
+    // This pager supports the month as a digit from 1 to 12 only.
+    if (empty($input[$this->options['month']])) {
+      $this->month = format_date(time(), 'custom', 'n', NULL);
+    }
+    else {
+      $this->month = $input[$this->options['month']];
+    }
+
+    // Now, turn the month and year into two dates for the filter.
+    $start = mktime(0, 0, 0, $this->month, 1, $this->year);
+    // Figure out next month:
+    $next_month = $this->month + 1;
+    $next_year = $this->year;
+
+    // Roll it over if we passed 12.
+    if ($next_month == 13) {
+      $next_month = 1;
+      $next_year++;
+    }
+
+    // The last day of the month is the same as the 0th day of the month after it.
+    $end = mktime(23, 59, 59, $next_month, 0, $next_year);
+
+    $group = 'fullcalendar';
+    $this->view->query->set_where_group('OR', $group);
+    $fields = _fullcalendar_parse_fields($this->display->handler, TRUE);
+    foreach ($this->view->field as $field) {
+      if (in_array($field->field, $fields)) {
+        $field_name = "$field->table.$field->real_field";
+        $this->view->query->add_where_expression($group, "$field_name >= :start AND $field_name <= :end", array(':start' => $start, ':end' => $end));
+        $this->view->query->ensure_table($field->table);
+        // Only add once per field.
+        unset($fields[$field->field]);
+      }
+    }
+  }
+}
