codepro123
codepro123

Reputation: 81

compute number of seconds in cpp week to current datetime,

I am trying to find out the number of seconds of week to date and i tried following way please correct me if i am wrong:

 //tp is time precision and dp is day precision.
    auto tp = floor<seconds>(system_clock::now());
    auto dp = floor<days>(tp);
    dp -= weekday{dp} - Monday;
    int WeekSeconds=tp - dp;

and error i am getting below:


jdoodle.cpp: In function ‘int main()’:
jdoodle.cpp:6:28: error: ‘floor’ is not a member of ‘std::chrono’
    6 |     auto tp = std::chrono::floor<seconds>(std::chrono::system_clock::now());
      |                            ^~~~~
jdoodle.cpp:6:34: error: ‘seconds’ was not declared in this scope; did you mean ‘std::chrono::seconds’?
    6 |     auto tp = std::chrono::floor<seconds>(std::chrono::system_clock::now());
      |                                  ^~~~~~~
      |                                  std::chrono::seconds
In file included from jdoodle.cpp:2:
/usr/include/c++/9.2.0/chrono:614:53: note: ‘std::chrono::seconds’ declared here
  614 |     typedef duration<_GLIBCXX_CHRONO_INT64_T>       seconds;
      |                                                     ^~~~~~~
jdoodle.cpp:7:15: error: ‘floor’ was not declared in this scope
    7 |     auto dp = floor<days>(tp);
      |               ^~~~~
jdoodle.cpp:7:21: error: ‘days’ was not declared in this scope
    7 |     auto dp = floor<days>(tp);
      |                     ^~~~
jdoodle.cpp:8:11: error: ‘weekday’ was not declared in this scope
    8 |     dp -= weekday{dp} - Monday;
      |           ^~~~~~~
jdoodle.cpp:8:25: error: ‘Monday’ was not declared in this scope
    8 |     dp -= weekday{dp} - Monday;
      |                         ^~~~~~
jdoodle.cpp:9:12: error: ‘thisWeekSeconds’ was not declared in this scope
    9 |     return thisWeekSeconds=tp - dp;

Upvotes: 1

Views: 590

Answers (2)

Howard Hinnant
Howard Hinnant

Reputation: 218750

Your code is almost correct, but a little ahead of its time. :-)

You are using new C++20 facilities that are not yet shipping. But there exists a free, open-source preview of the new C++20 chrono library which works with C++11/14/17.

#include "date/date.h"
#include <chrono>
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;

    auto tp = floor<seconds>(system_clock::now());
    auto dp = floor<days>(tp);
    dp -= weekday{dp} - Monday;
    auto WeekSeconds=tp - dp;
    cout << WeekSeconds << '\n';
}

WeekSeconds has type std::chrono::seconds, as opposed to int.

Note that this defines the beginning of the week as Monday 00:00:00 UTC.

If you want to define the beginning of the week in some other time zone, such as your local time zone, this would look more like:

#include "date/tz.h"
#include <chrono>
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;

    auto tp = floor<seconds>(system_clock::now());
    zoned_seconds dp{current_zone(), tp};
    auto lt = floor<days>(dp.get_local_time());
    lt -= weekday{lt} - Monday;
    dp = lt;
    auto WeekSeconds = tp - dp.get_sys_time();
    cout << WeekSeconds << '\n';
}

Above I convert to the "local time" using current_zone() and storing that in a "zoned time". I then extract the local time and do the computation to find the beginning of the week as before. Then store that back into the "zoned time".

Finally I subtract the computed beginning of the week in UTC from the current time. This gives the number of physical seconds since the beginning of the local week.

This brings up an interesting point: What if there was a "Fall back" daylight saving shift between the beginning of the local week and now? Do you want to count the number of physical seconds, which means that this week is 1h short of a normal week of 604800s (7*86400s), or do you want to count calendrical seconds, effectively skipping over the 3600s that were erased by the UTC shift? This latter computation makes every week look 604800s long. It is just that some of the seconds never existed, or that in a "Spring Forward" some will be counted twice.

If the latter computation is what you desire, this can be done by altering the above computation by doing the subtraction in local time instead of in UTC:

auto tp = floor<seconds>(system_clock::now());
zoned_seconds dp{current_zone(), tp};
auto lt = floor<days>(dp.get_local_time());
lt -= weekday{lt} - Monday;
auto WeekSeconds = dp.get_local_time() - lt;
cout << WeekSeconds << '\n';

One final caveat: None of the above computations includes the possibility of a leap second being inserted between now and the beginning of the week. However that too is possible to take into account using utc_clock-based time_points. I'd show an example but such an example will depend on the issues illustrated above such as counting UTC or local time.

Upvotes: 1

user4640261
user4640261

Reputation:

As far as I understood you want to get number of seconds in a week, so here is my take:

#include <chrono>
#include <iostream>
#include <ratio>

int main() {
  using namespace std;
  using namespace std::chrono;

  using days = duration<int, ratio_multiply<ratio<24>, chrono::hours::period>>;
  using weeks = duration<int, ratio_multiply<ratio<7>, days::period>>;

  seconds s = weeks{1};
  cout << s.count();
}

Note that the duration days and week is not landed on most compilers because it's in C++20 standard. Not a big deal though, you can easily define yourself, as above.

Upvotes: 1

Related Questions