Index: handlers/views_handler_filter_datetime.inc
===================================================================
--- handlers/views_handler_filter_datetime.inc	(revision 0)
+++ handlers/views_handler_filter_datetime.inc	(revision 117)
@@ -0,0 +1,181 @@
+<?php
+// $Id: views_handler_filter_date.inc,v 1.3 2008/11/26 19:01:44 merlinofchaos Exp $
+
+/**
+ * Filter to handle dates stored as a timestamp.
+ */
+class views_handler_filter_datetime extends views_handler_filter_numeric {
+  function option_definition() {
+    $options = parent::option_definition();
+
+    // value is already set up properly, we're just adding our new field to it.
+    $options['value']['type']['default'] = 'date';
+
+    return $options;
+  }
+
+  /**
+   * Add a type selector to the value form
+   */
+  function value_form(&$form, &$form_state) {
+    if (empty($form_state['exposed'])) {
+      $form['value']['type'] = array(
+        '#type' => 'radios',
+        '#title' => t('Value type'),
+        '#options' => array(
+          'date' => t('A date in any machine readable format. CCYY-MM-DD HH:MM:SS is preferred.'),
+          'offset' => t('An offset from the current time such as "+1 day" or "-2 hours and 30 minutes"'),
+        ),
+        '#default_value' => !empty($this->value['type']) ? $this->value['type'] : 'date',
+      );
+    }
+    parent::value_form($form, $form_state);
+  }
+
+  function options_validate(&$form, &$form_state) {
+    parent::options_validate($form, $form_state);
+
+    if (!empty($form_state['values']['options']['expose']['optional'])) {
+      // Who cares what the value is if it's exposed and optional.
+      return;
+    }
+
+    $this->validate_valid_time($form['value'], $form_state['values']['options']['operator'], $form_state['values']['options']['value']);
+  }
+
+  function exposed_validate(&$form, &$form_state) {
+    if (empty($this->options['exposed'])) {
+      return;
+    }
+
+    if (!empty($this->options['expose']['optional'])) {
+      // Who cares what the value is if it's exposed and optional.
+      return;
+    }
+
+    $value = &$form_state['values'][$this->options['expose']['identifier']];
+    if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator'])) {
+      $operator = $form_state['values'][$this->options['expose']['operator']];
+    }
+    else {
+      $operator = $this->operator;
+    }
+
+    $this->validate_valid_time($this->options['expose']['identifier'], $operator, $value);
+
+  }
+
+  /**
+   * Validate that the time values convert to something usable.
+   */
+  function validate_valid_time(&$form, $operator, $value) {
+    $operators = $this->operators();
+
+    if ($operators[$operator]['values'] == 1) {
+      $convert = strtotime($value['value']);
+      if ($convert == -1 || $convert === FALSE) {
+        form_error($form['value'], t('Invalid date format.'));
+      }
+    }
+    elseif ($operators[$operator]['values'] == 2) {
+      $min = strtotime($value['min']);
+      if ($min == -1 || $min === FALSE) {
+        form_error($form['min'], t('Invalid date format.'));
+      }
+      $max = strtotime($value['max']);
+      if ($max == -1 || $max === FALSE) {
+        form_error($form['max'], t('Invalid date format.'));
+      }
+    }
+  }
+
+  function accept_exposed_input($input) {
+    if (empty($this->options['exposed'])) {
+      return TRUE;
+    }
+
+    // Store this because it will get overwritten.
+    $type = $this->value['type'];
+    $rc = parent::accept_exposed_input($input);
+
+    // Don't filter if value(s) are empty.
+    $operators = $this->operators();
+    if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator'])) {
+      $operator = $input[$this->options['expose']['operator']];
+    }
+    else {
+      $operator = $this->operator;
+    }
+
+    if ($operators[$operator]['values'] == 1) {
+      if ($this->value['value'] == '') {
+        return FALSE;
+      }
+    }
+    else {
+      if ($this->value['min'] == '' || $this->value['max'] == '') {
+        return FALSE;
+      }
+    }
+
+    // restore what got overwritten by the parent.
+    $this->value['type'] = $type;
+    return $rc;
+  }
+
+  function op_between($field) {
+    if ($this->operator == 'between' && $this->value['type']!='offset') {
+      //$a = intval(strtotime($this->value['min'], 0));
+      //$b = intval(strtotime($this->value['max'], 0));
+      $a = $this->value['min'];
+      $b = $this->value['max'];
+
+      $this->query->add_where($this->options['group'], "$field >= '%s'", $a);
+      $this->query->add_where($this->options['group'], "$field <= '%s'", $b);
+    }
+    else {
+      $a = $this->value['min'];
+      $b = $this->value['max'];
+
+      //$this->query->add_where($this->options['group'], "$field >= '%s'", $a);
+      //$this->query->add_where($this->options['group'], "$field <= '%s'", $b);
+    }
+
+    if ($this->value['type'] == 'offset') {
+        //firep($a);
+        $expl_a = explode(' ', $a);
+        $expr_a = $expl_a[0];
+        $unit_a = $expl_a[1];
+        $expl_b = explode(' ', $b);
+        $expr_b = $expl_b[0];
+        $unit_b = $expl_b[1];
+        $a = 'DATE_ADD(FROM_UNIXTIME(***CURRENT_TIME***),INTERVAL ' . sprintf('%+d', $expr_a).' '.sprintf('%s',$unit_a).')'; // keep sign
+        $b = 'DATE_ADD(FROM_UNIXTIME(***CURRENT_TIME***),INTERVAL ' . sprintf('%+d', $expr_b).' '.sprintf('%s',$unit_b).')'; // keep sign
+        $this->query->add_where($this->options['group'], "$field <= %s", $a);
+        $this->query->add_where($this->options['group'], "$field >= %s", $b);
+    }
+
+    // %s is safe here because strtotime scrubbed the input and we might
+    // have a string if using offset.
+
+  }
+
+  function op_simple($field) {
+    
+    if (!empty($this->value['type']) && $this->value['type'] == 'offset')
+    {
+        $a = $this->value['value'];
+        $expl_a = explode(' ', $a);
+        $expr_a = $expl_a[0];
+        $unit_a = $expl_a[1];
+        $value = 'DATE_ADD(FROM_UNIXTIME(***CURRENT_TIME***),INTERVAL ' . sprintf('%+d', $expr_a).' '.sprintf('%s',$unit_a).')'; // keep sign
+        $this->query->add_where($this->options['group'], "$field $this->operator %s", $value);
+    }
+    else
+    {
+        $value = intval(strtotime($this->value['value'], 0));
+        $this->query->add_where($this->options['group'], "$field $this->operator FROM_UNIXTIME(%s)", $value);
+    }
+    
+  }
+}
Index: includes/handlers.inc
===================================================================
--- includes/handlers.inc	(revision 116)
+++ includes/handlers.inc	(revision 117)
@@ -1075,6 +1075,9 @@
       'views_handler_filter_date' => array(
         'parent' => 'views_handler_filter_numeric',
       ),
+      'views_handler_filter_datetime' => array(
+        'parent' => 'views_handler_filter_numeric',
+      ),
       'views_handler_filter_many_to_one' => array(
         'parent' => 'views_handler_filter_in_operator',
       ),
Index: modules/profile.views.inc
===================================================================
--- modules/profile.views.inc	(revision 116)
+++ modules/profile.views.inc	(revision 117)
@@ -15,6 +15,52 @@
  * Implementation of hook_views_data()
  */
 function profile_views_data() {
+
+
+  $data['dob']['table']['group']  = t('dob');
+/*
+  $data['dob']['table']['base'] = array(
+    'field' => 'uid',
+    'title' => t('Date of birth'),
+    'help' => t('Birthdates of the system known users'),
+  );
+*/
+
+   $data['dob']['table']['join'] = array(
+    'users' => array(
+      'left_field' => 'uid',
+      'field' => 'uid',
+    ),
+   );
+
+  $data['dob']['birthday'] = array(
+    'title' => t('Birthdate'), // The item it appears as on the UI,
+    'help' => t('The date the user was born.'), // The help that appears on the UI,
+    'field' => array(
+      'handler' => 'views_handler_field_date',
+      'click sortable' => TRUE,
+    ),
+    'type' => 'datetime',
+    'sort' => array(
+      'handler' => 'views_handler_sort_date',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_datetime',
+    ),
+    'table' => array(
+        'group' => t('dob'),
+        'join' => array(
+          'users' => array(
+            'table' => 'dob',
+            'left_field' => 'uid',
+            'field' => 'uid',
+          ),
+        ),
+      ),
+  );
+
+
+
   // Define the base group of this table. Fields that don't
   // have a group defined will go into this field by default.
   $data['profile_values']['table']['group']  = t('Profile');
