2

I have to instantiate an object of a custom library class that takes nanoseconds since 'epoch' in UTC time to construct:

class utc_time
{
public:
utc_time(TYPE nanoseconds_since_epoch):
_nanoseconds_since_epoch(nanoseconds_since_epoch){}

private:
TYPE _nanoseconds_since_epoch;
};

what I have as my input is nanoseconds since 'midnight' in UTC time. Naturally, I need to get the epoch till last midnight nanoseconds(in UTC) to add it to my input and supply it to my class constructor. I know we have gtime that may be helpful, but I dont know how to extract the required information.

I appreciate your clues

Mgetz
  • 5,108
  • 2
  • 33
  • 51
rahman
  • 4,820
  • 16
  • 52
  • 86
  • please do not tag spam this is a c++ question not a C question, I've removed the incorrect tag. – Mgetz Nov 13 '15 at 12:42

2 Answers2

9

In C++11 and later, <chrono> can be used to do this very easily:

#include <chrono>
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace std;
    using days = duration<int, ratio<86400>>;
    nanoseconds last_midnight =
        time_point_cast<days>(system_clock::now()).time_since_epoch();
    cout << last_midnight.count() << '\n';
}
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • The question is about UTC date time. I don't think you are considering to convert current time to UTC time before calculating time since epoch. – Bit_Pulse Mar 24 '17 at 04:49
  • @Bit_Pulse: I maintain that this code computes the number of nanoseconds in Unix Time (https://en.wikipedia.org/wiki/Unix_time) from the previous UTC midnight. I just ran this and it output `1490313600000000000`, which is exactly `17249 * 86400 * 10^9`, and today is day number 17249 since 1970-01-01. If the type-o's are corrected in the accepted answer, then that currently returns `1490331600`, which is my answer but in seconds instead of nanoseconds. – Howard Hinnant Mar 24 '17 at 13:18
  • 1
    You need to consider from which timezone you are testing your code and at what time. If UTC day is one day behind your current date then only you will see this issue otherwise, you will always get same time difference because it is until Midnight. `system_clock::now()` Returns the current time_point in the frame of the system_clock not the UTC time. I hope you understand the issue. – Bit_Pulse Mar 28 '17 at 01:39
  • 1
    @Bit_Pulse: I understand. I have written the very best C++ timezone handling library currently available: https://howardhinnant.github.io/date/tz.html The OP precisely nails both input and output down to UTC. No timezones other than UTC are involved. Furthermore my answer responds in kind: never taking into account any time zone or time standard other than UTC. If you would like to see how I would handle "seconds since local midnight", or "seconds since midnight in some other timezone", I'd be very happy to show you clean ``-based code on how to do that. Please post a question on it. – Howard Hinnant Mar 28 '17 at 02:53
2

In deed, nanoseconds since Epoch = nanoseconds since midnight + 1e9 * calendar time of last midnight. You lack the latter value. You can built it with a conjunction of ::gmtime() and ::mktime().

#include <ctime>

std::time_t last_midnight()
{
    // compute "now"
    std::tm& tm = *::gmtime(NULL);
    // move it to "last midnight"
    tm.tm_hour = 0;
    tm.tm_min  = 0;
    tm.tm_sec  = 0;
    // get time_t back
    return ::mktime(&tm);
}

You may find interest in using ::gmtime_r() (re-entrant version) instead of ::gmtime().

YSC
  • 38,212
  • 9
  • 96
  • 149