boostorg / mysql

MySQL C++ client based on Boost.Asio
https://www.boost.org/doc/libs/master/libs/mysql
Boost Software License 1.0
246 stars 34 forks source link

RFE: Date as local time #263

Closed SpareSimian closed 2 months ago

SpareSimian commented 2 months ago

I'm working with an old database with date fields with no timezone information. (The dates assume Pacific time.) boost::mysql::date appears to assume a UTC date when invoking as_time_point. It would be nice to be able to extract a local time_point, instead. For now, I think I need to build my own time_point from the y/m/d values.

Also, something not obvious from the documentation was whether months and days are zero- or one-based. Reading through the sources, it seems they're one-based.

SpareSimian commented 2 months ago

It seems what I want is a local_days object, so I'm creating that from the raw y/m/d in the results. https://stackoverflow.com/questions/70755499/create-stdchronozoned-time-from-zone-and-time

anarthal commented 2 months ago

You're completely correct. As this library targets C++11 and above, it used the only time_point facilities it had at the moment.

For now, and since the date::time_point you're getting is attempting to represent what C++20 local_days does, I'd advise you to cast the time point to local_days, like this:

mysql::date d; // get it from DB
std::chrono::local_days locdays (d.as_time_point().time_since_epoch());
std::chrono::zoned_time zt ("Your/time/zone", locdays);

(See this godbolt).

That being said, the ideal would be making get_time_point and as_time_point return local_days, but I can't just change it because that'd break people not in C++20. What I could do is adding get_local_time_point and as_local_time_point accessors returning local_days (and same for datetime).

I've also opened #264 to clarify the docs.

Let me know your thoughts about this.

Cheers, Ruben.

SpareSimian commented 2 months ago

That sounds reasonable. Is the cast to local_days like reinterpret_cast, leaving the value untouched and just changing the clock type? I wasn't sure if it would try to do math to convert it to the local timezone, but it now sounds like I misunderstood local_days to mean the actual local timezone and not just a time_point with an unspecified clock.

I agree about the compatibility and adding separate accessors makes sense to me.

anarthal commented 2 months ago

local_days carries no time zone information with it - it's like a sys_days, but with a placeholder clock such as, when you pass it to zoned_time constructor, it knows it's not UTC, but in the time zone you pass. Think of it as the "time-zone unaware" datetimes in Python.

So my cast is just discarding the time zone information sys_days has with it. It's building a time-zone unaware time point, with the same duration as the original. "Hey, this is not UTC, but a local time zone yet not specified"

SpareSimian commented 2 months ago

That sounds perfect, then.

anarthal commented 2 months ago

Which compiler/OS/stdlib are you using? gcc and clang have currently problems with the __cpp_lib_chrono feature test macro. They are missing some of the bits required to define the macro, but still have the local_time class.

SpareSimian commented 2 months ago

I'm using VS 2022 with C++20 on Win10x64. I had to switch the default language version to get the newer C++20 chrono features.

anarthal commented 2 months ago

Can you please have a quick look at the #269 PR?

SpareSimian commented 2 months ago

I went through all the commits and it all looks good. Thanks!