Skip to content

Commit 6192e70

Browse files
mathiask88mhdawson
authored andcommitted
src: add napi_date
PR-URL: #497 Reviewed-By: NickNaso <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent 7b1ee96 commit 6192e70

File tree

11 files changed

+232
-0
lines changed

11 files changed

+232
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ The following is the documentation for node-addon-api.
7575
- [String](doc/string.md)
7676
- [Name](doc/basic_types.md#name)
7777
- [Number](doc/number.md)
78+
- [Date](doc/date.md)
7879
- [BigInt](doc/bigint.md)
7980
- [Boolean](doc/boolean.md)
8081
- [Env](doc/env.md)

doc/basic_types.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,14 @@ bool Napi::Value::IsExternal() const;
257257
Returns `true` if the underlying value is a N-API external object or `false`
258258
otherwise.
259259

260+
#### IsDate
261+
```cpp
262+
bool Napi::Value::IsDate() const;
263+
```
264+
265+
Returns `true` if the underlying value is a JavaScript `Date` or `false`
266+
otherwise.
267+
260268
#### ToBoolean
261269
```cpp
262270
Napi::Boolean Napi::Value::ToBoolean() const;

doc/date.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Date
2+
3+
`Napi::Date` class is a representation of the JavaScript `Date` object. The
4+
`Napi::Date` class inherits its behavior from `Napi::Value` class
5+
(for more info see [`Napi::Value`](value.md))
6+
7+
## Methods
8+
9+
### Constructor
10+
11+
Creates a new _empty_ instance of a `Napi::Date` object.
12+
13+
```cpp
14+
Napi::Date::Date();
15+
```
16+
17+
Creates a new _non-empty_ instance of a `Napi::Date` object.
18+
19+
```cpp
20+
Napi::Date::Date(napi_env env, napi_value value);
21+
```
22+
23+
- `[in] env`: The environment in which to construct the `Napi::Date` object.
24+
- `[in] value`: The `napi_value` which is a handle for a JavaScript `Date`.
25+
26+
### New
27+
28+
Creates a new instance of a `Napi::Date` object.
29+
30+
```cpp
31+
static Napi::Date Napi::Date::New(Napi::Env env, double value);
32+
```
33+
34+
- `[in] env`: The environment in which to construct the `Napi::Date` object.
35+
- `[in] value`: The time value the JavaScript `Date` will contain represented
36+
as the number of milliseconds since 1 January 1970 00:00:00 UTC.
37+
38+
Returns a new instance of `Napi::Date` object.
39+
40+
### ValueOf
41+
42+
```cpp
43+
double Napi::Date::ValueOf() const;
44+
```
45+
46+
Returns the time value as `double` primitive represented as the number of
47+
milliseconds since 1 January 1970 00:00:00 UTC.
48+
49+
## Operators
50+
51+
### operator double
52+
53+
Converts a `Napi::Date` value to a `double` primitive.
54+
55+
```cpp
56+
Napi::Date::operator double() const;
57+
```
58+
59+
### Example
60+
61+
The following shows an example of casting a `Napi::Date` value to a `double`
62+
primitive.
63+
64+
```cpp
65+
double operatorVal = Napi::Date::New(Env(), 0); // Napi::Date to double
66+
// or
67+
auto instanceVal = info[0].As<Napi::Date>().ValueOf();
68+
```

doc/value.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The following classes inherit, either directly or indirectly, from `Napi::Value`
1010
- [`Napi::ArrayBuffer`](array_buffer.md)
1111
- [`Napi::Boolean`](boolean.md)
1212
- [`Napi::Buffer`](buffer.md)
13+
- [`Napi::Date`](date.md)
1314
- [`Napi::External`](external.md)
1415
- [`Napi::Function`](function.md)
1516
- [`Napi::Name`](name.md)
@@ -226,6 +227,14 @@ bool Napi::Value::IsBuffer() const;
226227

227228
Returns a `bool` indicating if this `Napi::Value` is a Node buffer.
228229

230+
### IsDate
231+
232+
```cpp
233+
bool Napi::Value::IsDate() const;
234+
```
235+
236+
Returns a `bool` indicating if this `Napi::Value` is a JavaScript date.
237+
229238
### As
230239

231240
```cpp

napi-inl.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,19 @@ inline bool Value::IsBigInt() const {
379379
}
380380
#endif // NAPI_EXPERIMENTAL
381381

382+
#if (NAPI_VERSION > 4)
383+
inline bool Value::IsDate() const {
384+
if (IsEmpty()) {
385+
return false;
386+
}
387+
388+
bool result;
389+
napi_status status = napi_is_date(_env, _value, &result);
390+
NAPI_THROW_IF_FAILED(_env, status, false);
391+
return result;
392+
}
393+
#endif
394+
382395
inline bool Value::IsString() const {
383396
return Type() == napi_string;
384397
}
@@ -660,6 +673,37 @@ inline void BigInt::ToWords(int* sign_bit, size_t* word_count, uint64_t* words)
660673
}
661674
#endif // NAPI_EXPERIMENTAL
662675

676+
#if (NAPI_VERSION > 4)
677+
////////////////////////////////////////////////////////////////////////////////
678+
// Date Class
679+
////////////////////////////////////////////////////////////////////////////////
680+
681+
inline Date Date::New(napi_env env, double val) {
682+
napi_value value;
683+
napi_status status = napi_create_date(env, val, &value);
684+
NAPI_THROW_IF_FAILED(env, status, Date());
685+
return Date(env, value);
686+
}
687+
688+
inline Date::Date() : Value() {
689+
}
690+
691+
inline Date::Date(napi_env env, napi_value value) : Value(env, value) {
692+
}
693+
694+
inline Date::operator double() const {
695+
return ValueOf();
696+
}
697+
698+
inline double Date::ValueOf() const {
699+
double result;
700+
napi_status status = napi_get_date_value(
701+
_env, _value, &result);
702+
NAPI_THROW_IF_FAILED(_env, status, 0);
703+
return result;
704+
}
705+
#endif
706+
663707
////////////////////////////////////////////////////////////////////////////////
664708
// Name class
665709
////////////////////////////////////////////////////////////////////////////////

napi.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ namespace Napi {
116116
#if (NAPI_VERSION > 2147483646)
117117
class BigInt;
118118
#endif // NAPI_EXPERIMENTAL
119+
#if (NAPI_VERSION > 4)
120+
class Date;
121+
#endif
119122
class String;
120123
class Object;
121124
class Array;
@@ -246,6 +249,9 @@ namespace Napi {
246249
#if (NAPI_VERSION > 2147483646)
247250
bool IsBigInt() const; ///< Tests if a value is a JavaScript bigint.
248251
#endif // NAPI_EXPERIMENTAL
252+
#if (NAPI_VERSION > 4)
253+
bool IsDate() const; ///< Tests if a value is a JavaScript date.
254+
#endif
249255
bool IsString() const; ///< Tests if a value is a JavaScript string.
250256
bool IsSymbol() const; ///< Tests if a value is a JavaScript symbol.
251257
bool IsArray() const; ///< Tests if a value is a JavaScript array.
@@ -358,6 +364,24 @@ namespace Napi {
358364
};
359365
#endif // NAPI_EXPERIMENTAL
360366

367+
#if (NAPI_VERSION > 4)
368+
/// A JavaScript date value.
369+
class Date : public Value {
370+
public:
371+
/// Creates a new Date value from a double primitive.
372+
static Date New(
373+
napi_env env, ///< N-API environment
374+
double value ///< Number value
375+
);
376+
377+
Date(); ///< Creates a new _empty_ Date instance.
378+
Date(napi_env env, napi_value value); ///< Wraps a N-API value primitive.
379+
operator double() const; ///< Converts a Date value to double primitive
380+
381+
double ValueOf() const; ///< Converts a Date value to a double primitive.
382+
};
383+
#endif
384+
361385
/// A JavaScript string or symbol value (that can be used as a property name).
362386
class Name : public Value {
363387
public:

test/binding.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ Object InitBuffer(Env env);
2020
#if (NAPI_VERSION > 2)
2121
Object InitCallbackScope(Env env);
2222
#endif
23+
#if (NAPI_VERSION > 4)
24+
Object InitDate(Env env);
25+
#endif
2326
Object InitDataView(Env env);
2427
Object InitDataViewReadWrite(Env env);
2528
Object InitError(Env env);
@@ -56,6 +59,9 @@ Object Init(Env env, Object exports) {
5659
// released in once it is no longer experimental
5760
#if (NAPI_VERSION > 2147483646)
5861
exports.Set("bigint", InitBigInt(env));
62+
#endif
63+
#if (NAPI_VERSION > 4)
64+
exports.Set("date", InitDate(env));
5965
#endif
6066
exports.Set("buffer", InitBuffer(env));
6167
#if (NAPI_VERSION > 2)

test/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
'basic_types/number.cc',
1515
'basic_types/value.cc',
1616
'bigint.cc',
17+
'date.cc',
1718
'binding.cc',
1819
'buffer.cc',
1920
'callbackscope.cc',

test/date.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#define NAPI_EXPERIMENTAL
2+
#include "napi.h"
3+
4+
using namespace Napi;
5+
6+
#if (NAPI_VERSION > 4)
7+
namespace {
8+
9+
Value CreateDate(const CallbackInfo& info) {
10+
double input = info[0].As<Number>().DoubleValue();
11+
12+
return Date::New(info.Env(), input);
13+
}
14+
15+
Value IsDate(const CallbackInfo& info) {
16+
Date input = info[0].As<Date>();
17+
18+
return Boolean::New(info.Env(), input.IsDate());
19+
}
20+
21+
Value ValueOf(const CallbackInfo& info) {
22+
Date input = info[0].As<Date>();
23+
24+
return Number::New(info.Env(), input.ValueOf());
25+
}
26+
27+
Value OperatorValue(const CallbackInfo& info) {
28+
Date input = info[0].As<Date>();
29+
30+
return Boolean::New(info.Env(), input.ValueOf() == static_cast<double>(input));
31+
}
32+
33+
} // anonymous namespace
34+
35+
Object InitDate(Env env) {
36+
Object exports = Object::New(env);
37+
exports["CreateDate"] = Function::New(env, CreateDate);
38+
exports["IsDate"] = Function::New(env, IsDate);
39+
exports["ValueOf"] = Function::New(env, ValueOf);
40+
exports["OperatorValue"] = Function::New(env, OperatorValue);
41+
42+
return exports;
43+
}
44+
45+
#endif

test/date.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'use strict';
2+
3+
const buildType = process.config.target_defaults.default_configuration;
4+
const assert = require('assert');
5+
6+
test(require(`./build/${buildType}/binding.node`));
7+
test(require(`./build/${buildType}/binding_noexcept.node`));
8+
9+
function test(binding) {
10+
const {
11+
CreateDate,
12+
IsDate,
13+
ValueOf,
14+
OperatorValue,
15+
} = binding.date;
16+
assert.deepStrictEqual(CreateDate(0), new Date(0));
17+
assert.strictEqual(IsDate(new Date(0)), true);
18+
assert.strictEqual(ValueOf(new Date(42)), 42);
19+
assert.strictEqual(OperatorValue(new Date(42)), true);
20+
}

0 commit comments

Comments
 (0)