Index: ruby/trunk/lib/open_ehr/am/archetype/constraint_model/primitive.rb
===================================================================
--- ruby/trunk/lib/open_ehr/am/archetype/constraint_model/primitive.rb	(revision 400)
+++ ruby/trunk/lib/open_ehr/am/archetype/constraint_model/primitive.rb	(revision 401)
@@ -256,4 +256,38 @@
             end
           end
+
+          class CDuration < CPrimitive
+            attr_reader :range
+            attr_accessor :years_allowed, :months_allowed, :weeks_allowed,
+                          :days_allowed, :hours_allowed, :minutes_allowed,
+                          :seconds_allowed, :fractional_seconds_allowed
+
+            def initialize(args = { })
+              super
+              self.fractional_seconds_allowed = args[:fractional_seconds_allowed]
+              self.seconds_allowed = args[:seconds_allowed]
+              self.minutes_allowed = args[:minutes_allowed]
+              self.hours_allowed = args[:hours_allowed]
+              self.days_allowed = args[:days_allowed]
+              self.months_allowed = args[:months_allowed]
+              self.weeks_allowed = args[:weeks_allowed]
+              self.years_allowed = args[:years_allowed]
+              self.range = args[:range]
+            end
+
+            def range=(range)
+              if range.nil? && !(@years_allowed ||
+                    @months_allowed ||
+                    @weeks_allowed ||
+                    @days_allowed ||
+                    @hours_allowed ||
+                    @minutes_allowed ||
+                    @seconds_allowed ||
+                    @fractional_seconds_allowed)
+                raise ArgumentError, 'invalid range'
+              end
+              @range = range
+            end
+          end
         end # of Primitive
       end # of CostraintModel
Index: ruby/trunk/lib/open_ehr/assumed_library_types.rb
===================================================================
--- ruby/trunk/lib/open_ehr/assumed_library_types.rb	(revision 400)
+++ ruby/trunk/lib/open_ehr/assumed_library_types.rb	(revision 401)
@@ -165,4 +165,11 @@
       end
 
+      def to_days
+        days = nilthenzero(@year)*TimeDefinitions::NOMINAL_DAYS_IN_YEAR +
+          nilthenzero(@month)*TimeDefinitions::NOMINAL_DAYS_IN_MONTH +
+          nilthenzero(@day)
+        return days
+      end
+
       def month_unknown?
         @month.nil?
@@ -217,13 +224,5 @@
 
       def <=>(other)
-        magnitude =
-          nilthenzero(@year)*TimeDefinitions::NOMINAL_DAYS_IN_YEAR +
-          nilthenzero(@month)*TimeDefinitions::NOMINAL_DAYS_IN_MONTH +
-          nilthenzero(@day)
-        other_magnitude =
-          nilthenzero(other.year)*TimeDefinitions::NOMINAL_DAYS_IN_YEAR +
-          nilthenzero(other.month)*TimeDefinitions::NOMINAL_DAYS_IN_MONTH +
-          nilthenzero(other.day)
-        magnitude <=> other_magnitude
+        self.to_days <=> other.to_days
       end
 
@@ -322,5 +321,10 @@
       end
 
-      
+      def to_second
+        second = (nilthenzero(@hour)*60 + nilthenzero(@minute))*60 +
+          nilthenzero(@second) +
+          nilthenzero(@fractional_second)
+        return second
+      end
     end
 
@@ -357,12 +361,5 @@
 
       def <=>(other)
-        magnitude = (nilthenzero(@hour)*60 + nilthenzero(@minute))*60 +
-          nilthenzero(@second) +
-          nilthenzero(@fractional_second)
-        other_magnitude = (nilthenzero(other.hour) * 60 +
-                           nilthenzero(other.minute)) * 60 +
-          nilthenzero(other.second) +
-          nilthenzero(other.fractional_second)
-        magnitude <=> other_magnitude
+        self.to_second <=> other.to_second
       end
 
@@ -480,4 +477,14 @@
         end
       end
+
+      def <=>(other)
+        self.magnitude <=> other.magnitude
+      end
+
+      protected
+      def magnitude
+        return self.to_days*HOURS_IN_DAY*MINUTES_IN_HOUR*SECONDS_IN_MINUTE +
+          self.to_second
+      end
     end
   
Index: ruby/trunk/spec/lib/open_ehr/am/archetype/constraint_model/primitive/c_duration_spec.rb
===================================================================
--- ruby/trunk/spec/lib/open_ehr/am/archetype/constraint_model/primitive/c_duration_spec.rb	(revision 401)
+++ ruby/trunk/spec/lib/open_ehr/am/archetype/constraint_model/primitive/c_duration_spec.rb	(revision 401)
@@ -0,0 +1,69 @@
+require File.dirname(__FILE__) + '/../../../../../../spec_helper'
+include OpenEHR::AssumedLibraryTypes
+include OpenEHR::AM::Archetype
+include OpenEHR::AM::Archetype::ConstraintModel::Primitive
+
+describe CDuration do
+  before(:each) do
+    assumed_value = stub(ISO8601Duration, :year => 2)
+    default_value = stub(ISO8601Duration, :month => 3)
+    range = stub(Interval, :upper => assumed_value, :lower => default_value)
+    @c_duration = CDuration.new(:assumed_value => assumed_value,
+                                :default_value => default_value,
+                                :range => range,
+                                :years_allowed => true,
+                                :months_allowed => false,
+                                :weeks_allowed => true,
+                                :days_allowed => false,
+                                :hours_allowed => true,
+                                :minutes_allowed => false,
+                                :seconds_allowed => true,
+                                :fractional_seconds_allowed => false)
+  end
+
+  it 'should be an instance of CDuration' do
+    @c_duration.should be_an_instance_of CDuration
+  end
+
+  it 'years_allowed should be assigned properly' do
+    @c_duration.years_allowed.should be_true
+  end
+
+  it 'months_allowed should be assigned properly' do
+    @c_duration.months_allowed.should be_false
+  end
+
+  it 'weeks_allowed should be assigned properly' do
+    @c_duration.weeks_allowed.should be_true
+  end
+
+  it 'days_allowed should be assigned properly' do
+    @c_duration.days_allowed.should be_false
+  end
+
+  it 'hours_allowed should be assigned properly' do
+    @c_duration.hours_allowed.should be_true
+  end
+
+  it 'minutes_allowed should be assigned properly' do
+    @c_duration.minutes_allowed.should be_false
+  end
+
+  it 'seconds_allowed should be assigned properly' do
+    @c_duration.seconds_allowed.should be_true
+  end
+
+  it 'fractional_seconds_allowed should be assigned properly' do
+    @c_duration.fractional_seconds_allowed.should be_false
+  end
+
+  it 'should raise ArgumentError if range is nil and all parameters are not allowed' do
+    @c_duration.years_allowed = false
+    @c_duration.weeks_allowed = false
+    @c_duration.hours_allowed = false
+    @c_duration.seconds_allowed = false
+    lambda {
+      @c_duration.range = nil
+    }.should raise_error ArgumentError
+  end
+end
