Browse Source

Date should honor the timezone rules for daylight savings

Eric Amodio 9 years ago
parent
commit
87a59a7f30
2 changed files with 37 additions and 17 deletions
  1. 18 0
      Jint.Tests/Runtime/EngineTests.cs
  2. 19 17
      Jint/Native/Date/DatePrototype.cs

+ 18 - 0
Jint.Tests/Runtime/EngineTests.cs

@@ -1575,6 +1575,24 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void DateShouldHonorTimezoneDaylightSavingRules()
+        {
+            var EST = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time");
+            var engine = new Engine(options => options.LocalTimeZone(EST))
+                .SetValue("log", new Action<object>(Console.WriteLine))
+                .SetValue("assert", new Action<bool>(Assert.True))
+                .SetValue("equal", new Action<object, object>(Assert.Equal))
+                ;
+
+            engine.Execute(@"
+                    var d = new Date(2016, 8, 1);
+
+                    equal('Thu Sep 01 2016 00:00:00 GMT-04:00', d.toString());
+                    equal('Thu Sep 01 2016', d.toDateString());
+            ");
+        }
+
         [Fact]
         public void DateShouldParseToString()
         {

+ 19 - 17
Jint/Native/Date/DatePrototype.cs

@@ -19,7 +19,7 @@ namespace Jint.Native.Date
         {
             var obj = new DatePrototype(engine)
             {
-                Prototype = engine.Object.PrototypeObject, 
+                Prototype = engine.Object.PrototypeObject,
                 Extensible = true,
                 PrimitiveValue = double.NaN
             };
@@ -360,7 +360,7 @@ namespace Jint.Native.Date
         {
             var t = LocalTime(EnsureDateInstance(thisObj).PrimitiveValue);
             var s = TypeConverter.ToNumber(arguments.At(0));
-            var milli = arguments.Length <= 1 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(1)); 
+            var milli = arguments.Length <= 1 ? MsFromTime(t) : TypeConverter.ToNumber(arguments.At(1));
             var date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
             var u = TimeClip(Utc(date));
             thisObj.As<DateInstance>().PrimitiveValue = u;
@@ -540,7 +540,7 @@ namespace Jint.Native.Date
                 throw new JavaScriptException(Engine.RangeError);
             }
 
-            return string.Format("{0:0000}-{1:00}-{2:00}T{3:00}:{4:00}:{5:00}.{6:000}Z", 
+            return string.Format("{0:0000}-{1:00}-{2:00}T{3:00}:{4:00}:{5:00}.{6:000}Z",
                 YearFromTime(t),
                 MonthFromTime(t)+1,
                 DateFromTime(t),
@@ -625,9 +625,9 @@ namespace Jint.Native.Date
         /// </summary>
         public static double DayFromYear(double y)
         {
-            return 365*(y - 1970) 
-                + System.Math.Floor((y - 1969)/4) 
-                - System.Math.Floor((y - 1901)/100) 
+            return 365*(y - 1970)
+                + System.Math.Floor((y - 1969)/4)
+                - System.Math.Floor((y - 1901)/100)
                 + System.Math.Floor((y - 1601)/400);
         }
 
@@ -661,7 +661,7 @@ namespace Jint.Native.Date
                 {
                     lower = current;
                 }
-                else 
+                else
                 {
                     upper = current;
                 }
@@ -680,12 +680,12 @@ namespace Jint.Native.Date
             if (daysInYear.Equals(365))
             {
                 return 0;
-            }            
+            }
 
             if (daysInYear.Equals(366))
             {
                 return 1;
-            }            
+            }
 
             throw new ArgumentException();
         }
@@ -878,13 +878,15 @@ namespace Jint.Native.Date
 
         public DateTimeOffset ToLocalTime(DateTime t)
         {
-            if (t.Kind == DateTimeKind.Unspecified)
+            switch (t.Kind)
             {
-                return t;
+                case DateTimeKind.Local:
+                    return new DateTimeOffset(TimeZoneInfo.ConvertTime(t.ToUniversalTime(), Engine.Options._LocalTimeZone), Engine.Options._LocalTimeZone.GetUtcOffset(t));
+                case DateTimeKind.Utc:
+                    return new DateTimeOffset(TimeZoneInfo.ConvertTime(t, Engine.Options._LocalTimeZone), Engine.Options._LocalTimeZone.GetUtcOffset(t));
+                default:
+                    return t;
             }
-
-            var offset = Engine.Options._LocalTimeZone.BaseUtcOffset;
-            return new DateTimeOffset(t.Ticks + offset.Ticks, offset);
         }
 
         public double LocalTime(double t)
@@ -949,7 +951,7 @@ namespace Jint.Native.Date
 
             switch ((long) month)
             {
-                case 0: 
+                case 0:
                 case 2:
                 case 4:
                 case 6:
@@ -965,7 +967,7 @@ namespace Jint.Native.Date
                 case 1:
                     return 28 + leap;
                 default:
-                    throw new ArgumentOutOfRangeException("month"); 
+                    throw new ArgumentOutOfRangeException("month");
 
             }
         }
@@ -1020,7 +1022,7 @@ namespace Jint.Native.Date
             {
                 t += DaysInMonth(m, InLeapYear(t)) * MsPerDay;
             }
-            
+
             return Day(t) + date - 1;
         }