<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -7,6 +7,7 @@
 
 #include &lt;math.h&gt;
 #include &lt;ruby.h&gt;
+#include &lt;time.h&gt;
 
 #define FLOOR(a) lrintf(floorf(a))
 #define FLOAT(a) (float)a
@@ -187,18 +188,37 @@ rb_date_new(int argc, VALUE * argv, VALUE self) {
       m    = (argc &gt; 1 ? NUM2INT(argv[1]) : 1),
       d    = (argc &gt; 2 ? NUM2INT(argv[2]) : 1);
   VALUE sg = (argc &gt; 3 ? argv[3] : ITALY);
-  int jd = civil_to_jd(y, m, d, sg);
+  int jd = -1;
   struct mini_tm t;
-  jd_to_civil(jd, sg, &amp;t);
-  if ( t.y != y || t.m != m || t.d != d ) {
-    rb_raise(rb_eArgError, &quot;Invalid date: (%d, %d, %d)&quot;, y, m, d);
-    return Qnil;
-  }else{
-    VALUE ajd = jd_to_ajd(jd, INT2FIX(0), INT2FIX(0));
-    VALUE date = rb_funcall(self, id_new_bang, 3, ajd, INT2FIX(0), sg);
-    rb_ivar_set(date, id_ivar_civil, rb_ary_new3(3, INT2FIX(t.y), INT2FIX(t.m), INT2FIX(t.d)));
-    return date;
+  if (d &lt; 0) {
+    int ny = (y * 12 + m) / 12;
+    int nm = (y * 12 + m) % 12;
+    nm = (nm + 1) / 1;
+    jd = civil_to_jd(ny, nm, d+1, sg);
+
+    VALUE ns = jd &lt; 2299161 ? JULIAN : GREGORIAN;
+    jd_to_civil(jd-d, ns, &amp;t);
+    if ( t.y != ny || t.m != nm || t.d != 1 ) {
+      rb_raise(rb_eArgError, &quot;Invalid date: (%d, %d, %d)&quot;, y, m, d);
+      return Qnil;
+    }
+    jd_to_civil(jd, sg, &amp;t);
+    if ( t.y != y || t.m != m ) {
+      rb_raise(rb_eArgError, &quot;Invalid date: (%d, %d, %d)&quot;, y, m, d);
+      return Qnil;
+    }
+  } else {
+    jd = civil_to_jd(y, m, d, sg);
+    jd_to_civil(jd, sg, &amp;t);
+    if ( t.y != y || t.m != m || t.d != d ) {
+      rb_raise(rb_eArgError, &quot;Invalid date: (%d, %d, %d)&quot;, y, m, d);
+      return Qnil;
+    }
   }
+  VALUE ajd = jd_to_ajd(jd, INT2FIX(0), INT2FIX(0));
+  VALUE date = rb_funcall(self, id_new_bang, 3, ajd, INT2FIX(0), sg);
+  rb_ivar_set(date, id_ivar_civil, rb_ary_new3(3, INT2FIX(t.y), INT2FIX(t.m), INT2FIX(t.d)));
+  return date;
 }
 
 </diff>
      <filename>ext/date_performance.c</filename>
    </modified>
    <modified>
      <diff>@@ -96,4 +96,25 @@ class ExtensionTest &lt; Test::Unit::TestCase
     assert_equal &quot;2007-01-01T04:20:00+00:00&quot;, dt.strftime(&quot;%FT%T%:z&quot;)
   end
 
+  def test_constructor_with_negative_days
+    #leap year
+    month_ends = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+    (1..12).each do |m|
+      d = Date.new(2008, m, -1)
+      assert_equal d.day, month_ends[m-1]
+    end
+    #normal year
+    month_ends = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+    (1..12).each do |m|
+      d = Date.new(2009, m, -1)
+      assert_equal d.day, month_ends[m-1]
+    end
+    #before calendar reform for Italy
+    month_ends = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+    (1..12).each do |m|
+      d = Date.new(1581, m, -1)
+      assert_equal d.day, month_ends[m-1]
+    end
+  end
+
 end</diff>
      <filename>test/extension_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>4872381152285ac388b9a0ed32b7252090d6402f</id>
    </parent>
  </parents>
  <author>
    <name>Alexander Dymo</name>
    <email>gremlin@venus.site</email>
  </author>
  <url>http://github.com/rtomayko/date-performance/commit/8203c325cf47516b275daab0a6770005f1248a05</url>
  <id>8203c325cf47516b275daab0a6770005f1248a05</id>
  <committed-date>2008-07-12T08:06:49-07:00</committed-date>
  <authored-date>2008-07-12T08:05:25-07:00</authored-date>
  <message>Implemented support for negative number of days as constructor arguments.

For example, Date.civil(2008, 7, -1) will construct &quot;2008-7-31&quot; date.</message>
  <tree>f7b389192f4eb74de9891d93cc6bd16951ab56e8</tree>
  <committer>
    <name>Ryan Tomayko</name>
    <email>rtomayko@gmail.com</email>
  </committer>
</commit>
