Skip to content

Instantly share code, notes, and snippets.

@UnquietCode
Last active May 20, 2020 11:01
Show Gist options
  • Save UnquietCode/5614860 to your computer and use it in GitHub Desktop.
Save UnquietCode/5614860 to your computer and use it in GitHub Desktop.
Code for running moment.js under Java using the Rhino script engine. https://github.com/timrwood/moment/
private static final String MOMENT_JS_FILE = "moment.min.js";
private static JSInvocable newMoment(Long epoch) {
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(MOMENT_JS_FILE);
Reader reader = new InputStreamReader(is);
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
Object moment;
try {
engine.eval(reader);
if (epoch == null) {
moment = ((Invocable) engine).invokeFunction("moment");
} else {
moment = ((Invocable) engine).invokeFunction("moment", epoch);
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return new JSInvocable((Invocable) engine, moment);
}
public class JSInvocable {
private final Invocable invocable;
private final Object object;
private JSInvocable(Invocable invocable, Object object) {
this.invocable = invocable;
this.object = object;
}
public String invoke(String method, Object...args) {
if (args == null) { args = new Object[0]; }
try {
return invocable.invokeMethod(object, method, args).toString();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
@rage-shadowman
Copy link

Using your code, the following always throws NullPointerException in Java6 for me (works fine in Java7):

JSInvocable invocable = JSInvocable.newMoment( System.currentTimeMillis() );
invocable.invoke( "format", "MMMM Do, YYYY" );

The following works fine in Java6 and Java7:

      InputStream is = Thread.currentThread().getContextClassLoader()
         .getResourceAsStream( "moment.min.js" );
      Reader reader = new InputStreamReader( is );
      ScriptEngineManager manager = new ScriptEngineManager();
      ScriptEngine engine = manager.getEngineByName( "JavaScript" );
      try
      {
         engine.eval( reader );
         return engine.eval( "new moment(" System.currentTimeMillis() + ").format('MMMM Do, YYYY');" ).toString();
      }
      catch( ScriptException e )
      {
         throw new RuntimeException( e );
      }

Of course, you have to escape the format value in case you use quotes so I use:

public static String formatDate( Date date, String format )
{
      InputStream is = Thread.currentThread().getContextClassLoader()
         .getResourceAsStream( "moment.min.js" );
      Reader reader = new InputStreamReader( is );
      ScriptEngineManager manager = new ScriptEngineManager();
      ScriptEngine engine = manager.getEngineByName( "JavaScript" );
      try
      {
         engine.eval( reader );
         format = format.replace( "'", "\\'" );
         String javascript = "new moment(" + date.getTime() + ").format('" + format + "');";
         return evalJavascript( javascript );
      }
      catch( ScriptException e )
      {
         throw new RuntimeException( e );
      }
}

The above has been tested and works with the following also:

MomentJsFormatter.formatDate( new Date(), "MMMM Do, YYYY [at] hh[']mm[\\"]" );

@rage-shadowman
Copy link

See this gist for a copy of my MomentJS dateFormat helper for use with jknack's handlebars.java project (including unit tests).

@dwygonow
Copy link

I’m a nubi at this and I am trying to calculate the difference between 2 date values, (ISO8601 format - this is the format that I am getting it in)

var d1 = new Date('2015-07-12T15:06:23');
var d2 = new Date('2015-07-14T16:09:33');

var diff = d2.getTime() - d1.getTime();

return diff;

I am getting NaN.

When I run this;

var d1 = new Date('2015-07-12T15:06:23');
return d1;

I get something like this;

org.mozilla.javascript.NativeDate@2bcf1082

Any help would be greatly appreciated.

Thanx.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment