Skip to content

Alternate system clock time point resolutions #2035

Closed
@mhfrantz

Description

@mhfrantz

Issue description

When translating from alternate system clock time point types, e.g. std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds> (on a platform where the resolution of std::chrono::system_clock::time_point is nanoseconds), the compiler complains in the type_caster code:

/root/.hunter/_Base/f119fdb/70a713e/0003bc6/Install/include/pybind11/chrono.h:119:19: error: no match for ‘operator=’ (operand types are ‘pybind11::detail::type_caster<std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000> > >, void>::type {aka std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000> > >}’ and ‘std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000000> > >’)
             value = system_clock::from_time_t(std::mktime(&cal)) + microseconds(PyDateTime_DATE_GET_MICROSECOND(src.ptr()));

The error comes because C++ will not silently perform the assignment if it could result in loss of precision. Instead, std::chrono::time_point_cast must be used. In this case, the result of system_clock::from_time_t will be in the default resolution (which is nanoseconds on my platform), so the assignment to value (which has microsecond resolution) requires the explicit cast.

Reproducible example code

Here is an example of the error I'm seeing, distilled into C++.

Here is the fix.

#include <pybind11/chrono.h>
#include <pybind11/pybind11.h>

namespace py = pybind11;

using time_point_us = std::chrono::time_point<
    std::chrono::system_clock, std::chrono::microseconds>;

struct Repro
{
    time_point_us timestamp;
};

PYBIND11_MODULE(repro, m)
{
    py::class_<Repro>(m, "Repro")
        .def(py::init<>())
        .def_readwrite("timestamp", &Repro::timestamp)
        ;
}
from datetime import datetime
from repro import Repro

r = Repro()
r.timestamp = datetime.now()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions