Hi.

This patch creates a _dump-method for Time that matches what Ruby 1.8 creates. The code is created by looking at time.c in the Ruby distro. I have also added some methods to support marshal_dump later on. What's missing is a correct implementation of _load in Time, but that will come soon too.

Regards
 Ola Bini
Index: src/org/jruby/RubyTime.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyTime.java,v
retrieving revision 1.18
diff -u -r1.18 RubyTime.java
--- src/org/jruby/RubyTime.java 26 Mar 2006 21:21:40 -0000      1.18
+++ src/org/jruby/RubyTime.java 31 Mar 2006 12:45:46 -0000
@@ -269,4 +269,38 @@
        // modified to match how hash is calculated in 1.8.2
         return getRuntime().newFixnum((int)(((cal.getTimeInMillis() / 1000) ^ 
microseconds()) << 1) >> 1);
     }    
+
+    public RubyString dump(final IRubyObject[] args) {
+        if (args.length > 1) {
+            throw getRuntime().newArgumentError(0, 1);
+        }
+        final RubyFixnum limit = (args.length == 
0)?RubyFixnum.minus_one(getRuntime()):(RubyFixnum)args[0];
+        return (RubyString)mdump(new IRubyObject[] {this});
+    }    
+
+    public RubyObject mdump(final IRubyObject[] args) {
+        final RubyTime obj = (RubyTime)args[0];
+        final Calendar cel = obj.gmtime().cal;
+        final byte buf[] = new byte[8];
+        int pe = 
+            0x1                                << 31 |
+            (cel.get(Calendar.YEAR)-1900)      << 14 |
+            cel.get(Calendar.MONTH)            << 10 |
+            cel.get(Calendar.DAY_OF_MONTH)     << 5  |
+            cel.get(Calendar.HOUR_OF_DAY);
+        
+        int se =
+            cel.get(Calendar.MINUTE)           << 26 |
+            cel.get(Calendar.SECOND)           << 20 |
+            cel.get(Calendar.MILLISECOND);
+        for(int i=0;i<4;i++) {
+            buf[i] = (byte)(pe & 0xFF);
+            pe >>= 8;
+        }
+        for(int i=4;i<8;i++) {
+            buf[i] = (byte)(se & 0xFF);
+            se >>= 8;
+        }
+        return RubyString.newString(obj.getRuntime(),buf);
+    }
 }
Index: src/org/jruby/runtime/marshal/MarshalStream.java
===================================================================
RCS file: 
/cvsroot/jruby/jruby/src/org/jruby/runtime/marshal/MarshalStream.java,v
retrieving revision 1.13
diff -u -r1.13 MarshalStream.java
--- src/org/jruby/runtime/marshal/MarshalStream.java    26 Oct 2005 05:34:13 
-0000      1.13
+++ src/org/jruby/runtime/marshal/MarshalStream.java    31 Mar 2006 10:21:42 
-0000
@@ -54,6 +54,10 @@
     private int depth = 0;
     private MarshalCache cache;
 
+    private final static char TYPE_USRMARSHAL = 'U';
+    private final static char TYPE_USERDEF = 'u';
+
+
     public MarshalStream(IRuby runtime, OutputStream out, int depthLimit) 
throws IOException {
         super(out);
 
@@ -72,6 +76,8 @@
         }
         if (! shouldBeRegistered(value)) {
             writeDirectly(value);
+        } else if (hasNewUserDefinedMarshaling(value)) {
+            userNewMarshal(value);
         } else if (hasUserDefinedMarshaling(value)) {
             userMarshal(value);
         } else {
@@ -115,14 +121,22 @@
         return value.respondsTo("_dump");
     }
 
+    private boolean hasNewUserDefinedMarshaling(IRubyObject value) {
+        return value.respondsTo("marshal_dump");
+    }
+
     private void userMarshal(IRubyObject value) throws IOException {
-        out.write('u');
+        out.write(TYPE_USERDEF);
         dumpObject(RubySymbol.newSymbol(runtime, 
value.getMetaClass().getName()));
 
         RubyString marshaled = (RubyString) value.callMethod("_dump", 
runtime.newFixnum(depthLimit)); 
         dumpString(marshaled.getValue());
     }
 
+    private void userNewMarshal(IRubyObject value) throws IOException {
+        out.write(TYPE_USRMARSHAL);
+    }
+
     public void dumpString(String value) throws IOException {
         dumpInt(value.length());
         out.write(RubyString.stringToBytes(value));
Index: src/org/jruby/runtime/builtin/meta/TimeMetaClass.java
===================================================================
RCS file: 
/cvsroot/jruby/jruby/src/org/jruby/runtime/builtin/meta/TimeMetaClass.java,v
retrieving revision 1.2
diff -u -r1.2 TimeMetaClass.java
--- src/org/jruby/runtime/builtin/meta/TimeMetaClass.java       26 Mar 2006 
21:21:40 -0000      1.2
+++ src/org/jruby/runtime/builtin/meta/TimeMetaClass.java       31 Mar 2006 
11:04:13 -0000
@@ -76,6 +76,7 @@
             defineSingletonMethod("mktime", Arity.optional(), "new_local"); 
             defineSingletonMethod("utc", Arity.optional(), "new_utc"); 
             defineSingletonMethod("gm", Arity.optional(), "new_utc"); 
+            defineSingletonMethod("_load", Arity.optional(), "s_load"); 
                     
             // Missing getgm, getlocal, getutc (alias of getgm), gmt_offset, 
gmtoff (alias of
             // gmt_offset), utc_offset (alias of gmt_offset)
@@ -115,6 +116,7 @@
             defineMethod("localtime", Arity.noArguments()); 
             defineMethod("hash", Arity.noArguments()); 
             defineMethod("initialize_copy", Arity.singleArgument()); 
+            defineMethod("_dump", Arity.optional(),"dump"); 
         }
     };
     
@@ -169,6 +171,10 @@
     public RubyTime new_utc(IRubyObject[] args) {
         return createTime(args, true);
     }
+
+    public RubyTime s_load(IRubyObject[] args) {
+        return null;
+    }
     
     private static final String[] months = {"jan", "feb", "mar", "apr", "may", 
"jun",
                                             "jul", "aug", "sep", "oct", "nov", 
"dec"};

Reply via email to