I have a double
containing seconds. I would like to convert this into a struct tm
.
I can't find a standard function which accomplishes this. Do I have to fill out the struct tm
by hand?
I just accidentally asked this about converting to a time_t
and http://www.StackOverflow.com will not let me post unless I link it.
Well, you accidentally asked the right question before. Convert double
to time_t
, and then convert that to a struct tm
. There's no subsecond field in struct tm
anyway.
For grins, using this chrono
-based header-only library:
#include "date.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
using namespace date;
auto recovery_time = 320.023s; // Requires C++14 for the literal 's'
std::cout << make_time(duration_cast<milliseconds>(recovery_time)) << '\n';
}
outputs:
00:05:20.023
The object returned by make_time
has getters if you want to query each field:
constexpr std::chrono::hours hours() const noexcept {return h_;}
constexpr std::chrono::minutes minutes() const noexcept {return m_;}
constexpr std::chrono::seconds seconds() const noexcept {return s_;}
constexpr precision subseconds() const noexcept {return sub_s_;}
You don't need to choose milliseconds
. You could choose any precision you want from hours
to picoseconds
(if you also supply a type alias for picoseconds
). For example:
std::cout << make_time(duration_cast<seconds>(recovery_time)) << '\n';
Outputs:
00:05:20
MSalters answer is correct, but I thought I'd add a bit of detail on how you should convert to time_t
and how you should convert to tm
.
So given a number of seconds in double input
you can use the implementation dependent method of casting:
const auto temp = static_cast<time_t>(input);
But since time_t
is implementation defined there is no way to know that this is a primitive that can simply be cast to. So the guaranteed method would be to use the chrono library's implementation independent method of converting:
const auto temp = chrono::system_clock::to_time_t(chrono::system_clock::time_point(chrono::duration_cast<chrono::seconds>(chrono::duration<double>(input))));
The conversion options are discussed in more detail here: https://stackoverflow.com/a/50495821/2642059 but once you have obtained your time_t
through one of these methods you can simply use localtime
to convert temp
to a struct tm
.
const auto output = *localtime(&temp);
Note the dereference is important. It will use the default copy assignment operator so output
is captured by value, which is essential because:
The structure may be shared between std::gmtime
, std::localtime
, and std::ctime
, and may be overwritten on each invocation.