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	2 Apr 2006 21:09:48 -0000
@@ -19,6 +19,7 @@
  * Copyright (C) 2004 Charles O Nutter <headius@headius.com>
  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
  * Copyright (C) 2006 Thomas E Enebo <enebo@acm.org>
+ * Copyright (C) 2006 Ola Bini <ola.bini@ki.se>
  * 
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
@@ -269,4 +270,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/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	2 Apr 2006 21:10:10 -0000
@@ -19,6 +19,7 @@
  * Copyright (C) 2004 Charles O Nutter <headius@headius.com>
  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
  * Copyright (C) 2006 Thomas E Enebo <enebo@acm.org>
+ * Copyright (C) 2006 Ola Bini <ola.bini@ki.se>
  * 
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
@@ -76,6 +77,7 @@
             defineSingletonMethod("mktime", Arity.optional(), "new_local"); 
             defineSingletonMethod("utc", Arity.optional(), "new_utc"); 
             defineSingletonMethod("gm", Arity.optional(), "new_utc"); 
+            defineSingletonMethod("_load", Arity.singleArgument(), "s_load"); 
                     
             // Missing getgm, getlocal, getutc (alias of getgm), gmt_offset, gmtoff (alias of
             // gmt_offset), utc_offset (alias of gmt_offset)
@@ -115,6 +117,7 @@
             defineMethod("localtime", Arity.noArguments()); 
             defineMethod("hash", Arity.noArguments()); 
             defineMethod("initialize_copy", Arity.singleArgument()); 
+            defineMethod("_dump", Arity.optional(),"dump"); 
         }
     };
     
@@ -169,6 +172,48 @@
     public RubyTime new_utc(IRubyObject[] args) {
         return createTime(args, true);
     }
+
+    public RubyTime s_load(final IRubyObject def) {
+        final RubyTime ext = (RubyTime)s_new();
+        return s_mload(ext,def);
+    }
+
+    protected RubyTime s_mload(final RubyTime time, final IRubyObject def) {
+        final Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.setTimeZone(TimeZone.getTimeZone(RubyTime.UTC));
+        byte[] str = null;
+        try {
+            str = def.toString().getBytes("iso8859-1");
+        } catch(final java.io.UnsupportedEncodingException uee) {
+            throw getRuntime().newTypeError("marshaled time format differ");
+        }
+        if(str.length != 8) {
+            throw getRuntime().newTypeError("marshaled time format differ");
+        }
+        int p=0;
+        int s=0;
+        for(int i=0;i<4;i++) {
+            p |= ((int)str[i] & 0xFF)<<(8*i);
+        }
+        for(int i=4;i<8;i++) {
+            s |= ((int)str[i] & 0xFF)<<(8*(i-4));
+        }
+        if((p & (1<<31)) == 0) {
+            cal.setTimeInMillis(p*1000L + s);
+        } else {
+            p &= ~(1<<31);
+            cal.set(Calendar.YEAR,((p >>> 14) & 0xFFFF)+1900);
+            cal.set(Calendar.MONTH,((p >>> 10) & 0xF));
+            cal.set(Calendar.DAY_OF_MONTH,((p >>> 5)  & 0x1F));
+            cal.set(Calendar.HOUR_OF_DAY,(p & 0x1F));
+            cal.set(Calendar.MINUTE,((s >>> 26) & 0x3F));
+            cal.set(Calendar.SECOND,((s >>> 20) & 0x3F));
+            cal.set(Calendar.MILLISECOND,(s & 0xFFFFF));
+        }
+        time.setJavaCalendar(cal);
+        return time;
+    }
     
     private static final String[] months = {"jan", "feb", "mar", "apr", "may", "jun",
                                             "jul", "aug", "sep", "oct", "nov", "dec"};
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	2 Apr 2006 21:09:57 -0000
@@ -16,6 +16,7 @@
  * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
  * Copyright (C) 2004 Charles O Nutter <headius@headius.com>
  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
+ * Copyright (C) 2006 Ola Bini <ola.bini@ki.se>
  * 
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
@@ -54,6 +55,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 +77,8 @@
         }
         if (! shouldBeRegistered(value)) {
             writeDirectly(value);
+        } else if (hasNewUserDefinedMarshaling(value)) {
+            userNewMarshal(value);
         } else if (hasUserDefinedMarshaling(value)) {
             userMarshal(value);
         } else {
@@ -115,14 +122,26 @@
         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(final IRubyObject value) throws IOException {
+        out.write(TYPE_USRMARSHAL);
+        dumpObject(RubySymbol.newSymbol(runtime, value.getMetaClass().getName()));
+
+        IRubyObject marshaled =  value.callMethod("marshal_dump"); 
+        dumpObject(marshaled);
+    }
+
     public void dumpString(String value) throws IOException {
         dumpInt(value.length());
         out.write(RubyString.stringToBytes(value));
Index: src/org/jruby/runtime/marshal/UnmarshalStream.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/runtime/marshal/UnmarshalStream.java,v
retrieving revision 1.15
diff -u -r1.15 UnmarshalStream.java
--- src/org/jruby/runtime/marshal/UnmarshalStream.java	26 Oct 2005 05:34:13 -0000	1.15
+++ src/org/jruby/runtime/marshal/UnmarshalStream.java	2 Apr 2006 21:10:01 -0000
@@ -16,6 +16,7 @@
  * Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
  * Copyright (C) 2004 Charles O Nutter <headius@headius.com>
  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
+ * Copyright (C) 2006 Ola Bini <ola.bini@ki.se>
  * 
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
@@ -134,6 +135,9 @@
             case 'u' :
                 rubyObj = userUnmarshal();
                 break;
+            case 'U' :
+                rubyObj = userNewUnmarshal();
+                break;
             default :
                 throw getRuntime().newArgumentError("dump format error(" + type + ")");
         }
@@ -230,4 +234,14 @@
         registerLinkTarget(result);
         return result;
     }
+
+    private IRubyObject userNewUnmarshal() throws IOException {
+        final String className = unmarshalObject().asSymbol();
+        final IRubyObject marshaled = unmarshalObject();
+        final RubyClass classInstance = runtime.getClass(className);
+        final IRubyObject result = classInstance.newInstance(new IRubyObject[0]);;
+        result.callMethod("marshal_load",marshaled);
+        registerLinkTarget(result);
+        return result;
+    }
 }
Index: test/testTime.rb
===================================================================
RCS file: /cvsroot/jruby/jruby/test/testTime.rb,v
retrieving revision 1.2
diff -u -r1.2 testTime.rb
--- test/testTime.rb	26 Mar 2006 21:21:40 -0000	1.2
+++ test/testTime.rb	2 Apr 2006 20:32:49 -0000
@@ -47,3 +47,6 @@
 
 # Time.utc can accept float values (by turning them into ints)
 test_no_exception { Time::utc(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0) }
+
+x1 = Marshal.load(Marshal.dump(t1))
+test_equal(true,t1==x1)
