C/C++ - Everything about time, date

 Important data types 


time_t

Although not defined by the C standard, this is almost always an integral value holding the number of seconds (not counting leap seconds) since 00:00, Jan 1 1970 UTC, corresponding to POSIX time. 

Unix and POSIX systems define time_t as an integer (usually a 32-bit or 64-bit integer) or a floating-point type.

Note : Time_t can only be handled in seconds, but not in milliseconds or microsec. 


struct tm

The tm structure has the following structure.

struct tm {
  int tm_sec;
  int tm_min;
  int tm_hour;
  int tm_mday;
  int tm_mon;
  int tm_year;
  int tm_wday;
  int tm_yday;
  int tm_isdst;
};

time_t is a variable that stores seconds that have elapsed since 1970. It is often used to convert from this variable to the easy-to-use year, month, day, hour, minute, and second formats.


struct timeval

The time_t discussed above has only a value in seconds. Time_t cannot be used if ms (0.001sec) and us (0.000001sec) values of less than seconds are required. What needs to be addressed is a timeval structure. This structure has a variable tv_usec that stores the value in microseconds along with the time_t value.


Note : tv_usec is not a cumulative US as of 1970. It is less than or equal to tv_sec. If the tvsec of the timeval structure is 1666278477 and the tv_usec is 442388, 

This means 1666278477.442388 sec.


struct timeval
{
    time_t tv_sec;        /* Seconds. */
    suseconds_t tv_usec;  /* Microseconds. */
};


If the current time needs to be covered up to microseconds, this structure should be used. However, there is one thing to note. If this structure has a variable in microseconds, but your hardware does not implement the resolution in microseconds, the actual value may not be accurate up to microseconds. If you have a high resolution timer in your system, you will be able to get tv_usec accurately up to microseconds. Therefore, for safe processing, it is easy to use it in milliseconds.


struct timespec

Timers on modern computers are capable of managing time from microseconds to nanoseconds. Not all computers can manage nanoseconds. As will be described later, use the timespec_get function to use this structure. Don't judge that you can get the exact value up to nanoseconds just because you called this function. If the system's timer does not manage nanoseconds, perhaps the last 3 digits of the tv_nsec value will be meaningless and will play the same role as the timeval structure.

struct timespec
{
    time_t tv_sec;        /* Seconds. */
    suseconds_t tv_nsec;  /* Nanoseconds. */
};



Get the current time

First, I use the time function to get the time_t value, and then use the localtime function to change it to a format that is easy for us to understand.  

Note : the year added 1900, not 1970.


#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;
int main()
{
    time_t now;      // must include time.h
    struct tm *ntm; // must include sys/time.h
    memset(&now, 0x00, sizeof(time_t));  
    time(&now);
    
  
    //converts secs(time_t) to human readable format(struct tm)
    ntm = localtime(&now);

    cout << "year:" << ntm->tm_year + 1900 <<endl;
    cout << "month:" << ntm->tm_mon + 1 <<endl;   //0 based index
    cout << "day:" << ntm->tm_mday <<endl;
    cout << "hour:" << ntm->tm_hour <<endl;
    cout << "minutes:" << ntm->tm_min <<endl;
    cout << "secs:" << ntm->tm_sec <<endl;
    cout << "wday:" << ntm->tm_wday <<endl; //sunday(0), monday(1), ..., Saturday(6)
    cout << "yday:" << ntm->tm_yday <<endl; //1 ~ 365
    return 0;
}


Let's compile and run the codes.

[spypiggy@localhost datecompare]$ g++ today.cpp
[spypiggy@localhost datecompare]$ ./a.out
year:2022
month:10
day:21
hour:0
minutes:49
secs:21
wday:5
yday:293


Get More Accurate Time

This time, let's use the timeval structure to find the value below seconds. The gettimeofday function fills the value of the timeval structure with the current time.

And, using the tv_sec value of the structure, we can use the localtime function to change it to a format that is easy for us to understand. And you can use the tv_usec variable additionally.  

#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;
int main()
{
    timeval curTime;
    struct tm *ntm; // must include sys/time.h

    gettimeofday(&curTime, NULL);
    //converts secs(time_t) to human readable format(struct tm)
    ntm = localtime(&curTime.tv_sec);

    cout << "year:" << ntm->tm_year + 1900<<endl;
    cout << "month:" << ntm->tm_mon + 1 <<endl;   //0 based index
    cout << "day:" << ntm->tm_mday <<endl;
    cout << "hour:" << ntm->tm_hour <<endl;
    cout << "minutes:" << ntm->tm_min <<endl;
    cout << "secs:" << ntm->tm_sec <<endl;
    cout << "micro secs:" << curTime.tv_usec <<endl;
    cout << "wday:" << ntm->tm_wday <<endl; //sunday(0), monday(1), ..., Saturday(6)
    cout << "yday:" << ntm->tm_yday <<endl; //1 ~ 365
    return 0;
}


Let's compile and run the codes. It can be seen that the microseconds were obtained. But I usually divide this value by 1000 and use only milliseconds.

[spypiggy@localhost datecompare]$ g++ today.cpp
[spypiggy@localhost datecompare]$ ./a.out
year:2022
month:10
day:21
hour:0
minutes:56
secs:14
micro secs:301915
wday:5
yday:293


Get More More Accurate Time

We saw earlier that the timespec structure provides the highest timer resolution. Let's see how to get the current time using the timespec structure. You can use the timespec_get function. Note that this function is only available in C++11 or higher.


#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;

int main(void)
{
    struct timespec ts;
    struct tm *ntm;
    timespec_get(&ts, TIME_UTC);
    char buff[100];
    ntm = localtime(&ts.tv_sec);

    cout << "year:" << ntm->tm_year + 1900<<endl;
    cout << "month:" << ntm->tm_mon + 1 <<endl;   //0 based index
    cout << "day:" << ntm->tm_mday <<endl;
    cout << "hour:" << ntm->tm_hour <<endl;
    cout << "minutes:" << ntm->tm_min <<endl;
    cout << "secs:" << ntm->tm_sec <<endl;
    cout << "wday:" << ntm->tm_wday <<endl; //sunday(0), monday(1), ..., Saturday(6)
    cout << "yday:" << ntm->tm_yday <<endl; //1 ~ 365
    cout << "nano sec:" << ts.tv_nsec <<endl; //[0, 999999999]
}


Let's compile and run the codes. It can be seen that the microseconds were obtained. But I usually divide this value by 1000,000 and use only milliseconds.

[spypiggy@localhost time]$ ./a.out
year:2022
month:11
day:19
hour:7
minutes:28
secs:45
wday:6
yday:322
nano sec:335961248


Get time from string

Sometimes it is necessary to convert a time-displayed string into a timeval or time_t value. To do this, we use the strptime function. As you can see in the code below, the mktime function converts a tm structure into a time_t. By substituting this value into the tv_sec value of the timeval structure, time functions using the timeval structure can be used.

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

using namespace std;
int main()
{
    struct tm file_tm{};
    time_t now;
    struct tm *ntm = &file_tm;
    string file_date = ("2022-10-19 22:03:00");
    strptime(file_date.c_str(), "%Y-%m-%d %H:%M:%S", &file_tm);
    
    now = mktime(&file_tm); //if you need to get time_t value, use mktime function
    timeval strTime;
    strTime.tv_sec = now;   //now you can use strTime related functions

    cout << "year:" << ntm->tm_year + 1900<<endl;
    cout << "month:" << ntm->tm_mon + 1 <<endl;   //0 based index
    cout << "day:" << ntm->tm_mday <<endl;
    cout << "hour:" << ntm->tm_hour <<endl;
    cout << "minutes:" << ntm->tm_min <<endl;
    cout << "secs:" << ntm->tm_sec <<endl;
    cout << "wday:" << ntm->tm_wday <<endl; //sunday(0), monday(1), ..., Saturday(6)
    cout << "yday:" << ntm->tm_yday <<endl; //1 ~ 365    
    return 0;
}


Let's compile and run the codes. It can be seen that the microseconds were obtained. 

[spypiggy@localhost datecompare]$ g++ day_from_file.cpp
[spypiggy@localhost datecompare]$ ./a.out
year:2022
month:10
day:19
hour:22
minutes:3
secs:0
wday:3
yday:291


Get elapsed time

Let's find the elapsed values of two times. Let's find the past time from the string and then calculate the difference from the present time. The most important function is diffime. The difftime function is very simple. Returns the difference between the two variables of type time_t.

Note : the return value of difftime function is double type.


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

using namespace std;
int main()
{
    double diff;
    struct tm file_tm{};
    time_t now, start;
    time(&now);
    
    string file_date = ("2022-10-19 22:03:00");
    strptime(file_date.c_str(), "%Y-%m-%d %H:%M:%S", &file_tm);
    start = mktime(&file_tm);
    diff = difftime(now, start);    //secs between 2 values
    cout << "now:" << now <<endl;
cout << "start:" << start <<endl; cout << "secs:" << diff <<endl; cout << "hour:" << diff / 3600 <<endl; return 0; }


Let's compile and run the codes. 

[spypiggy@localhost datecompare]$ ./a.out
now:1666282667
start:1666184580
sec:98087
hour:27.2464


Obtain dates before and after N days from a particular date

This problem can be easily solved if we understand that the basis of the date-time operation lies in the time_t value. You can add or subtract seconds corresponding to N days.  In the example below, the date around 40 days was obtained as of 22:03 on October 19, 2021.


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

using namespace std;
int main()
{
    struct tm file_tm{};
    time_t past, start, future;
    int N = 40;
    struct tm *ntm;
    
    string file_date = ("2021-10-19 22:03:00");
    strptime(file_date.c_str(), "%Y-%m-%d %H:%M:%S", &file_tm);
    start = mktime(&file_tm);
    past = start - 40 * 3600 * 24;
    future = start + 40 * 3600 * 24;
    
    ntm = localtime(&past);

    cout << "past year:" << ntm->tm_year + 1900<<endl;
    cout << "past month:" << ntm->tm_mon + 1 <<endl;   //0 based index
    cout << "past day:" << ntm->tm_mday <<endl;
    cout << "past hour:" << ntm->tm_hour <<endl;
    cout << "past minutes:" << ntm->tm_min <<endl;
    cout << "past secs:" << ntm->tm_sec <<endl;
    cout << "past wday:" << ntm->tm_wday <<endl; //sunday(0), monday(1), ..., Saturday(6)
    cout << "past yday:" << ntm->tm_yday <<endl << endl; //1 ~ 365    

    ntm = localtime(&future);

    cout << "future year:" << ntm->tm_year + 1900<<endl;
    cout << "future month:" << ntm->tm_mon + 1 <<endl;   //0 based index
    cout << "future day:" << ntm->tm_mday <<endl;
    cout << "future hour:" << ntm->tm_hour <<endl;
    cout << "future minutes:" << ntm->tm_min <<endl;
    cout << "future secs:" << ntm->tm_sec <<endl;
    cout << "future wday:" << ntm->tm_wday <<endl; //sunday(0), monday(1), ..., Saturday(6)
    cout << "future yday:" << ntm->tm_yday <<endl; //1 ~ 365    

    return 0;
}


Let's compile and run the codes. 

[spypiggy@localhost datecompare]$ ./a.out
past year:2021
past month:9
past day:9
past hour:22
past minutes:3
past secs:0
past wday:4
past yday:251

future year:2021
future month:11
future day:28
future hour:22
future minutes:3
future secs:0
future wday:0
future yday:331



댓글

이 블로그의 인기 게시물

MQTT - C/C++ Client

RabbitMQ - C++ Client #1 : Installing C/C++ Libraries