Browse Source

Support configuring kind of JsDate produced DateTime (#1481)

Marko Lahma 2 years ago
parent
commit
657584860d
3 changed files with 41 additions and 3 deletions
  1. 28 2
      Jint.Tests/Runtime/InteropTests.cs
  2. 7 1
      Jint/Native/JsDate.cs
  3. 6 0
      Jint/Options.cs

+ 28 - 2
Jint.Tests/Runtime/InteropTests.cs

@@ -1105,10 +1105,36 @@ namespace Jint.Tests.Runtime
         public void ShouldConvertDateInstanceToDateTime()
         public void ShouldConvertDateInstanceToDateTime()
         {
         {
             var result = _engine.Evaluate("new Date(0)");
             var result = _engine.Evaluate("new Date(0)");
-            var value = result.ToObject();
+            var value = result.ToObject() is DateTime ? (DateTime) result.ToObject() : default;
 
 
-            Assert.Equal(typeof(DateTime), value.GetType());
             Assert.Equal(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), value);
             Assert.Equal(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), value);
+            Assert.Equal(DateTimeKind.Utc, value.Kind);
+        }
+
+        [Fact]
+        public void ShouldConvertDateInstanceToLocalDateTime()
+        {
+            TimeZoneInfo timeZone;
+            try
+            {
+                timeZone = TimeZoneInfo.FindSystemTimeZoneById("Europe/Helsinki");
+            }
+            catch (TimeZoneNotFoundException)
+            {
+                timeZone = TimeZoneInfo.FindSystemTimeZoneById("FLE Standard Time");
+            }
+
+            var engine = new Engine(options =>
+            {
+                options.TimeZone = timeZone;
+                options.Interop.DateTimeKind = DateTimeKind.Local;
+            });
+
+            var result = engine.Evaluate("new Date(0)");
+            var value = result.ToObject() is DateTime ? (DateTime) result.ToObject() : default;
+
+            Assert.Equal(new DateTime(1970, 1, 1, 2, 0, 0, DateTimeKind.Local), value);
+            Assert.Equal(DateTimeKind.Local, value.Kind);
         }
         }
 
 
         [Fact]
         [Fact]

+ 7 - 1
Jint/Native/JsDate.cs

@@ -54,7 +54,13 @@ public sealed class JsDate : ObjectInstance
 
 
         if (_dateValue.DateTimeRangeValid)
         if (_dateValue.DateTimeRangeValid)
         {
         {
-            return DateConstructor.Epoch.AddMilliseconds(_dateValue.Value);
+            var dateTime = DateConstructor.Epoch.AddMilliseconds(_dateValue.Value);
+            if (_engine.Options.Interop.DateTimeKind == DateTimeKind.Local)
+            {
+                dateTime = TimeZoneInfo.ConvertTimeFromUtc(dateTime, _engine.Options.TimeZone);
+                dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
+            }
+            return dateTime;
         }
         }
 
 
         ExceptionHelper.ThrowRangeError(_engine.Realm);
         ExceptionHelper.ThrowRangeError(_engine.Realm);

+ 6 - 0
Jint/Options.cs

@@ -335,6 +335,12 @@ namespace Jint
         /// <see cref="IObjectWrapper"/> passing through 'JSON.stringify'.
         /// <see cref="IObjectWrapper"/> passing through 'JSON.stringify'.
         /// </summary>
         /// </summary>
         public Func<object, string>? SerializeToJson { get; set; }
         public Func<object, string>? SerializeToJson { get; set; }
+
+        /// <summary>
+        /// What kind of date time should be produced when JavaScript date is converted to DateTime. If Local, uses <see cref="Options.TimeZone"/>.
+        /// Defaults to <see cref="System.DateTimeKind.Utc"/>.
+        /// </summary>
+        public DateTimeKind DateTimeKind { get; set; } = DateTimeKind.Utc;
     }
     }
 
 
     /// <summary>
     /// <summary>