Question: how to extract milliseconds (or nanoseconds) from a hh_mm_ss
By trial and error, i figured out something, but please verify. Is this the proper way to break down a time point? Extract fields, especially the milliseconds (subseconds). Into plain old integer numbers.
$ cat tt.cc
#include "date/tz.h"
#include <iostream>
int main() {
using namespace date;
using namespace std::chrono;
auto z = make_zoned(current_zone(), system_clock::now());
auto l = z.get_local_time();
auto mill = floor<milliseconds>(l);
auto day = floor<days>(mill);
year_month_day ymd{day};
hh_mm_ss<milliseconds> hmsms{mill - day}; // Or "make_time(mill - day)"?
std::cout << "year month day:\n";
std::cout << (ymd.year() - 0_y).count() << '\n';
std::cout << (ymd.month() - December).count() << '\n'; // 1-based. 1==January
std::cout << (ymd.day() - 0_d).count() << '\n'; // Or "static_cast<int>(ymd.day())" ?
std::cout << "hours minutes seconds weekday:\n";
std::cout << hmsms.hours().count() << '\n';
std::cout << hmsms.minutes().count() << '\n';
std::cout << hmsms.seconds().count() << '\n';
std::cout << (weekday{day} - Sunday).count() << '\n'; // 1==Monday
std::cout << "isdst:\n";
std::cout << std::boolalpha << (z.get_info().save != minutes{0}) << '\n';
std::cout << "subseconds:\n";
std::cout << hmsms.subseconds().count() << '\n';
}
$ g++ -Wall -Werror -std=c++14 -I/home/xx/date/include -DINSTALL=/home/xx -DHAS_REMOTE_API=0 -O0 -o tt tt.cc /home/xx/date/src/tz.cpp -lpthread
$ ./tt
year month day:
2020
3
4
hours minutes seconds weekday:
17
41
45
3
isdst:
false
subseconds:
478
Yes, but there all alternatives you may prefer. I'll intersperse them below:
auto z = make_zoned(current_zone(), system_clock::now());
auto l = z.get_local_time();
auto mill = floor<milliseconds>(l);
auto day = floor<days>(mill);
or:
auto day = floor<days>(l);
Either works as well as the other.
year_month_day ymd{day};
hh_mm_ss<milliseconds> hmsms{mill - day}; // Or "make_time(mill - day)"?
Yes. In C++17 and higher you can simply say hh_mm_ss hmsms{mill - day};. This is because the language feature CTAD will deduce the <milliseconds> template parameter. And for this reason, make_time, though it still exists, is considered deprecated and was purposefully not put into C++20.
std::cout << "year month day:\n";
std::cout << (ymd.year() - 0_y).count() << '\n';
std::cout << (ymd.month() - December).count() << '\n'; // 1-based. 1==January
std::cout << (ymd.day() - 0_d).count() << '\n'; // Or "static_cast<int>(ymd.day())" ?
The above could also look like:
std::cout << int{ymd.year()} << '\n';
std::cout << unsigned{ymd.month()} << '\n'; // 1-based. 1==January
std::cout << unsigned{ymd.day()} << '\n'; // Or "static_cast<int>(ymd.day())" ? Yes, this too.
Also each of the above can be streamed out directly:
std::cout << ymd.year() << '\n';
std::cout << ymd.month() << '\n';
std::cout << ymd.day() << '\n';
which outputs:
2020
Mar
04
std::cout << "hours minutes seconds weekday:\n";
std::cout << hmsms.hours().count() << '\n';
std::cout << hmsms.minutes().count() << '\n';
std::cout << hmsms.seconds().count() << '\n';
The above can also be streamed out direclty:
std::cout << hmsms.hours() << '\n';
std::cout << hmsms.minutes() << '\n';
std::cout << hmsms.seconds() << '\n';
resulting in:
12h
22min
42s
std::cout << (weekday{day} - Sunday).count() << '\n'; // 1==Monday
This can also be done with:
std::cout << weekday{day}.c_encoding() << '\n'; // 1==Monday
And there is also an .iso_encoding() which maps Sunday to 7.
std::cout << "isdst:\n";
std::cout << std::boolalpha << (z.get_info().save != minutes{0}) << '\n';
In C++14 and later you can use 0min in place of minutes{0}.
std::cout << "subseconds:\n";
std::cout << hmsms.subseconds().count() << '\n';
Without the .count() above:
std::cout << hmsms.subseconds() << '\n';
Then you also get the units:
410ms
A sub-question:
How to qualify things like 0min or 0_y?
std::chrono::minutes{0} works.
std::chrono::0min does not work. ("expected unqualified-id before numeric constant")
I don't know of a way to qualify user defined literals. For this reason they are often put in namespaces that only define literals so that you can have a using directive that doesn't pull that much into scope.
For example _y lives in namespace date::literals. You can access it with either using namespace date (which pulls in a lot), or using namespace date::literals (which only pulls in other date literals.
For min the most limited scope is namespace std::chrono_literals. The next largest scope is namespace std::literals (which pulls in all std literals, not just the chrono ones). And you also get them with the huge scope of namespace std.
If you're in a context where you really don't want a using (such as namespace scope in a header), then std::chrono::minutes{0} and date::year{0} is the way to go.
What is the type of date::make_zoned?
How to pass, for example, a zoned time to a funtion (as parameter)?
In my current environment
date::zoned_time<std::common_type_t<std::chrono::nanoseconds, std::chrono::seconds>> now = date::make_zoned(date::current_zone(), std::chrono::system_clock::now());
seems working, but I am afraid that in other environment, where system_clock has other resolution than nanoseconds, it will fail.
(This question may be independent of date library. I apologize for that.)
No need to apologize. I'm happy to help.
date::make_zoned should be considered deprecated. It's only function is to deduce the template arguments for zoned_time<Duration>, which is what make_zoned returns. In C++17 and later, the constructor arguments to zoned_time can be automatically reduced.
For example:
auto zt = make_zoned(current_zone(), system_clock::now());
zoned_time<system_clock::duration> zt{current_zone(), system_clock::now()};
zoned_time zt{current_zone(), system_clock::now()};
All three lines above are equivalent. The third one requires C++17 or higher.
And that was a long-winded way of saying that zoned_time<system_clock::duration> is the type you're looking for. The type of system_clock::duration will vary with platform:
- With llvm/libc++ it is
microseconds. - With gcc/libstdc++ it is
nanoseconds. - On Windows it is 100ns.
Thank you.
(Issue can be closed.)