Permalink
Browse files

Enable allocate class method for Date and DateTime

Also, change dup and clone to call super instead of using
DUPSETUP and CLONESETUP.  This makes dup and clone work
correctly on rubinius.  It also makes dup and clone work
correctly for Date on jruby, but not for DateTime due to
a bug in JRuby.

allocate is defined to use the julian day 0 for simplicity.
  • Loading branch information...
1 parent a0afad3 commit ba9a86ff668615d0b619b69ff861f4e740c6865a @jeremyevans committed Feb 28, 2011
Showing with 49 additions and 21 deletions.
  1. +2 −3 README.rdoc
  2. +25 −9 ext/date_ext/date_ext.c
  3. +17 −4 ext/date_ext/datetime.c
  4. +2 −2 spec/date/allocate_spec.rb
  5. +3 −3 spec/datetime/allocate_spec.rb
View
@@ -182,9 +182,8 @@ you use the standard library.
* DateTime offsets are stored in minutes, so it will round offsets
with fractional minutes to the nearest minute.
* All public class and instance methods for both Date and DateTime
- are implemented, except that the allocate class method is not
- available and on 1.9, _dump and _load are used instead of
- marshal_dump and marshal_load.
+ are implemented, except that on 1.9, _dump and _load are used
+ instead of marshal_dump and marshal_load.
* Only the public API is compatible, the private methods in the
standard library are not implemented.
* The marshalling format differs from the one used by the standard
View
@@ -1517,6 +1517,18 @@ static VALUE rhrd_s__strptime(int argc, VALUE *argv, VALUE klass) {
}
/* call-seq:
+ * allocate() -> Date <br />
+ *
+ * Returns a +Date+ object for julian day 0.
+ */
+static VALUE rhrd_s_allocate(VALUE klass) {
+ rhrd_t *d;
+ VALUE rd = Data_Make_Struct(klass, rhrd_t, NULL, -1, d);
+ d->flags = RHR_HAVE_JD;
+ return rd;
+}
+
+/* call-seq:
* civil() -> Date <br />
* civil(year, month=1, day=1, sg=nil) -> Date
*
@@ -2095,10 +2107,12 @@ static VALUE rhrd_asctime(VALUE self) {
*/
static VALUE rhrd_clone(VALUE self) {
rhrd_t *d, *nd;
- VALUE rd = Data_Make_Struct(rb_obj_class(self), rhrd_t, NULL, -1, nd);
- Data_Get_Struct(self, rhrd_t, d);
- memcpy(nd, d, sizeof(rhrd_t));
- CLONESETUP(rd, self);
+ VALUE rd = rb_call_super(0, NULL);
+ if (!rb_obj_is_kind_of(self, rhrdt_class)) {
+ Data_Get_Struct(self, rhrd_t, d);
+ Data_Get_Struct(rd, rhrd_t, nd);
+ memcpy(nd, d, sizeof(rhrd_t));
+ }
return rd;
}
@@ -2222,10 +2236,12 @@ static VALUE rhrd_downto(VALUE self, VALUE other) {
*/
static VALUE rhrd_dup(VALUE self) {
rhrd_t *d, *nd;
- VALUE rd = Data_Make_Struct(rb_obj_class(self), rhrd_t, NULL, -1, nd);
- Data_Get_Struct(self, rhrd_t, d);
- memcpy(nd, d, sizeof(rhrd_t));
- DUPSETUP(rd, self);
+ VALUE rd = rb_call_super(0, NULL);
+ if (!rb_obj_is_kind_of(self, rhrdt_class)) {
+ Data_Get_Struct(self, rhrd_t, d);
+ Data_Get_Struct(rd, rhrd_t, nd);
+ memcpy(nd, d, sizeof(rhrd_t));
+ }
return rd;
}
@@ -4065,7 +4081,7 @@ void Init_date_ext(void) {
/* Define classes*/
rhrd_class = rb_define_class("Date", rb_cObject);
- rb_undef_alloc_func(rhrd_class);
+ rb_define_alloc_func(rhrd_class, rhrd_s_allocate);
rhrd_s_class = rb_singleton_class(rhrd_class);
/* Define methods for all ruby versions */
View
@@ -580,6 +580,18 @@ static VALUE rhrdt_s__strptime(int argc, VALUE *argv, VALUE klass) {
}
/* call-seq:
+ * allocate() -> DateTime <br />
+ *
+ * Returns a +DateTime+ object for julian day 0.
+ */
+static VALUE rhrdt_s_allocate(VALUE klass) {
+ rhrdt_t *d;
+ VALUE rd = Data_Make_Struct(klass, rhrdt_t, NULL, -1, d);
+ d->flags = RHR_HAVE_JD | RHR_HAVE_NANOS;
+ return rd;
+}
+
+/* call-seq:
* civil() -> DateTime <br />
* civil(year, month=1, day=1, hour=0, minute=0, second=0, offset=0, sg=nil) -> DateTime
*
@@ -1007,10 +1019,10 @@ static VALUE rhrdt_asctime(VALUE self) {
*/
static VALUE rhrdt_clone(VALUE self) {
rhrdt_t *d, *nd;
- VALUE rd = Data_Make_Struct(rb_obj_class(self), rhrdt_t, NULL, -1, nd);
+ VALUE rd = rb_call_super(0, NULL);
Data_Get_Struct(self, rhrdt_t, d);
+ Data_Get_Struct(rd, rhrdt_t, nd);
memcpy(nd, d, sizeof(rhrdt_t));
- CLONESETUP(rd, self);
return rd;
}
@@ -1124,10 +1136,10 @@ static VALUE rhrdt_day_fraction(VALUE self) {
*/
static VALUE rhrdt_dup(VALUE self) {
rhrdt_t *d, *nd;
- VALUE rd = Data_Make_Struct(rb_obj_class(self), rhrdt_t, NULL, -1, nd);
+ VALUE rd = rb_call_super(0, NULL);
Data_Get_Struct(self, rhrdt_t, d);
+ Data_Get_Struct(rd, rhrdt_t, nd);
memcpy(nd, d, sizeof(rhrdt_t));
- DUPSETUP(rd, self);
return rd;
}
@@ -2769,6 +2781,7 @@ void Init_datetime(void) {
/* Define class */
rhrdt_class = rb_define_class("DateTime", rhrd_class);
+ rb_define_alloc_func(rhrdt_class, rhrdt_s_allocate);
rhrdt_s_class = rb_singleton_class(rhrdt_class);
/* Define methods for all ruby versions*/
@@ -1,7 +1,7 @@
require File.expand_path('../../spec_helper', __FILE__)
describe "Date.allocate" do
- it "should not be defined" do
- proc{Date.allocate}.should raise_error
+ it "should be the same as jd" do
+ Date.allocate.should == Date.jd
end
end
@@ -1,7 +1,7 @@
require File.expand_path('../../spec_helper', __FILE__)
-describe "Date.allocate" do
- it "should not be defined" do
- proc{DateTime.allocate}.should raise_error
+describe "DateTime.allocate" do
+ it "should be the same as jd" do
+ DateTime.allocate.should == DateTime.jd
end
end

0 comments on commit ba9a86f

Please sign in to comment.