diff -urp d:\Temp\date/date/date.module .\date/date/date.module
--- d:\Temp\date/date/date.module	2008-12-02 10:32:35.000000000 -0700
+++ .\date/date/date.module	2008-12-18 17:14:40.359375000 -0700
@@ -358,11 +358,11 @@ function date_formatter_process($element
       $date = date_make_date($value, $timezone_db, $field['type']);
       $dates[$processed] = array();
       $dates[$processed]['db']['object'] = $date;
-      $dates[$processed]['db']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
+      $dates[$processed]['db']['datetime'] = date_format_date($date, 'custom', DATE_FORMAT_DATETIME);
 
       date_timezone_set($date, timezone_open($timezone));
       $dates[$processed]['local']['object'] = $date;
-      $dates[$processed]['local']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
+      $dates[$processed]['local']['datetime'] = date_format_date($date, 'custom', DATE_FORMAT_DATETIME);
       $dates[$processed]['local']['timezone'] = $timezone;
       $dates[$processed]['local']['offset'] = date_offset_get($date);
       
diff -urp d:\Temp\date/date_api.module .\date/date_api.module
--- d:\Temp\date/date_api.module	2008-11-29 09:22:12.000000000 -0700
+++ .\date/date_api.module	2008-12-18 17:22:41.765625000 -0700
@@ -592,7 +592,10 @@ function date_format_date($object, $type
       $format = variable_get('date_format_long', 'l, F j, Y - H:i');
       break;
     case 'custom':
-      $format = $format;
+      // Note: Special handling for fuzzy dates; use the precision encoded in the
+      // date object to derive the 'effective' format. No effect on non-fuzzy
+      // dates.
+      $format = _date_fuzzy_format_derive($format, $object);
       break;
     case 'medium':
     default:
@@ -1294,6 +1297,14 @@ function date_limit_value($date, $granul
  *   a format string with all other elements removed
  */
 function date_limit_format($format, $granularity) {
+
+/*
+  // Special case for fuzzy dates; translate to our most specific format.
+  if (_date_is_fuzzy_format($format)) {
+    $format = 'F d, Y - H:i'; 
+  } 
+*/
+
   // Get rid of dash separating date and time if either is missing.
   if (!date_has_time($granularity)
     || sizeof(array_intersect($granularity, array('year', 'month', 'day')) == 0)) {
@@ -1717,4 +1728,136 @@ function date_api_schema_alter(&$schema)
     'default' => '',
     'description' => t('Per-user timezone name.'),
   );
-}
\ No newline at end of file
+}
+
+/**
+ * Determine if a given format accepts "fuzzy" dates.
+ *
+ * @param $format
+ *   a format string, e.g. "F d, Y - H:i" or "F d, Y - H:i \X" 
+ * @return 
+ *   return true if date format is a fuzzy format (accepts partial dates). 
+ */
+function _date_is_fuzzy_format($format) {
+  return (substr($format,-1) == 'X');
+}
+
+/**
+ * Decode a fuzzy date into its effective non-fuzzy format
+ * for a given datetime.
+ *
+ * @param $format
+ *   a format string, e.g. "F d, Y - H:i" or "F d, Y - H:i \X" 
+ *   NOTE: right now this isn't used, as only one fuzzy format is 
+ *   supported, but in the future we're hopefully support more.
+ * @param $datetime
+ *   a datetime object or string containing a valid date
+ * @return 
+ *   return true if date format is a fuzzy format (accepts partial dates). 
+ */
+function _date_fuzzy_format_derive($format, $dateobject) {
+
+  // Special case: if $format has been stripped to *only* our fuzzy marker, by 
+  // date_limit_value, then just set format to empty string. (otherwise we'll
+  // get an entire date returned for the timezone portion. odd.)
+  if ($format=='\X') {
+    $format = '';
+  }
+
+  if (_date_is_fuzzy_format($format)) {
+  
+    // if we were passed a string for $format, convert it to a datetime object
+    if (is_string($dateobject)) {
+      $dateobject = date_create($dateobject);
+    }
+    
+    // here's our (in)glorious hack:
+    //   determine date precision from seconds field and
+    //   set appropriate partial date
+    $seconds = intval(date_format($dateobject,'s'));
+    switch ($seconds) {
+      case 59: 
+        // minute
+        $format = 'F d, Y - H:i'; break;
+      case 58: 
+        // hour
+        $format = 'F d, Y-H'; break;
+      case 57: 
+        // day
+        $format = 'F d, Y'; break;
+      case 55: 
+        //  month
+        $format = 'F Y'; break;
+      case 52: 
+        // year
+        $format = 'Y'; break;
+      default: 
+        $format = 'F d, Y - H:i'; break;
+    }
+  }
+  else {
+    // date format isn't fuzzy, so nothing to do.
+  }
+  return $format;
+}
+
+/**
+ * Enocde a fuzzy date into a date string. We use the seconds
+ * field to encode what precision we have. (Of course, we can no
+ * longer have seconds precision: only day, month, or year.)
+ *
+ * @param $datestring
+ *   a date in a string, presumably in our chozen fuzzy format
+ * @param $format
+ *   a format string, e.g. "F d, Y - H:i" or "F d, Y - H:i \X" 
+ *   NOTE: right now this isn't used, as only one fuzzy format is 
+ *   supported, but in the future we're hopefully support more.
+ * @return 
+ *   return a datestring that has precision encoded in the seconds field 
+ */
+
+function _date_parse_fuzzy($datestring, $format) {
+  /*
+    Proposed precision encoding:
+      59-minute
+      58-hour
+      57-day
+      56-week
+      55-month
+      54-season
+      53-quarter
+      52-year
+  */
+  $pattern = "/^ *((January)?(February)?(March)?(April)?(May)?(June)?(July)?(August)?(September)?(November)?(December)?(Jan)?(Feb)?(Mar)?(Apr)?(May)?(Jun)?(Jul)?(Aug)?(Sep)?(Nov)?(Dec)?) *([0-9]+)? *,? *([0-9][0-9][0-9][0-9])/i";
+  $match_count = preg_match ($pattern, $datestring, $matches);
+
+  if ($match_count > 0) {
+    $datestring = $matches[0];
+    $month = $matches[1];
+    $day   = $matches[24];
+    $year  = $matches[25];
+
+    // decide precision of our date.
+    if (!$month) { 
+      $month='Jan';
+      $day='1';
+      $precision=52;
+    }
+    else if (!$day) {
+      $day='1';
+      $precision=55;
+    }
+    else {
+      $precision=57;
+    }
+
+    $effective_date = $day . ' ' . $month . ' '. $year . ' ' . '00:00:' . $precision;
+    $d = new DateTime($effective_date);
+    $date = $d->format('Y-m-d H:i:s'); // e.g. 2008-12-16 21:12:57
+  }
+  else {
+    // invalid date
+    $date = '';
+  }
+  return $date;
+}
diff -urp d:\Temp\date/date_api_elements.inc .\date/date_api_elements.inc
--- d:\Temp\date/date_api_elements.inc	2008-11-18 18:42:18.000000000 -0700
+++ .\date/date_api_elements.inc	2008-12-18 17:20:46.421875000 -0700
@@ -141,7 +141,7 @@ function date_text_process($element, $ed
 
   $element['date']['#type'] = 'textfield';
   $element['date']['#weight'] = !empty($element['date']['#weight']) ? $element['date']['#weight'] : $element['#weight'];
-  $element['date']['#default_value'] = is_object($date) ? date_format($date , $element['#date_format']) : '';
+  $element['date']['#default_value'] = is_object($date) ? date_format_date($date , 'custom', $element['#date_format']) : '';
   $element['date']['#attributes'] = array('class' => (isset($element['#attributes']['class']) ? $element['#attributes']['class'] : '') .' date-date');
   $element['date']['#description'] = ' '. t('Format: @date', array('@date' => date($element['#date_format'], time())));
   
@@ -565,6 +565,16 @@ function date_timezone_validate($element
  *   input value converted to a DATE_DATETIME value
  */
 function date_convert_from_custom($date, $format) {
+  // special case for fuzzy dates
+  if (_date_is_fuzzy_format($format)) {
+    // create our encoded version
+    $date = _date_parse_fuzzy($date, $format);
+    // this is the standard format that fuzzy dates get converted to
+    // we fool the rest of this funciton into thinking this was the
+    // format being used.
+    $format = 'Y-m-d H:i:s';
+  }
+
   $array = date_format_patterns();
   foreach ($array as $key => $value) {
     $patterns[] = "`(^|[^\\\\\\\\])". $key ."`"; // the letter with no preceding '\'
@@ -593,7 +603,7 @@ function date_convert_from_custom($date,
   // if we did not find all the values for the patterns in the format, abort
   if (count($letters) != count($values)) {
     return  NULL;
-  }
+  } 
   $final_date = array('hour' => 0, 'minute' => 0, 'second' => 0,
     'month' => 0, 'day' => 0, 'year' => 0);
   foreach ($letters as $i => $letter) {
