|
9 | 9 | #include <Python.h>
|
10 | 10 | #include <datetime.h>
|
11 | 11 |
|
12 |
| -// https://github.com/python/cpython/blob/v3.10.11/Modules/_datetimemodule.c#L89-L92 |
13 |
| -#define DATE_SET_MICROSECOND(o, v) \ |
14 |
| - (((o)->data[7] = ((v) & 0xff0000) >> 16), \ |
15 |
| - ((o)->data[8] = ((v) & 0x00ff00) >> 8), \ |
16 |
| - ((o)->data[9] = ((v) & 0x0000ff))) |
17 |
| - |
18 | 12 | DateType::DateType(PyObject *object) : PyType(object) {}
|
19 | 13 |
|
20 | 14 | DateType::DateType(JSContext *cx, JS::HandleObject dateObj) {
|
21 | 15 | if (!PyDateTimeAPI) { PyDateTime_IMPORT; } // for PyDateTime_FromTimestamp
|
22 | 16 |
|
23 |
| - // Convert by the timestamp value |
24 | 17 | JS::Rooted<JS::ValueArray<0>> args(cx);
|
25 |
| - JS::Rooted<JS::Value> timeValue(cx); |
26 |
| - JS_CallFunctionName(cx, dateObj, "getTime", args, &timeValue); |
27 |
| - double milliseconds = timeValue.toNumber(); |
28 |
| - |
29 |
| - PyObject *timestampArg = PyTuple_New(2); |
30 |
| - PyTuple_SetItem(timestampArg, 0, PyFloat_FromDouble(milliseconds / 1000)); |
31 |
| - PyTuple_SetItem(timestampArg, 1, PyDateTime_TimeZone_UTC); // Make the resulting Python datetime object timezone-aware |
32 |
| - // See https://docs.python.org/3/library/datetime.html#aware-and-naive-objects |
33 |
| - pyObject = PyDateTime_FromTimestamp(timestampArg); |
34 |
| - Py_INCREF(PyDateTime_TimeZone_UTC); // PyTuple_SetItem steals the reference |
35 |
| - Py_DECREF(timestampArg); |
36 |
| - |
37 |
| - // Round to milliseconds precision because the smallest unit for a JS Date is 1ms |
38 |
| - double microseconds = PyDateTime_DATE_GET_MICROSECOND(pyObject); |
39 |
| - DATE_SET_MICROSECOND( |
40 |
| - (PyDateTime_DateTime *)pyObject, |
41 |
| - std::lround(microseconds / 1000) * 1000 |
| 18 | + JS::Rooted<JS::Value> year(cx); |
| 19 | + JS::Rooted<JS::Value> month(cx); |
| 20 | + JS::Rooted<JS::Value> day(cx); |
| 21 | + JS::Rooted<JS::Value> hour(cx); |
| 22 | + JS::Rooted<JS::Value> minute(cx); |
| 23 | + JS::Rooted<JS::Value> second(cx); |
| 24 | + JS::Rooted<JS::Value> usecond(cx); |
| 25 | + JS_CallFunctionName(cx, dateObj, "getUTCFullYear", args, &year); |
| 26 | + JS_CallFunctionName(cx, dateObj, "getUTCMonth", args, &month); |
| 27 | + JS_CallFunctionName(cx, dateObj, "getUTCDate", args, &day); |
| 28 | + JS_CallFunctionName(cx, dateObj, "getUTCHours", args, &hour); |
| 29 | + JS_CallFunctionName(cx, dateObj, "getUTCMinutes", args, &minute); |
| 30 | + JS_CallFunctionName(cx, dateObj, "getUTCSeconds", args, &second); |
| 31 | + JS_CallFunctionName(cx, dateObj, "getUTCMilliseconds", args, &usecond); |
| 32 | + |
| 33 | + pyObject = PyDateTimeAPI->DateTime_FromDateAndTime( |
| 34 | + year.toNumber(), month.toNumber() + 1, day.toNumber(), |
| 35 | + hour.toNumber(), minute.toNumber(), second.toNumber(), |
| 36 | + usecond.toNumber() * 1000, |
| 37 | + PyDateTime_TimeZone_UTC, // Make the resulting Python datetime object timezone-aware |
| 38 | + // See https://docs.python.org/3/library/datetime.html#aware-and-naive-objects |
| 39 | + PyDateTimeAPI->DateTimeType |
42 | 40 | );
|
| 41 | + Py_INCREF(PyDateTime_TimeZone_UTC); |
43 | 42 | }
|
44 | 43 |
|
45 | 44 | JSObject *DateType::toJsDate(JSContext *cx) {
|
|
0 commit comments