<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -41,6 +41,35 @@ module ActsAsSolr #:nodoc:
     #          sort:: Sorts the faceted resuls by highest to lowest count. (true|false)
     #          browse:: This is where the 'drill-down' of the facets work. Accepts an array of
     #                   fields in the format &quot;facet_field:term&quot;
+    #          mincount:: Replacement for zeros (it has been deprecated in Solr). Specifies the
+    #                     minimum count necessary for a facet field to be returned. (Solr's
+    #                     facet.mincount) Overrides :zeros if it is specified. Default is 0.
+    #
+    #          dates:: Run date faceted queries using the following arguments:
+    #            fields:: The fields to be included in the faceted date search (Solr's facet.date).
+    #                     It may be either a String/Symbol or Hash. If it's a hash the options are the
+    #                     same as date_facets minus the fields option (i.e., :start:, :end, :gap, :other,
+    #                     :between). These options if provided will override the base options.
+    #                     (Solr's f.&lt;field_name&gt;.date.&lt;key&gt;=&lt;value&gt;).
+    #            start:: The lower bound for the first date range for all Date Faceting. Required if
+    #                    :fields is present
+    #            end:: The upper bound for the last date range for all Date Faceting. Required if
+    #                  :fields is prsent
+    #            gap:: The size of each date range expressed as an interval to be added to the lower
+    #                  bound using the DateMathParser syntax.  Required if :fields is prsent
+    #            hardend:: A Boolean parameter instructing Solr what do do in the event that
+    #                      facet.date.gap does not divide evenly between facet.date.start and facet.date.end.
+    #            other:: This param indicates that in addition to the counts for each date range
+    #                    constraint between facet.date.start and facet.date.end, other counds should be
+    #                    calculated. May specify more then one in an Array. The possible options are:
+    #              before:: - all records with lower bound less than start
+    #              after:: - all records with upper bound greater than end
+    #              between:: - all records with field values between start and end
+    #              none:: - compute no other bounds (useful in per field assignment)
+    #              all:: - shortcut for before, after, and between
+    #            filter:: Similar to :query option provided by :facets, in that accepts an array of
+    #                     of date queries to limit results. Can not be used as a part of a :field hash.
+    #                     This is the only option that can be used if :fields is not present.
     # 
     # Example:
     # 
@@ -51,6 +80,24 @@ module ActsAsSolr #:nodoc:
     #                                                 :fields =&gt; [:category, :manufacturer],
     #                                                 :browse =&gt; [&quot;category:Memory&quot;,&quot;manufacturer:Someone&quot;]}
     # 
+    #
+    # Examples of date faceting:
+    #
+    #  basic:
+    #    Electronic.find_by_solr &quot;memory&quot;, :facets =&gt; {:dates =&gt; {:fields =&gt; [:updated_at, :created_at],
+    #      :start =&gt; 'NOW-10YEARS/DAY', :end =&gt; 'NOW/DAY', :gap =&gt; '+2YEARS', :other =&gt; :before}}
+    #
+    #  advanced:
+    #    Electronic.find_by_solr &quot;memory&quot;, :facets =&gt; {:dates =&gt; {:fields =&gt; [:updated_at,
+    #    {:created_at =&gt; {:start =&gt; 'NOW-20YEARS/DAY', :end =&gt; 'NOW-10YEARS/DAY', :other =&gt; [:before, :after]}
+    #    }], :start =&gt; 'NOW-10YEARS/DAY', :end =&gt; 'NOW/DAY', :other =&gt; :before, :filter =&gt;
+    #    [&quot;created_at:[NOW-10YEARS/DAY TO NOW/DAY]&quot;, &quot;updated_at:[NOW-1YEAR/DAY TO NOW/DAY]&quot;]}}
+    #
+    #  filter only:
+    #    Electronic.find_by_solr &quot;memory&quot;, :facets =&gt; {:dates =&gt; {:filter =&gt; &quot;updated_at:[NOW-1YEAR/DAY TO NOW/DAY]&quot;}}
+    #
+    #
+    #
     # scores:: If set to true this will return the score as a 'solr_score' attribute
     #          for each one of the instances found. Does not currently work with find_id_by_solr
     # </diff>
      <filename>lib/class_methods.rb</filename>
    </modified>
    <modified>
      <diff>@@ -23,9 +23,42 @@ module ActsAsSolr #:nodoc:
           query_options[:facets][:sort] = :count if options[:facets][:sort]
           query_options[:facets][:mincount] = 0
           query_options[:facets][:mincount] = 1 if options[:facets][:zeros] == false
+          # override the :zeros (it's deprecated anyway) if :mincount exists
+          query_options[:facets][:mincount] = options[:facets][:mincount] if options[:facets][:mincount]
           query_options[:facets][:fields] = options[:facets][:fields].collect{|k| &quot;#{k}_facet&quot;} if options[:facets][:fields]
           query_options[:filter_queries] = replace_types([*options[:facets][:browse]].collect{|k| &quot;#{k.sub!(/ *: */,&quot;_facet:&quot;)}&quot;}) if options[:facets][:browse]
           query_options[:facets][:queries] = replace_types(options[:facets][:query].collect{|k| &quot;#{k.sub!(/ *: */,&quot;_t:&quot;)}&quot;}) if options[:facets][:query]
+          
+          
+          if options[:facets][:dates]
+            query_options[:date_facets] = {}
+            # if options[:facets][:dates][:fields] exists then :start, :end, and :gap must be there
+            if options[:facets][:dates][:fields]
+              [:start, :end, :gap].each { |k| raise &quot;#{k} must be present in faceted date query&quot; unless options[:facets][:dates].include?(k) }
+              query_options[:date_facets][:fields] = []
+              options[:facets][:dates][:fields].each { |f|
+                if f.kind_of? Hash
+                  key = f.keys[0]
+                  query_options[:date_facets][:fields] &lt;&lt; {&quot;#{key}_d&quot; =&gt; f[key]}
+                  validate_date_facet_other_options(f[key][:other]) if f[key][:other]
+                else
+                  query_options[:date_facets][:fields] &lt;&lt; &quot;#{f}_d&quot;
+                end
+              }
+            end
+            
+            query_options[:date_facets][:start]   = options[:facets][:dates][:start] if options[:facets][:dates][:start]
+            query_options[:date_facets][:end]     = options[:facets][:dates][:end] if options[:facets][:dates][:end]
+            query_options[:date_facets][:gap]     = options[:facets][:dates][:gap] if options[:facets][:dates][:gap]
+            query_options[:date_facets][:hardend] = options[:facets][:dates][:hardend] if options[:facets][:dates][:hardend]
+            query_options[:date_facets][:filter]  = replace_types([*options[:facets][:dates][:filter]].collect{|k| &quot;#{k.sub!(/ *:(?!\d) */,&quot;_d:&quot;)}&quot;}) if options[:facets][:dates][:filter]
+
+            if options[:facets][:dates][:other]
+              validate_date_facet_other_options(options[:facets][:dates][:other])
+              query_options[:date_facets][:other]   = options[:facets][:dates][:other]
+            end
+            
+          end          
         end
         
         if models.nil?
@@ -156,5 +189,13 @@ module ActsAsSolr #:nodoc:
         record_id(record).to_s == doc_id.to_s
       end
     end
+    
+    def validate_date_facet_other_options(options)
+      valid_other_options = [:after, :all, :before, :between, :none]
+      options = [options] unless options.kind_of? Array
+      bad_options = options.map {|x| x.to_sym} - valid_other_options
+      raise &quot;Invalid option#{'s' if bad_options.size &gt; 1} for faceted date's other param: #{bad_options.join(', ')}. May only be one of :after, :all, :before, :between, :none&quot; if bad_options.size &gt; 0
+    end
+    
   end
 end
\ No newline at end of file</diff>
      <filename>lib/parser_methods.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,7 @@
 
 class Solr::Request::Standard &lt; Solr::Request::Select
 
-  VALID_PARAMS = [:query, :sort, :default_field, :operator, :start, :rows, :shards,
+  VALID_PARAMS = [:query, :sort, :default_field, :operator, :start, :rows, :shards, :date_facets,
     :filter_queries, :field_list, :debug_query, :explain_other, :facets, :highlighting, :mlt]
   
   def initialize(params)
@@ -92,6 +92,35 @@ class Solr::Request::Standard &lt; Solr::Request::Select
           end
         end
       end
+      
+      if @params[:date_facets]
+        hash[&quot;facet.date&quot;] = []
+        if @params[:date_facets][:fields]
+          @params[:date_facets][:fields].each do |f|
+            if f.kind_of? Hash
+              key = f.keys[0]
+              hash[&quot;facet.date&quot;] &lt;&lt; key
+              f[key].each { |k, v|
+                hash[&quot;f.#{key}.facet.date.#{k}&quot;] = v
+              }
+            else
+              hash[&quot;facet.date&quot;] &lt;&lt; f
+            end
+          end
+        end
+        hash[&quot;facet.date.start&quot;] = @params[:date_facets][:start]
+        hash[&quot;facet.date.end&quot;] = @params[:date_facets][:end]
+        hash[&quot;facet.date.gap&quot;] = @params[:date_facets][:gap]
+        hash[&quot;facet.date.other&quot;] = @params[:date_facets][:other]
+        hash[&quot;facet.date.hardend&quot;] = @params[:date_facets][:hardend]
+        if @params[:date_facets][:filter]
+          if hash[:fq]
+            hash[:fq] &lt;&lt; @params[:date_facets][:filter]
+          else
+            hash[:fq] = @params[:date_facets][:filter]
+          end
+        end
+      end
     end
     
     # highlighting parameter processing - http://wiki.apache.org/solr/HighlightingParameters</diff>
      <filename>lib/solr/request/standard.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,6 +6,7 @@ class CreateElectronics &lt; ActiveRecord::Migration
       t.column :features, :string
       t.column :category, :string
       t.column :price, :string
+      t.timestamps
     end
   end
 </diff>
      <filename>test/db/migrate/004_create_electronics.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,8 @@ ipod_video:
   features: iTunes, Podcasts, Audiobooks
   category: Electronics
   price: 599.00
+  created_at: &lt;%= Date.today - 1.year %&gt;
+  updated_at: &lt;%= Date.today - 1.month %&gt;
   
 dell_monitor:
   id: 2
@@ -13,6 +15,8 @@ dell_monitor:
   features: 30&quot; TFT active matrix LCD, 2560 x 1600, .25mm dot pitch, 700:1 contrast
   category: Electronics
   price: 750.00
+  created_at: &lt;%= Date.today - 1.year %&gt;
+  updated_at: &lt;%= Date.today - 1.month %&gt;
   
 samsung_hd:
   id: 3
@@ -21,6 +25,8 @@ samsung_hd:
   features: 7200RPM, 8MB cache, IDE Ultra ATA-133
   category: Hard Drive
   price: 319.00
+  created_at: &lt;%= Date.today - 2.years %&gt;
+  updated_at: &lt;%= Date.today - 2.months %&gt;
   
 corsair_ram:
   id: 4
@@ -29,6 +35,8 @@ corsair_ram:
   features: CAS latency 2,	2-3-3-6 timing, 2.75v, unbuffered, heat-spreader
   category: Memory
   price: 155.00
+  created_at: &lt;%= Date.today - 6.years %&gt;
+  updated_at: &lt;%= Date.today - 3.months %&gt;
   
 a_data_ram:
   id: 5
@@ -37,3 +45,5 @@ a_data_ram:
   features: CAS latency 3, 2.7v
   category: Memory
   price: 65.79
+  created_at: &lt;%= Date.today - 9.years %&gt;
+  updated_at: &lt;%= Date.today - 4.months %&gt;</diff>
      <filename>test/fixtures/electronics.yml</filename>
    </modified>
    <modified>
      <diff>@@ -119,4 +119,45 @@ class FacetedSearchTest &lt; Test::Unit::TestCase
     assert_equal({&quot;category_facet&quot;=&gt;{&quot;Memory&quot;=&gt;2}}, records.facets['facet_fields'])
   end
   
+  def test_faceted_search_with_dates
+    records = Electronic.find_by_solr &quot;memory&quot;, :facets =&gt; {:dates =&gt; {:fields =&gt; [:created_at, :updated_at],
+      :start =&gt; (Date.today - 7.years).strftime(&quot;%Y-%m-%dT%H:%M:%SZ&quot;), :end =&gt; Date.today.strftime(&quot;%Y-%m-%dT%H:%M:%SZ&quot;), :gap =&gt; '+1YEAR', :other =&gt; :all}}
+
+    assert_equal 4, records.docs.size
+    
+    assert_equal 0, records.facets[&quot;facet_dates&quot;][&quot;created_at_d&quot;][&quot;after&quot;]
+    assert_equal 1, records.facets[&quot;facet_dates&quot;][&quot;created_at_d&quot;][&quot;before&quot;]
+    assert_equal 3, records.facets[&quot;facet_dates&quot;][&quot;created_at_d&quot;][&quot;between&quot;]
+    
+    assert_equal 0, records.facets[&quot;facet_dates&quot;][&quot;updated_at_d&quot;][&quot;after&quot;]
+    assert_equal 0, records.facets[&quot;facet_dates&quot;][&quot;updated_at_d&quot;][&quot;before&quot;]
+    assert_equal 4, records.facets[&quot;facet_dates&quot;][&quot;updated_at_d&quot;][&quot;between&quot;]
+  end
+  
+  def test_faceted_search_with_dates_filter
+    records = Electronic.find_by_solr &quot;memory&quot;, :facets =&gt; {:dates =&gt; {:filter =&gt; [&quot;updated_at:[#{(Date.today - 3.months).strftime(&quot;%Y-%m-%dT%H:%M:%SZ&quot;)} TO NOW-1MONTH/DAY]&quot;]}}
+    
+    assert_equal 2, records.docs.size
+    
+    records.docs.each { |r|
+      assert r.updated_at &gt;= (Date.today - 3.month)
+      assert r.updated_at &lt;= (Date.today - 1.month)
+    }
+  end
+  
+  def test_faceted_search_with_dates_filter_and_facets
+    # this is a very contrived example but gives us data to validate
+    records = Electronic.find_by_solr &quot;memory&quot;, :facets =&gt; {:dates =&gt; {:filter =&gt; [&quot;updated_at:[#{(Date.today - 3.months).strftime(&quot;%Y-%m-%dT%H:%M:%SZ&quot;)} TO NOW-1MONTH/DAY]&quot;],
+      :fields =&gt; [:created_at, :updated_at], :start =&gt; 'NOW-2MONTHS/DAY', :end =&gt; 'NOW-1MONTH/DAY', :gap =&gt; '+1MONTH', :other =&gt; :all}}
+    
+    assert_equal 2, records.docs.size
+    
+    assert_equal 0, records.facets[&quot;facet_dates&quot;][&quot;created_at_d&quot;][&quot;after&quot;]
+    assert_equal 2, records.facets[&quot;facet_dates&quot;][&quot;created_at_d&quot;][&quot;before&quot;]
+    assert_equal 0, records.facets[&quot;facet_dates&quot;][&quot;created_at_d&quot;][&quot;between&quot;]
+    
+    assert_equal 0, records.facets[&quot;facet_dates&quot;][&quot;updated_at_d&quot;][&quot;after&quot;]
+    assert_equal 1, records.facets[&quot;facet_dates&quot;][&quot;updated_at_d&quot;][&quot;before&quot;]
+    assert_equal 1, records.facets[&quot;facet_dates&quot;][&quot;updated_at_d&quot;][&quot;between&quot;]
+  end
 end</diff>
      <filename>test/functional/faceted_search_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,10 +5,11 @@
 # - features
 # - category
 # - price
+# - created_on
 
 class Electronic &lt; ActiveRecord::Base
   acts_as_solr :facets =&gt; [:category, :manufacturer],
-               :fields =&gt; [:name, :manufacturer, :features, :category, {:price =&gt; {:type =&gt; :range_float, :boost =&gt; 10.0}}],
+               :fields =&gt; [:name, :manufacturer, :features, :category, {:created_at =&gt; :date}, {:updated_at =&gt; :date}, {:price =&gt; {:type =&gt; :range_float, :boost =&gt; 10.0}}],
                :boost  =&gt; 5.0, 
                :exclude_fields =&gt; [:features]
 </diff>
      <filename>test/models/electronic.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>d2220b1840dbdbde8230a8f1dd714a026240bbaf</id>
    </parent>
  </parents>
  <author>
    <name>Mitchell Hatter</name>
    <email>chatter@Curtis-MacBook.local</email>
  </author>
  <url>http://github.com/mattmatt/acts_as_solr/commit/8ea5714649a6628076e3a1a333ed1dcda8143824</url>
  <id>8ea5714649a6628076e3a1a333ed1dcda8143824</id>
  <committed-date>2009-02-28T08:06:58-08:00</committed-date>
  <authored-date>2009-02-27T14:18:01-08:00</authored-date>
  <message>modifications to acts_as_solr in order to provide date faceting facilities, includes tests</message>
  <tree>3da72aa7ad737cc9ba1a5bd1f27fa29f148302e2</tree>
  <committer>
    <name>Mathias Meyer</name>
    <email>meyer@paperplanes.de</email>
  </committer>
</commit>
