1

JavaScript's date constructor can parse strings to create a date:

var date = new Date("2015");
console.log(date); // Thu Jan 01 2015 06:00:00 GMT+0600 (NOVT)
console.log(date.getTime()); // 1420070400000

I need a similar parsing (string to date) in my C++ Node.js addon. I found two ways to get v8:Date:

  • static Local<Value> Date::New(Isolate* isolate, double time). It takes a double value.

  • static Date* Date::Cast(v8::Value* obj) But it simple converts string to double:


v8::Local<v8::String> str = Nan::New("2015").ToLocalChecked();
v8::Date *castDate = v8::Date::Cast(*str);
double castVal = castDate->NumberValue();
printf("%f\n", castVal); // 2015.000000, not 1420070400000 :(

v8::Local<v8::Date> newDate = 
    v8::Date::New(info.GetIsolate(), 2015).As<v8::Date>();
double newVal = newDate->NumberValue();
printf("%f\n", newVal); // 2015.000000

What methods are there in v8 for creating C++ v8::Date from a string?

UPDATE (2016.01.05):

I added "without JS execution from C++" to the question title.

Dzenly
  • 1,611
  • 12
  • 18
  • The V8 date parser is implemented in JavaScript. If the overhead incurred by the C++-to-JS transition is acceptable, you can use approach offered by @ekarak below. Other alternative is to find C++ date parser implementation, for example, http://stackoverflow.com/questions/3786201/how-to-parse-date-time-from-string – smirnoff Jan 04 '16 at 17:33

2 Answers2

2

I thought a bit out of the box and came up with some trickery:

v8::Local<v8::Date> tmp = Nan::New<v8::Date>(0).ToLocalChecked();
v8::Local<v8::Function> cons = v8::Local<v8::Function>::Cast(
    Nan::Get(tmp, Nan::New("constructor").ToLocalChecked()).ToLocalChecked()
);

const int argc = 1;
v8::Local<v8::Value> argv[argc] = {Nan::New("2015").ToLocalChecked()};
v8::Local<v8::Date> date = v8::Local<v8::Date>::Cast(
    Nan::NewInstance(cons, argc, argv).ToLocalChecked()
);

First, I create an arbitrary Date object, then I extract the constructor function which is then used to effectively call new Date("2015").

You could also persist the constructor in your class for slightly more efficiency on frequent use.

p2k
  • 51
  • 1
  • 3
1

How about using an one-off v8::Script for parsing your string? (disclaimer: code not tested)

v8::Handle<v8::String> source = v8::String::New("new Date('2016-01-04')");
v8::Handle<v8::Script> script = v8::Script::Compile(source);
v8::Handle<v8::Value> result = script->Run();
ekarak
  • 608
  • 6
  • 15
  • I knew this way. I corrected the question to be more specific. I believe that JS can use C++ libs inside, and there could be such parsing functions somewhere and somewhen they will be exposed to module writters. :) – Dzenly Jan 05 '16 at 13:38
  • Hmmm, (v8::internal::DateParser)[http://v8.paulfryzel.com/docs/master/classv8_1_1internal_1_1_date_parser.html] looks like a v8 helper class, but I don't see any publicly-facing API – ekarak Jan 05 '16 at 14:47
  • Can't see any straightforward way to use v8 to parse ECMAscript dates in a string. You can either keep a persistent copy of the date parsing script , or maybe even use some other C++ library like Boost (http://www.boost.org/doc/libs/1_49_0/doc/html/date_time/examples.html) to parse the string into a double. Beware of locale and time zone issues ! – ekarak Jan 05 '16 at 23:00
  • Interesting, the DateParser class (https://github.com/mojombo/v8/blob/master/src/dateparser.h) contains such a public function: ```static bool Parse(String* str, FixedArray* output);```. Right now the problem is not actual (we are OK to use "double" date values instead of "string"), but another time I will try it. Thank you for the hint. Probably v8 and Node.js contain a lot hidden stuff which can be useful for node.js addon writers. – Dzenly Jan 06 '16 at 10:20