【问题标题】:Nashorn NativeDate conversion to java.util.DateNashorn NativeDate 转换为 java.util.Date
【发布时间】:2014-08-19 14:23:28
【问题描述】:

当使用 Java 8 上的 Nashorn 将 Javascript Date 对象返回给 Java 时,如下所示:

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("nashorn");
Object js = engine.eval("new Date();");

通过以下尝试,我得到了例外:

  1. Date javaDate = (Date)js;

    jdk.nashorn.api.scripting.ScriptObjectMirror cannot be cast to java.util.Date

  2. Date javaDate = js.to(Date.class);

    Cannot cast jdk.nashorn.internal.objects.NativeDate to java.util.Date

  3. Date javaDate = (Date)ScriptUtils.convert(js.to(NativeDate.class), Date.class);

    Cannot cast jdk.nashorn.internal.objects.NativeDate to java.util.Date

回到 Rhino,我只是使用 context.jsToJava(nativeDateObj, Date.class);

有什么想法可以在返回 Java 时实际转换 NativeDate 吗?

附:如果我执行 js.toString() 那么它会给我“[Date 2012-01-01T19:00:00.000Z]”。我想我可以正则表达式解析...但是为什么-哦-为什么...

【问题讨论】:

    标签: java javascript date nashorn


    【解决方案1】:

    jdk.nashorn.api.scripting.ScriptObjectMirror 上转换返回的JavaScript 对象,然后您将能够以“类似地图”的方式访问其属性。

    ScriptObjectMirror jsDate = (ScriptObjectMirror) engine.eval("new Date();")
    long timestampLocalTime = (long) (double) jsDate.callMember("getTime"); 
    // yes, js date returns timestamp in local time so you need to adjust it... ;)
    int timezoneOffsetMinutes = (int) (double) jsDate.callMember("getTimezoneOffset");
    // java.util.Date construcctor utilizes UTC timestamp
    Date jDate = new Date(timestampLocalTime + timezoneOffsetMinutes * 60 * 1000);
    

    另请参阅:http://cr.openjdk.java.net/~sundar/jdk.nashorn.api/8u20/javadoc/jdk/nashorn/api/scripting/ScriptObjectMirror.html

    但是,如果您要在 Java 端频繁使用一些“JavaScript 类” - 您可能会发现定义“覆盖”接口以更方便地访问 javascript 对象的方法很有用。请参见以下示例:

    public interface JsDateWrapper {
        long getTime();
        int getTimezoneOffset();
        // ...
    }
    
    Object jso = engine.eval("new Date();");
    JsDateWrap jsDate = ((Invocable) engine).getInterface(jso, JsDateWrapper.class);
    Date jDate = new Date(jsDate.getTime() + jsDate.getTimezoneOffset() * 60 * 1000);
    

    【讨论】:

    • 转换为 LongInteger 不起作用,因为 getTimegetTimezoneOffSet 都返回双精度值。将它们投射到 Double 并要求 longValue()intValue() 然后它可以工作。
    • @Aris2World - 实际上第一部分提出了演员表异常。我现在修好了。但我敢打赌,当我第一次发布它时它会起作用;)(我通常构建并运行示例)。无论如何,感谢您的通知。
    • 我很确定。正如这个答案stackoverflow.com/a/33126596/3148880 中所述,我想问题是内部类在没有任何通知的情况下发生了变化。无论如何,您的解决方案是最好的,恕我直言,我满意地使用它,所以我很高兴为它的正确性做出贡献。再次感谢。
    【解决方案2】:

    同样的问题,解决方法:

    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("nashorn");
    Object js = engine.eval("new java.util.Date();");
    

    【讨论】:

    • 尽管如此,您并没有生成 JavaScript Date 对象。
    • 在脚本中设置完整的 Date 类名(对于我想在脚本中创建新 Date 实例的情况)对我有帮助;新的 java.util.Date()
    【解决方案3】:

    我在我的项目中这样做:

    retValue = new Date(value.to(Long.class));
    

    【讨论】:

    • 需要获取js类名:if ("Date".equalst(value.getClassName())
    猜你喜欢
    • 2014-02-10
    • 2011-08-29
    • 2019-08-03
    • 2019-07-22
    • 2011-06-29
    • 2016-02-14
    • 1970-01-01
    相关资源
    最近更新 更多