Skip to content

Commit 36ceee2

Browse files
authored
Merge pull request #138 from Distributive-Network/Xmader/feat/py-datetime-to-js
Feat: Support converting Python datetime objects to JS Date
2 parents 80b889d + 8ea103b commit 36ceee2

File tree

5 files changed

+31
-4
lines changed

5 files changed

+31
-4
lines changed

include/DateType.hh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,19 @@
2626
struct DateType : public PyType {
2727
public:
2828
DateType(PyObject *object);
29-
DateType(JSContext *cx, JS::Handle<JSObject *> dateObj);
29+
/**
30+
* @brief Convert a JS Date object to Python datetime
31+
*/
32+
DateType(JSContext *cx, JS::HandleObject dateObj);
33+
3034
const TYPE returnType = TYPE::DATE;
35+
36+
/**
37+
* @brief Convert a Python datetime object to JS Date
38+
*
39+
* @param cx - javascript context pointer
40+
*/
41+
JSObject *toJsDate(JSContext *cx);
3142
};
3243

3344
#endif

src/DateType.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
DateType::DateType(PyObject *object) : PyType(object) {}
1313

14-
DateType::DateType(JSContext *cx, JS::Handle<JSObject *> dateObj) {
14+
DateType::DateType(JSContext *cx, JS::HandleObject dateObj) {
1515
JS::Rooted<JS::ValueArray<0>> args(cx);
1616
JS::Rooted<JS::Value> year(cx);
1717
JS::Rooted<JS::Value> month(cx);
@@ -33,4 +33,12 @@ DateType::DateType(JSContext *cx, JS::Handle<JSObject *> dateObj) {
3333
year.toNumber(), month.toNumber() + 1, day.toNumber(),
3434
hour.toNumber(), minute.toNumber(), second.toNumber(),
3535
usecond.toNumber() * 1000);
36-
}
36+
}
37+
38+
JSObject *DateType::toJsDate(JSContext *cx) {
39+
// See https://docs.python.org/3/library/datetime.html#datetime.datetime.timestamp
40+
PyObject *timestamp = PyObject_CallMethod(pyObject, "timestamp", NULL); // the result is in seconds
41+
double milliseconds = PyFloat_AsDouble(timestamp) * 1000;
42+
Py_DECREF(timestamp);
43+
return JS::NewDateObject(cx, JS::TimeClip(milliseconds));
44+
}

src/jsTypeFactory.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "include/StrType.hh"
2121
#include "include/IntType.hh"
2222
#include "include/PromiseType.hh"
23+
#include "include/DateType.hh"
2324
#include "include/ExceptionType.hh"
2425
#include "include/BufferType.hh"
2526

@@ -28,6 +29,7 @@
2829
#include <js/Proxy.h>
2930

3031
#include <Python.h>
32+
#include <datetime.h> // https://docs.python.org/3/c-api/datetime.html
3133

3234
#define HIGH_SURROGATE_START 0xD800
3335
#define LOW_SURROGATE_START 0xDC00
@@ -65,6 +67,8 @@ size_t UCS4ToUTF16(const uint32_t *chars, size_t length, uint16_t **outStr) {
6567
}
6668

6769
JS::Value jsTypeFactory(JSContext *cx, PyObject *object) {
70+
PyDateTime_IMPORT; // for PyDateTime_Check
71+
6872
JS::RootedValue returnType(cx);
6973

7074
if (PyBool_Check(object)) {
@@ -145,6 +149,10 @@ JS::Value jsTypeFactory(JSContext *cx, PyObject *object) {
145149
JSObject *error = ExceptionType(object).toJsError(cx);
146150
returnType.setObject(*error);
147151
}
152+
else if (PyDateTime_Check(object)) {
153+
JSObject *dateObj = DateType(object).toJsDate(cx);
154+
returnType.setObject(*dateObj);
155+
}
148156
else if (PyObject_CheckBuffer(object)) {
149157
BufferType *pmBuffer = new BufferType(object);
150158
JSObject *typedArray = pmBuffer->toJsTypedArray(cx); // may return null

src/modules/pythonmonkey/pythonmonkey.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ static bool clearTimeout(JSContext *cx, unsigned argc, JS::Value *vp) {
375375
// Retrieve the AsyncHandle by `timeoutID`
376376
int32_t timeoutID = timeoutIdArg.toInt32();
377377
AsyncHandle *handle = AsyncHandle::fromId((uint32_t)timeoutID);
378-
if (!handle) return true; // does nothing on invalid timeoutID
378+
if (!handle) return true; // does nothing on invalid timeoutID
379379

380380
// Cancel this job on Python event-loop
381381
handle->cancel();
File renamed without changes.

0 commit comments

Comments
 (0)