time elapsed since local midnight?

I need to find the elapsed time (duration) from local midnight.

I tried this:


1
2
3
4
// if we have a time_point, must convert to a duration first
auto tp = chr::system_clock::now();
// convert to duration first (subtract from midnight)
chr::hh_mm_ss hms2{ tp - chr::floor<chr::days>(tp) };


but gives me 6 hours more than the correct value - that's because it's taking from midnight GMT and not local midnight....I am in CST timezone

please help
Last edited on
As explained before:
system_clock::now() gives you a time point. That is the amount of time (duration) that has elapsed since "epoch", which is usually defined as 1 January 1970, 00:00:00 UTC. And this is totally independent from any time-zone or "local" time! Regardless of where in the world you are located, the amount of time that has elapsed since "epoch" (1 January 1970, 00:00:00 UTC) is exactly the same 😏
1
2
const std::chrono::time_point clock_system = std::chrono::system_clock::now();
std::cout << clock_system.time_since_epoch() << std::endl;
Result:
16941712194600337[1/10000000]s  <-- number of 100-nanosecond intervals elapsed since "epoch"

Okay. You can also convert the time point into a local time, which necessarily requires specifying the time-zone, because the "local" time obviously is specific to the time-zone where you are located! Here we use the system's default time-zone, for simplicity:
1
2
3
const std::chrono::local_time<std::chrono::system_clock::duration> clock_local = 
    std::chrono::current_zone()->to_local(clock_system);
std::cout << clock_local << std::endl;
Result:
2023-09-08 13:11:47.7973938  <-- the "local" time at default time-zone


So, system_clock::now() is not "in GMT" (UTC), but is a time-zone agnostic time point. The point in time is the same, irregardless of time-zone. It's just that the "epoch", which is the reference point (offset) for time points, happens to be "1 January 1970, 00:00:00 UTC".
Last edited on
I am looking for time elapsed from local midnight. It is now approx 16:03:05 but this calculation below gives me time from GMT midnight which is 6 hours more:


1
2
auto tp = chr::system_clock::now();
cout << tp << endl;



2023-09-10 22:03:05.6599597


1
2
chr::hh_mm_ss hms2{ tp - chr::floor<chr::days>(tp) };
cout << hms2 << endl;




22:03:05.6599597



The current time in CST is 6 hours less. How can I get time from local midnight?
(I could substract 6 hours but that would only work for CST) I want time from local midnight regardless of my current time zone!

You are not listening correctly what I am saying and think I am repeating my question which is not the case!!!


Just follow my reasoning please!
How can I get time from local midnight?

Maybe like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <chrono>

using namespace std::chrono;

int main()
{
  zoned_time const current{ current_zone(), system_clock::now() };
  zoned_time const midnight{ current_zone(), floor<days>(current.get_local_time()) };

  duration const time_since_midnight = current.get_local_time() - midnight.get_local_time();

  std::cout << hh_mm_ss{ time_since_midnight } << '\n';
}

https://godbolt.org/z/b6MbGe6GG
Last edited on
I am looking for time elapsed from local midnight. It is now approx 16:03:05 but this calculation below gives me time from GMT midnight which is 6 hours more:
1
2
auto tp = chr::system_clock::now();
cout << tp << endl;

2023-09-10 22:03:05.6599597

A better way to visualize (print) what a time point really "contains" is:
1
2
auto tp = chr::system_clock::now();
cout << tp.time_since_epoch() << endl;

std::chrono::time_point: Class template std::chrono::time_point represents a point in time. It is implemented as if it stores a value of type Duration indicating the time interval from the start of the Clock's epoch.
std::chrono::system_clock: system_clock measures Unix Time (i.e., time since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, not counting leap seconds). [since C++20]


So, what a time_point represents is not really in any time-zone, not even in UTC/GMT. It is agnostic of time-zones (local times).

It's just that the "epoch" (offset point) of the system clock happens to be defined as 00:00:00 UTC on January 1st, 1970.

As pointed out before, if you want a "local" time, then you have to convert the time_point to "local" time, by using the desired time-zone!

I think this is the way to go:
https://cplusplus.com/forum/general/285601/#msg1240872

(Convert time_point to a zoned_time in the desired time-zone, truncate that zoned_time to "days" precision so that hours/minutes/seconds will all be zeroed out, and finally compute the difference between the truncated zoned_time and the non-truncated zoned_time)
Last edited on
Finally mbozzi got what I was asking!
Thanks!

You could also write this without zoned_time if you prefer:

1
2
3
4
5
6
7
8
int main()
{
  local_time current = current_zone()->to_local(system_clock::now());
  local_time midnight = floor<days>(current);
  duration time_since_midnight = current - midnight;
  
  std::cout << hh_mm_ss{ time_since_midnight } << '\n';
}


Notice the code in the prior post does call current_zone twice, which raises the question of whether or not the current time zone can change in the period between the two calls.

I think the code is fine, as long as reload_tzdb is not called. Even so it might be better to act defensively and call current_zone only once.
Last edited on
Topic archived. No new replies allowed.