3

I want to get the date and time that contain six digits after a second such as 2017-07-03 15:01:01.123456. How to get it? I try with time timeval and gettimeofday but I got an error. My code:

time_t timer;
char timestr[29];
struct timeval *tm_info;

time(&timer);

tm_info = gettimeofday(&timer);

strftime(timestr, 29, "%Y-%m-%d %H:%M:%S", tm_info);

ss << timestr;
  • What is the error? And what is `ss` ? – 463035818_is_not_an_ai May 04 '18 at 10:13
  • 3
    Can you use C++11's `std::chrono`? – YSC May 04 '18 at 10:14
  • 1
    Look at Howard Hinnant's library in his [answer here](https://stackoverflow.com/questions/34963738/c11-get-current-date-and-time-as-string) – Vishaal Shankar May 04 '18 at 10:17
  • ss is string stream. – Yoekleng Kuy May 04 '18 at 10:18
  • cannot convert ‘time_t* {aka long int*}’ to ‘timeval*’ for argument ‘1’ to ‘int gettimeofday(timeval*, __timezone_ptr_t)’ tm_info = gettimeofday(&timer); error: cannot convert ‘timeval*’ to ‘const tm*’ for argument ‘4’ to ‘size_t strftime(char*, size_t, const char*, const tm*)’ strftime(timestr, 29, "%Y-%m-%d %H:%M:%S", tm_info); – Yoekleng Kuy May 04 '18 at 10:19
  • Possible duplicate of https://stackoverflow.com/questions/24686846/get-current-time-in-milliseconds-or-hhmmssmmm-format – Galik May 04 '18 at 10:25
  • If you want use `gettimeofday` function you need pass into it `timeval` and `timezone` structs. see man here http://man7.org/linux/man-pages/man2/gettimeofday.2.html – goldstar May 04 '18 at 10:28
  • Using C++ https://stackoverflow.com/a/27678121/2135548 – Mandar May 04 '18 at 12:07
  • @YoeklengKuy Both of the answers below solve your problem. Please click "accept answer" (the checkbox) on the answer that helped you the most. –  May 04 '18 at 16:01

2 Answers2

2

First of all, if you want six decimal places resolution on the current second, we are talking about microseconds (1us = 10E-6), not milliseconds (1ms = 10E-3). Also, you should probably use std::chrono, as gettimeofday() is OS-specific to Linux and will not work on other systems.

To get the date you can use <time.h> and its gmtime() (UTC), which returns a struct tm. As to the time, an easy way to get elapsed time after the current second, in microseconds, (e.g. 14:31:09.590721), is to exploit the fact that time_t has a resolution of only 1s:

#include <iostream>
#include <string>
#include <chrono>
#include <time.h>

int main() {
    for (int i = 0; i < 1000; ++i) {
        auto now = std::chrono::system_clock::now();
        auto now_t = std::chrono::system_clock::to_time_t(now);

        //Exploit now_t (time_t): resolution is only 1 second - get microseconds
        auto dur = now - std::chrono::system_clock::from_time_t(now_t);
        auto micros = std::chrono::duration_cast<std::chrono::microseconds>(dur).count();


        //Print the date and time as yyyy-mm-dd hh::mm::ss.xxxxxx
        tm& now_tm = *(gmtime(&now_t));
        std::string year = std::to_string(now_tm.tm_year + 1900) + "-";
        std::string mon = std::to_string(now_tm.tm_mon + 1) + "-";
        std::string day = std::to_string(now_tm.tm_mday) + " ";
        std::string hour = std::to_string(now_tm.tm_hour);
        std::string min = std::to_string(now_tm.tm_min);
        std::string sec = std::to_string(now_tm.tm_sec);

        if (hour.size() == 1) hour.insert(0, "0");
        if (min.size() == 1) min.insert(0, "0");
        if (sec.size() == 1) sec.insert(0, "0");

        std::cout << year << mon << day
            << hour << ":" << min << ":" << sec << "." << micros << "\n";
    }
    return 1;
}

Running 10 iterations in my timezone gives:

2018-5-4 12:36:11.47578
2018-5-4 12:36:11.48663
2018-5-4 12:36:11.49516
2018-5-4 12:36:11.50392
2018-5-4 12:36:11.51261
2018-5-4 12:36:11.52455
2018-5-4 12:36:11.53316
2018-5-4 12:36:11.54213
2018-5-4 12:36:11.55113
2018-5-4 12:36:11.55969

PS: When you're at this kind of granularity, you should know the clock source accuracy / drift. This depends on the system (hw, OS, etc). Serious timekeeping requires special hardware (e.g. GPSDO) and software.

1

Here's an easier way to do it using <chrono> and Howard Hinnant's date/time library. This prints out the current time UTC to microseconds precision ten times:

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

int
main()
{
    using namespace std::chrono;
    using namespace date;
    for (auto i = 0; i < 10; ++i)
        std::cout << floor<microseconds>(system_clock::now()) << '\n';
}

Sample output:

2018-05-04 14:01:04.473663
2018-05-04 14:01:04.473770
2018-05-04 14:01:04.473787
2018-05-04 14:01:04.473805
2018-05-04 14:01:04.473824
2018-05-04 14:01:04.473842
2018-05-04 14:01:04.473860
2018-05-04 14:01:04.473878
2018-05-04 14:01:04.473895
2018-05-04 14:01:04.473914
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577