Blue schrieb am 18.04.21 um 15:31:
> I am trying to use CPython's API directly, but it seems like the already
> defined interface is incomplete. In my case PyDateTime_TimeZone_UTC
> <
https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_TimeZone_UTC> is
> missing, and PyDateTime_FromTimestamp
> <
https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_FromTimestamp> takes
> 3 arguments when it's supposed to take 2 arguments
> <
https://docs.python.org/3/library/datetime.html#datetime.datetime.fromtimestamp>
The .pxd file was added in 2013 and it looks like it wasn't updated with
new functions since then. PR welcome that adds the newer functions.
https://github.com/cython/cython/blob/master/Cython/Includes/cpython/datetime.pxd
PyDateTime_FromTimestamp() only takes a single argument, BTW, a tuple.
Note that you can always just define these functions yourself if you need
them in your code (and send a PR anyway :) ).
> I am trying to *change *the following code into using Cython's interface of
> the Cpython API
> <
https://github.com/cython/cython/blob/master/Cython/Includes/cpython/datetime.pxd>
> I:
>
> from libc.stdint cimport int64_t
> from datetime import datetime, timezone
>
> cdef int64_t DISCORD_EPOCH = 1420070400000
>
> cdef class Snowflake:
> cdef readonly int64_t id
>
> def __cinit__(self, int64_t id, *args, **kwargs):
>
self.id = id
>
> @property
> def created_at(self):
> """Returns a datetime object of when the snowflake was created."""
> cdef unsigned long long timestamp = (
self.id >> 22) + DISCORD_EPOCH
> return datetime.fromtimestamp(timestamp / 1000, tz=timezone.utc)
>
> *But** this fails*
Note that "this fails" is not very descriptive. Instead of hoping for
someone to copy your code into a file and compile it to find out about the
error message, it's better to just copy it right into your email when you
see it on your screen.
> from libc.stdint cimport int64_t
>
> from cpython.datetime cimport import_datetime, PyDateTimeAPI
> import_datetime()
>
> cdef int64_t DISCORD_EPOCH = 1420070400000
>
>
> cdef class Snowflake:
> cdef readonly int64_t id
>
> def __cinit__(self, int64_t id, *args, **kwargs):
>
self.id = id
>
> @property
> def created_at(self):
> """Returns a datetime object of when the snowflake was created."""
> cdef int64_t timestamp = ((
self.id >> 22) + DISCORD_EPOCH) / 1000
> return PyDateTimeAPI.DateTime_FromTimestamp(timestamp, 0)
>
> Am I looking at wrong place, or is Cython in this case wrong?
Neither, really. The macro (it's actually not a function) maps the
arguments internally. You probably don't want to call through the function
pointer directly. We should provide a convenience inline wrapper function
"date[time]_from_timestamp()" for the Date[Time]_FromTimestamp() functions,
just like for the other constructor functions.
Again, PR welcome.
Stefan