Browse Source

Incremental work on Date

Sebastien Ros 12 years ago
parent
commit
4951a81228

+ 59 - 12
Jint/Native/Date/DateConstructor.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Globalization;
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
@@ -9,6 +10,12 @@ namespace Jint.Native.Date
     public sealed class DateConstructor : FunctionInstance, IConstructor
     {
         private static readonly DateTime Origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+        private const long MsPerSecond = 1000;
+        private const long MsPerMinute = MsPerSecond * 60;
+        private const long MsPerHour = MsPerMinute * 60;
+        private const long MsPerDay = MsPerHour * 24;
+
+
 
         public DateConstructor(Engine engine) : base(engine, null, null, false)
         {
@@ -33,29 +40,39 @@ namespace Jint.Native.Date
 
         public void Configure()
         {
-            FastAddProperty("parse", new ClrFunctionInstance<object, object>(Engine, Parse, 0), true, false, true);
-            FastAddProperty("UTC", new ClrFunctionInstance<object, object>(Engine, Utc, 0), true, false, true);
+            FastAddProperty("parse", new ClrFunctionInstance<object, object>(Engine, Parse, 1), true, false, true);
+            FastAddProperty("UTC", new ClrFunctionInstance<object, object>(Engine, Utc, 7), true, false, true);
             FastAddProperty("now", new ClrFunctionInstance<object, object>(Engine, Now, 0), true, false, true);
         }
 
         private object Parse(object thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            DateTime result;
+            var date = TypeConverter.ToString(arguments.At(0));
+
+
+            if (!DateTime.TryParseExact(date, new[] { "yyyy-MM-ddTH:m:s.fffK", "yyyy-MM-dd", "yyyy-MM", "yyyy", "THH:m:s.fff", "TH:mm:sm", "THH:mm", "THH" }, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out result))
+            {
+                throw new JavaScriptException(Engine.SyntaxError, "Invalid date");
+            }
+
+            return Construct(result);
         }
 
         private object Utc(object thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var local = (DateInstance) Construct(arguments);
+            return local.PrimitiveValue;
         }
 
         private object Now(object thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            return (DateTime.UtcNow - Origin).TotalMilliseconds;
         }
 
         public override object Call(object thisObject, object[] arguments)
         {
-            return Construct(arguments);
+            return PrototypeObject.ToString((DateInstance) Construct(Arguments.Empty), Arguments.Empty);
         }
 
         /// <summary>
@@ -74,8 +91,7 @@ namespace Jint.Native.Date
                 var v = TypeConverter.ToPrimitive(arguments[0]);
                 if (TypeConverter.GetType(v) == Types.String)
                 {
-                    var d = DateTime.Parse(TypeConverter.ToString(v));
-                    return Construct(d);
+                    return (ObjectInstance) Parse(Undefined.Instance, Arguments.From(v));
                 }
 
                 return Construct(TypeConverter.ToNumber(v));
@@ -90,12 +106,38 @@ namespace Jint.Native.Date
                 var seconds = arguments.Length > 5 ? (int)TypeConverter.ToInteger(arguments[5]) : 0;
                 var ms = arguments.Length > 6 ? (int)TypeConverter.ToInteger(arguments[6]) : 0;
 
+                for (int i = 2; i < arguments.Length; i++)
+                {
+                    if (double.IsNaN(TypeConverter.ToNumber(arguments[i])))
+                    {
+                        return Construct(double.NaN);
+                    }
+                }
+
                 if ((!double.IsNaN(y)) && (0 <= TypeConverter.ToInteger(y)) && (TypeConverter.ToInteger(y) <= 99))
                 {
                     y += 1900;
                 }
 
-                return Construct(new DateTime((int) y, m + 1, date, hours, minutes, seconds, ms, DateTimeKind.Utc));
+                var ym = y + System.Math.Floor(m / 12);
+                var mn = m % 12;
+
+                try
+                {
+                    var dt = new DateTime((int) ym, mn + 1, 1, 0, 0, 0, 0, DateTimeKind.Local);
+                    var primitiveValue = FromDateTime(dt)
+                                         + ms
+                                         + seconds*MsPerSecond
+                                         + minutes*MsPerMinute
+                                         + hours*MsPerHour
+                                         + date*MsPerDay;
+
+                    return Construct(primitiveValue);
+                }
+                catch(ArgumentOutOfRangeException)
+                {
+                    throw new JavaScriptException(Engine.RangeError);
+                }
             }
         }
 
@@ -106,7 +148,7 @@ namespace Jint.Native.Date
             var instance = new DateInstance(Engine)
                 {
                     Prototype = PrototypeObject,
-                    PrimitiveValue = (value - Origin).TotalMilliseconds,
+                    PrimitiveValue = FromDateTime(value),
                     Extensible = true
                 };
 
@@ -125,7 +167,7 @@ namespace Jint.Native.Date
             return instance;
         }
 
-        public double TimeClip(double time)
+        public static double TimeClip(double time)
         {
             if (double.IsInfinity(time) || double.IsNaN(time))
             {
@@ -135,9 +177,14 @@ namespace Jint.Native.Date
             if (System.Math.Abs(time) > 8640000000000000)
             {
                 return double.NaN;
-            }
+            } 
 
             return TypeConverter.ToInteger(time);
         }
+
+        public static double FromDateTime(DateTime dt)
+        {
+            return (dt.ToUniversalTime() - Origin).TotalMilliseconds;
+        }
     }
 }

+ 107 - 43
Jint/Native/Date/DatePrototype.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Globalization;
+using Jint.Runtime;
 using Jint.Runtime.Interop;
 
 namespace Jint.Native.Date
@@ -20,7 +21,7 @@ namespace Jint.Native.Date
             obj.Prototype = engine.Object.PrototypeObject;
             obj.Extensible = true;
 
-            obj.FastAddProperty("constructor", dateConstructor, false, false, false);
+            obj.FastAddProperty("constructor", dateConstructor, true, false, true);
 
             return obj;
         }
@@ -52,23 +53,24 @@ namespace Jint.Native.Date
             FastAddProperty("getMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, GetMilliseconds, 0), true, false, true);
             FastAddProperty("getUTCMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCMilliseconds, 0), true, false, true);
             FastAddProperty("getTimezoneOffset", new ClrFunctionInstance<DateInstance, double>(Engine, GetTimezoneOffset, 0), true, false, true);
-            FastAddProperty("setTime", new ClrFunctionInstance<DateInstance, double>(Engine, SetTime, 0), true, false, true);
-            FastAddProperty("setMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetMilliseconds, 0), true, false, true);
-            FastAddProperty("setSeconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetSeconds, 0), true, false, true);
-            FastAddProperty("setUTCSeconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCSeconds, 0), true, false, true);
-            FastAddProperty("setMinutes", new ClrFunctionInstance<DateInstance, double>(Engine, SetMinutes, 0), true, false, true);
-            FastAddProperty("setUTCMinutes", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCMinutes, 0), true, false, true);
-            FastAddProperty("setHours", new ClrFunctionInstance<DateInstance, double>(Engine, SetHours, 0), true, false, true);
-            FastAddProperty("setUTCHours", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCHours, 0), true, false, true);
-            FastAddProperty("setDate", new ClrFunctionInstance<DateInstance, double>(Engine, SetDate, 0), true, false, true);
-            FastAddProperty("setUTCDate", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCDate, 0), true, false, true);
-            FastAddProperty("setMonth", new ClrFunctionInstance<DateInstance, double>(Engine, SetMonth, 0), true, false, true);
-            FastAddProperty("setUTCMonth", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCMonth, 0), true, false, true);
-            FastAddProperty("setFullYear", new ClrFunctionInstance<DateInstance, double>(Engine, SetFullYear, 0), true, false, true);
-            FastAddProperty("setUTCFullYear", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCFullYear, 0), true, false, true);
+            FastAddProperty("setTime", new ClrFunctionInstance<DateInstance, double>(Engine, SetTime, 1), true, false, true);
+            FastAddProperty("setMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetMilliseconds, 1), true, false, true);
+            FastAddProperty("setUTCMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCMilliseconds, 1), true, false, true);
+            FastAddProperty("setSeconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetSeconds, 2), true, false, true);
+            FastAddProperty("setUTCSeconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCSeconds, 2), true, false, true);
+            FastAddProperty("setMinutes", new ClrFunctionInstance<DateInstance, double>(Engine, SetMinutes, 3), true, false, true);
+            FastAddProperty("setUTCMinutes", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCMinutes, 3), true, false, true);
+            FastAddProperty("setHours", new ClrFunctionInstance<DateInstance, double>(Engine, SetHours, 4), true, false, true);
+            FastAddProperty("setUTCHours", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCHours, 4), true, false, true);
+            FastAddProperty("setDate", new ClrFunctionInstance<DateInstance, double>(Engine, SetDate, 1), true, false, true);
+            FastAddProperty("setUTCDate", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCDate, 1), true, false, true);
+            FastAddProperty("setMonth", new ClrFunctionInstance<DateInstance, double>(Engine, SetMonth, 2), true, false, true);
+            FastAddProperty("setUTCMonth", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCMonth, 2), true, false, true);
+            FastAddProperty("setFullYear", new ClrFunctionInstance<DateInstance, double>(Engine, SetFullYear, 3), true, false, true);
+            FastAddProperty("setUTCFullYear", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCFullYear, 3), true, false, true);
             FastAddProperty("toUTCString", new ClrFunctionInstance<DateInstance, string>(Engine, ToUTCString, 0), true, false, true);
             FastAddProperty("toISOString", new ClrFunctionInstance<DateInstance, string>(Engine, ToISOString, 0), true, false, true);
-            FastAddProperty("toJSON", new ClrFunctionInstance<DateInstance, string>(Engine, ToJSON, 0), true, false, true);
+            FastAddProperty("toJSON", new ClrFunctionInstance<DateInstance, string>(Engine, ToJSON, 1), true, false, true);
         }
 
         private double ValueOf(DateInstance thisObj, object[] arguments)
@@ -76,7 +78,7 @@ namespace Jint.Native.Date
             return thisObj.PrimitiveValue;
         }
 
-        private string ToString(DateInstance thisObj, object[] arg2)
+        public string ToString(DateInstance thisObj, object[] arg2)
         {
             return thisObj.ToDateTime().ToString("F", CultureInfo.InvariantCulture);
         }
@@ -123,7 +125,7 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().Year;
+            return thisObj.ToDateTime().ToLocalTime().Year;
         }
 
         private double GetUTCFullYear(DateInstance thisObj, object[] arguments)
@@ -143,7 +145,7 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().Month - 1;
+            return thisObj.ToDateTime().ToLocalTime().Month - 1;
         }
 
         private double GetUTCMonth(DateInstance thisObj, object[] arguments)
@@ -163,7 +165,7 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().Day;
+            return thisObj.ToDateTime().ToLocalTime().Day;
         }
 
         private double GetUTCDate(DateInstance thisObj, object[] arguments)
@@ -183,7 +185,7 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return (int)thisObj.ToDateTime().DayOfWeek;
+            return (int)thisObj.ToDateTime().ToLocalTime().DayOfWeek;
         }
 
         private double GetUTCDay(DateInstance thisObj, object[] arguments)
@@ -203,7 +205,7 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().Hour;
+            return thisObj.ToDateTime().ToLocalTime().Hour;
         }
 
         private double GetUTCHours(DateInstance thisObj, object[] arguments)
@@ -223,7 +225,7 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().Minute;
+            return thisObj.ToDateTime().ToLocalTime().Minute;
         }
 
         private double GetUTCMinutes(DateInstance thisObj, object[] arguments)
@@ -243,7 +245,7 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().Second;
+            return thisObj.ToDateTime().ToLocalTime().Second;
         }
 
         private double GetUTCSeconds(DateInstance thisObj, object[] arguments)
@@ -263,7 +265,7 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().Millisecond;
+            return thisObj.ToDateTime().ToLocalTime().Millisecond;
         }
 
         private double GetUTCMilliseconds(DateInstance thisObj, object[] arguments)
@@ -283,81 +285,143 @@ namespace Jint.Native.Date
                 return double.NaN;
             }
 
-            return TimeZoneInfo.Local.GetUtcOffset(thisObj.ToDateTime()).Hours;
+            return - TimeZoneInfo.Local.GetUtcOffset(thisObj.ToDateTime()).Hours*60;
         }
 
         private double SetTime(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            return thisObj.PrimitiveValue = DateConstructor.TimeClip(TypeConverter.ToNumber(arguments.At(0)));
         }
 
         private double SetMilliseconds(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour,dt.Minute,dt.Second,(int)TypeConverter.ToNumber(arguments.At(0)), DateTimeKind.Local);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+        }
+
+        private double SetUTCMilliseconds(DateInstance thisObj, object[] arguments)
+        {
+            var dt = thisObj.ToDateTime().ToUniversalTime();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)TypeConverter.ToNumber(arguments.At(0)), DateTimeKind.Utc);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetSeconds(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToLocalTime();
+            var ms = arguments.At(1) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(1));
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, (int)TypeConverter.ToNumber(arguments.At(0)), (int) ms, DateTimeKind.Local);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetUTCSeconds(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToUniversalTime();
+            var ms = arguments.At(1) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(1));
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, (int)TypeConverter.ToNumber(arguments.At(0)), (int) ms, DateTimeKind.Utc);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetMinutes(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToLocalTime();
+            var s = arguments.At(1) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(1));
+            var ms = arguments.At(2) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(2));
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, (int)TypeConverter.ToNumber(arguments.At(0)), (int) s, (int) ms, DateTimeKind.Local);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetUTCMinutes(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToUniversalTime();
+            var s = arguments.At(1) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(1));
+            var ms = arguments.At(2) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(2));
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, (int)TypeConverter.ToNumber(arguments.At(0)), (int)s, (int)ms, DateTimeKind.Utc);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetHours(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToLocalTime();
+            var min = arguments.At(1) == Undefined.Instance ? dt.Minute : TypeConverter.ToNumber(arguments.At(1));
+            var s = arguments.At(2) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(2));
+            var ms = arguments.At(3) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(3));
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, (int)TypeConverter.ToNumber(arguments.At(0)), (int) min, (int)s, (int)ms, DateTimeKind.Local);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetUTCHours(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToUniversalTime();
+            var min = arguments.At(1) == Undefined.Instance ? dt.Minute : TypeConverter.ToNumber(arguments.At(1));
+            var s = arguments.At(2) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(2));
+            var ms = arguments.At(3) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(3));
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, (int)TypeConverter.ToNumber(arguments.At(0)), (int)min, (int)s, (int)ms, DateTimeKind.Utc);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetDate(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToLocalTime();
+            dt = new DateTime(dt.Year, dt.Month, (int)TypeConverter.ToNumber(arguments.At(0)), dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetUTCDate(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToUniversalTime();
+            dt = new DateTime(dt.Year, dt.Month, (int)TypeConverter.ToNumber(arguments.At(0)), dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetMonth(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToUniversalTime();
+            var date = arguments.At(1) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(1));
+            dt = new DateTime(dt.Year, (int)TypeConverter.ToNumber(arguments.At(0)), (int) date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetUTCMonth(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToUniversalTime();
+            var date = arguments.At(1) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(1));
+            dt = new DateTime(dt.Year, (int)TypeConverter.ToNumber(arguments.At(0)), (int) date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetFullYear(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToLocalTime();
+            var month = arguments.At(1) == Undefined.Instance ? dt.Month : TypeConverter.ToNumber(arguments.At(1));
+            var date = arguments.At(2) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(2));
+            dt = new DateTime((int)TypeConverter.ToNumber(arguments.At(0)), (int)month, (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
         private double SetUTCFullYear(DateInstance thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
+            var dt = thisObj.ToDateTime().ToUniversalTime();
+            var month = arguments.At(1) == Undefined.Instance ? dt.Month : TypeConverter.ToNumber(arguments.At(1));
+            var date = arguments.At(2) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(2));
+            dt = new DateTime((int)TypeConverter.ToNumber(arguments.At(0)), (int)month,(int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
+            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+        }
+
+        private string ToUTCString(DateInstance thisObj, object[] arguments)
+        {
+            return thisObj.ToDateTime().ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
         }
 
-        private string ToUTCString(DateInstance thisObj, object[] arguments) { throw new NotImplementedException(); }
-        private string ToISOString(DateInstance thisObj, object[] arguments) { throw new NotImplementedException(); }
-        private string ToJSON(DateInstance thisObj, object[] arguments) { throw new NotImplementedException(); }
+        private string ToISOString(DateInstance thisObj, object[] arguments)
+        {
+            return thisObj.ToDateTime().ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
+        }
+
+        private string ToJSON(DateInstance thisObj, object[] arguments)
+        {
+            return thisObj.ToDateTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
+        }
     }
 }

+ 9 - 2
Jint/Runtime/Interop/ClrFunctionInstance.cs

@@ -25,8 +25,15 @@ namespace Jint.Runtime.Interop
 
         public override object Call(object thisObject, object[] arguments)
         {
-            var result = _func((TObject) thisObject, arguments);
-            return result;
+            try
+            {
+                var result = _func((TObject) thisObject, arguments);
+                return result;
+            }
+            catch (InvalidCastException)
+            {
+                throw new JavaScriptException(Engine.TypeError);
+            }
         }
     }
 }