Skip to content
Browse files

Add a home-made date dimension builder with specs.

  • Loading branch information...
1 parent 5283372 commit a68832ed516c8a00b813bb508aa1be515d630430 @thbar thbar committed Jun 19, 2011
Showing with 131 additions and 1 deletion.
  1. +5 −1 Gemfile
  2. +10 −0 Gemfile.lock
  3. +5 −0 Rakefile
  4. +40 −0 lib/date_dimension_builder.rb
  5. +70 −0 spec/date_dimension_builder_spec.rb
  6. +1 −0 spec/spec_helper.rb
View
6 Gemfile
@@ -5,4 +5,8 @@ gem 'activewarehouse-etl', :git => 'git@github.com:activewarehouse/activewarehou
gem 'mysql'
gem 'awesome_print'
-gem 'rocco'
+gem 'rocco'
+
+group :test do
+ gem 'rspec'
+end
View
10 Gemfile.lock
@@ -35,6 +35,7 @@ GEM
arel (2.0.10)
awesome_print (0.4.0)
builder (2.1.2)
+ diff-lcs (1.1.2)
fastercsv (1.5.4)
i18n (0.5.0)
mustache (0.99.4)
@@ -48,6 +49,14 @@ GEM
rocco (0.7)
mustache
rdiscount
+ rspec (2.6.0)
+ rspec-core (~> 2.6.0)
+ rspec-expectations (~> 2.6.0)
+ rspec-mocks (~> 2.6.0)
+ rspec-core (2.6.4)
+ rspec-expectations (2.6.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.6.0)
ruby-ole (1.2.11.1)
spreadsheet (0.6.5.4)
ruby-ole (>= 1.0)
@@ -63,3 +72,4 @@ DEPENDENCIES
awesome_print
mysql
rocco
+ rspec
View
5 Rakefile
@@ -1,6 +1,11 @@
require 'bundler'
Bundler.setup
+require 'rspec/core/rake_task'
+
+desc "Run all examples"
+RSpec::Core::RakeTask.new
+
task :rocco do
require 'rocco'
View
40 lib/date_dimension_builder.rb
@@ -0,0 +1,40 @@
+class DateDimensionBuilder
+ # Specify the start date for the first record
+ attr_accessor :start_date
+
+ # Specify the end date for the last record
+ attr_accessor :end_date
+
+ # Initialize the builder.
+ #
+ # * <tt>start_date</tt>: The start date.
+ # * <tt>end_date</tt>: The end date.
+ def initialize(start_date, end_date)
+ @start_date = start_date.class == String ? Date.parse(start_date) : start_date
+ @end_date = end_date.class == String ? Date.parse(end_date) : end_date
+ end
+
+ # Returns an array of hashes representing records in the dimension. The values for each record are
+ # accessed by name.
+ def build(options={})
+ records = []
+ date = start_date
+ while date <= end_date
+ record = {}
+ record[:date] = date.strftime("%Y-%m-%d")
+ record[:month] = Date::MONTHNAMES[date.month].downcase
+ record[:day_of_week] = Date::DAYNAMES[date.wday].downcase
+ record[:year] = date.year.to_s
+ record[:year_and_month] = record[:year] + "-" + date.month.to_s.rjust(2,'0')
+ record[:sql_date_stamp] = date
+ record[:week] = "week #{date.to_date.cweek}"
+ # compute quarter ourselves - available in Time but not in Date - anything better ?
+ quarter = 1 + (date.month-1) / 3
+ record[:quarter] = "Q#{quarter}"
+ record[:semester] = "S#{(quarter+1)/2}"
+ records << record
+ date = date.next
+ end
+ records
+ end
+end
View
70 spec/date_dimension_builder_spec.rb
@@ -0,0 +1,70 @@
+require File.dirname(__FILE__) + '/spec_helper'
+
+require 'date_dimension_builder'
+
+describe "DateDimensionBuilder" do
+
+ def days(from, to, key=nil)
+ result = DateDimensionBuilder.new(from, to).build
+ result.map! { |e| e[key] } unless key.nil?
+ result
+ end
+
+ def day(from, key=nil)
+ days(from, from, key).first
+ end
+
+ it "should return the expected number of days" do
+ days('2007-01-01', '2007-12-31').size.should eql(365)
+ end
+
+ it "should return :date formatted as yyyy-mm-dd" do
+ day('2007-12-31', :date).should eql('2007-12-31')
+ end
+
+ it "should return :month in english" do
+ (1..12).map { |month| day("2007-#{month}-01", :month) }.should eql(
+ %w(january february march april may june july august september october november december)
+ )
+ end
+
+ it "should return :year on four digits" do
+ days('1959-1-1', '1959-12-31', :year).uniq.should eql(%w(1959))
+ end
+
+ it "should return :year_and_month in a sortable fashion" do
+ day('2008-02-03', :year_and_month).should eql('2008-02')
+ day('2008-12-03', :year_and_month).should eql('2008-12')
+ end
+
+ it "should return all the days of week in english" do
+ days('2007-12-01', '2007-12-07', :day_of_week).should eql(%w(saturday sunday monday tuesday wednesday thursday friday))
+ end
+
+ it "should return a sql_date_stamp" do
+ day('1991-1-1', :sql_date_stamp).should eql(Date.parse("1991-1-1"))
+ end
+
+ it "should return :quarter" do
+ day('2007-12-01', :quarter).should eql('Q4')
+ day('2007-06-30', :quarter).should eql('Q2')
+ end
+
+ it "should implement quarter properly - it's home baked after all" do
+ (1..12).map { |month| day("2007-#{month}-01", :quarter) }.should eql(%w(Q1 Q1 Q1 Q2 Q2 Q2 Q3 Q3 Q3 Q4 Q4 Q4))
+ end
+
+ it "should return :semester" do
+ day('2007-7-1', :semester).should eql('S2')
+ day('2007-06-30', :semester).should eql('S1')
+ day('2007-12-31', :semester).should eql('S2')
+ end
+
+ it "should return :week and respect ISO 8601" do
+ # http://fr.wikipedia.org/wiki/ISO_8601
+ day('2009-12-31', :week).should eql('week 53')
+ day('2010-1-1', :week).should eql('week 53')
+ day('2010-1-4', :week).should eql('week 1')
+ end
+
+end
View
1 spec/spec_helper.rb
@@ -0,0 +1 @@
+$: << File.dirname(__FILE__) + '/../lib'

0 comments on commit a68832e

Please sign in to comment.
Something went wrong with that request. Please try again.