C++ function that returns system date - c++

I need function in c++ that allows me to retrieve and store the system date. I have a class for storing dates.

Dealing with dates and time is difficult, thats why people use libraries. I prefer boost::date_time.
boost::posix_time::ptime local_time = boost::posix_time::second_clock::local_time();
boost::gregorian::date d = local_time.date();
d is a current date in local time, which use computer timezone settings. To get UTC time you can use boost::posix_time::second_clock::universal_time().

From time.h:
struct tm {
int tm_sec; /* seconds after the minute - [0,59] */
int tm_min; /* minutes after the hour - [0,59] */
int tm_hour; /* hours since midnight - [0,23] */
int tm_mday; /* day of the month - [1,31] */
int tm_mon; /* months since January - [0,11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday - [0,6] */
int tm_yday; /* days since January 1 - [0,365] */
int tm_isdst; /* daylight savings time flag */
};
time_t time(time_t * timer);
struct tm* gmtime(const time_t *timer);
struct tm* localtime(const time_t * timer);

For C++ on Windows look at the Windows time functions, in particular GetSystemTime.

Just to add, GetSystemTime gives you UTC time, while to get the TimeZone adjusted time you need to use GetLocalTime.
One more difference between WinBase time function (through windows.h) compared to time.h functions is windows time functions are reliable all the way back to 1601, while time.h is only till 1900 onwards. I am not sure if that is something which you need to consider.

time()
But also see localtime and asctime for display

Here's what I ended up using (nowtm is populated with current system time):
time_t rawtime=time(NULL);
tm* nowtm = gmtime(&rawtime);
where tm is defined:
struct tm {
int tm_sec; /* seconds after the minute - [0,59] */
int tm_min; /* minutes after the hour - [0,59] */
int tm_hour; /* hours since midnight - [0,23] */
int tm_mday; /* day of the month - [1,31] */
int tm_mon; /* months since January - [0,11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday - [0,6] */
int tm_yday; /* days since January 1 - [0,365] */
int tm_isdst; /* daylight savings time flag */
};

I wrote quite similar answer a few minutes ago. You can use chrono available in C++11.
http://en.cppreference.com/w/cpp/chrono/time_point

Related

Convert the seconds since "midnight 1904-1-1" to a date-time string

In some multimedia metadata, there may be date-time in seconds since
midnight, Jan. 1, 1904, in UTC time.
As I know, the date time function is normally based on 1970-1-1 midnight in C/C++ standard library, at least in Visual C++, is there a function in C/C++/Win32-API to convert the seconds since "1904-1-1 midnight" to a date time string, like as "hh:mm:ss MM. dd, yyyy" or other format string or a structure like as "struct tm"?
struct tm
{
int tm_sec; // seconds after the minute - [0, 60] including leap second
int tm_min; // minutes after the hour - [0, 59]
int tm_hour; // hours since midnight - [0, 23]
int tm_mday; // day of the month - [1, 31]
int tm_mon; // months since January - [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0, 6]
int tm_yday; // days since January 1 - [0, 365]
int tm_isdst; // daylight savings time flag
};
Solution#1:
int main()
{
SYSTEMTIME systm;
memset(&systm, 0, sizeof(systm));
systm.wYear = 1904;
systm.wMonth = 1;
systm.wDay = 1;
FILETIME filetm;
if (SystemTimeToFileTime(&systm, &filetm) == FALSE){
printf("Failed to convert system time to file-time.\n");
return 0;
}
ULARGE_INTEGER nanoSeconds;
nanoSeconds.HighPart = filetm.dwHighDateTime;
nanoSeconds.LowPart = filetm.dwLowDateTime;
nanoSeconds.QuadPart += 3600ULL * 10000000; // add 1hour based on 1904/1/1 midnight
filetm.dwHighDateTime = nanoSeconds.HighPart;
filetm.dwLowDateTime = nanoSeconds.LowPart;
if (FileTimeToSystemTime(&filetm, &systm) == FALSE){
printf("Failed to convert file-time to system time.\n");
return 0;
}
printf("New system time by adding 1 hour: %d-%02d-%02d %02d:%02d:%02d.%03d\n",
systm.wYear, systm.wMonth, systm.wDay,
systm.wHour, systm.wMinute, systm.wSecond, systm.wMilliseconds);
return 0;
}
The output is
New system time by adding 1 hour: 1904-01-01 01:00:00.000
Solution#2:
With #Howard Hinnant's date.h, it can also solve this issue, please see the sample code provided by him https://stackoverflow.com/a/49733937/3968307
This would be a good time to use Howard Hinnant's free, open-source date/time library:
#include "date/date.h"
#include <cstdint>
#include <iostream>
#include <string>
std::string
convert(std::int64_t seconds_since_1904)
{
using namespace date;
using namespace std::chrono;
constexpr auto offset = sys_days{January/1/1970} - sys_days{January/1/1904};
return format("%T %m.%d, %Y", sys_seconds{seconds{seconds_since_1904}} - offset);
}
int
main()
{
std::cout << convert(3'606'124'378) << '\n';
}
Output:
13:12:58 04.09, 2018
Update
The above code will port to C++20 (when it ships) by:
Change #include "date/date.h" to #include <chrono>
Change using namespace date; to using namespace std;
Change "%T %m.%d, %Y" to "{:%T %m.%d, %Y}"
As you can easily calculate with any available spreadsheet application in your system, the difference in seconds between those two timestamps (assumed both are in UTC time) the difference in seconds from 1/1/1904 to 1/1/1970 is 2,082,844,800 sec. So the conversion function from a unix timestamp to your time, consists in adding 2082844800 to the unix timestamp you receive from any of the time functions. In case you want to pass back from a timestamp in your time to unix timestamp, then subtract that fixed value from your timescale. Beware that that number does not fit in a signed int so you must use probably a 64bit number to manage properly all those timestamps. Worse if you want to use nanoseconds resolution.
I don't guess the reason of using that strange epoch timestamp, but to illustrate a practical and in use application of such differences, there's a timestamp in internet that uses an epoch close to that, that is the NTP (Network Time Protocol) timestamp, that is based on 1/1/1900 epoch and has a resolution of 1/2**32 sec. that is around 232 ps. for a specification of this protocol, see RFC-5905
The time problem here practically begs you to write your own code for it. The year 1900 is an exception since it is divisible by 4 but still is not a leap year, so by starting in 1904 you can avoid that particular exception and use the fact that there are 1461 days in every four-year period starting with 1904.

math with ctime and time_t

Does anyone know how todo math with ctime? I need to be able to get the time in sec in "time_t" (like it normally does) and then subtract a set number of seconds from it before inputting time_t into ctime to get the time and date.
so basically it would calculating the date of so many sec ago.
time_t
The most basic representation of a date and time is the type time_t. The value of a time_t variable is the number of seconds since January 1, 1970, sometimes call the Unix epoch. This is the best way to internally represent the start and end times for an event because it is easy to compare these values.
struct tm
While time_t represents a date and time as a single number, struct tm represents it as a struct with a lot of numbers:
struct tm
{
int tm_sec; /* Seconds. [0-60] (1 leap second) */
int tm_min; /* Minutes. [0-59] */
int tm_hour; /* Hours. [0-23] */
int tm_mday; /* Day. [1-31] */
int tm_mon; /* Month. [0-11] */
int tm_year; /* Year - 1900. */
int tm_wday; /* Day of week. [0-6] */
int tm_yday; /* Days in year.[0-365] */
int tm_isdst; /* DST. [-1/0/1]*/
};
Conversion
You can convert a time_t value to a struct tm value using the localtime function:
struct tm startTM;
time_t start;
/* ... */
startTM = *localtime(&start);
So,you can subtract subtract a set number of seconds like this
startTm.tm_sec -= somesecond;
add convert to time_t like this
struct tm startTM;
time_t start;
/* ... */
start = mktime(&startTM);
and use ctime fun to convert date
ctime(&start)
hope it can helpful!
You can try:
time_t now = time( NULL);
struct tm now_tm = *localtime( &now);
now_tm.tm_sec -= 50; // subtract 50 seconds to the time
now_tm.tm_sec +=1000; // add 1000 sec to the time
printf( "%s\n", asctime( &now_tm));
time_t is an integral type. It always represents a number of seconds, so you can freely add/subtract integers from it.
Example:
time_t now = time(nullptr);
time_t one_minute_ago = now - 60;
std::cout << ctime(&one_minute_ago) << std::endl;

Wrong time with localtime()

Running dateon my server results in the correct time. But using localtime() in C(++) I'm getting the wrong time.
Running date: Fr 30. Nov 12:15:36 CET 2012
Using localtime(): Fr 30 Nov 2012 11:15:36 CET
What's wrong here?
OS: Debian 5.0.10
Some code:
struct tm* today;
today = localtime(...);
strftime(timeBuffer,50,myConnection.getMetaData().getDateFormat().c_str(),today);
disclaimer : This answer was written before any mention of strftime was added, and was a gut reaction to the 1 hour difference in the timestamps. Looking back at it now, that 1 hour difference couldn't have been due to DST (because the dates are not in summer), but is likely showing a UTC timestamp (1 hour difference between UTC and CET).
Unfortunately, the answer was accepted, and so I can't delete it. Even more unfortunate, is that the question as it stands is not answerable without additional information.
Leaving the original answer here for full transparency, but know that it does not address the question as asked :
The struct tm returned by localtime has a tm_isdst field that indicates whether daylight saving time (DST) is in effect. You need to take that field into account when formatting the time.
Try using asctime to format the time eg. :
puts(asctime(today));
I have experienced the same problem while writing a date adjustment routine. Adding 86400 seconds (= 1 day) to any given datetime value should result in incrementing the datetime value by one day. However in testing, the output value invariably added exactly one hour to the expected output. For instance, '2019-03-20 00:00:00' incremented by 86400 seconds resulted in '2019-03-21 01:00:00'. The reverse also occurred: '2019-03-21 00:00:00' decremented by -86400 resulted in '2019-03-20 01:00:00'.
The solution (inexplicably) was to subtract 3600 seconds (one hour) from the final interval before applying it to the input datetime.
The solution (thanks to helpful comments from #Lightness-Races-in-Orbit) was to set tm_isdst to -1 before calling mktime(). This tells mktime() that the DST status for the input datetime value is unknown, and that mktime() should use the system timezone databases to determine the correct timezone for the input datetime value.
The function (as corrected below) allows for any integer adjustment of days and now produces consistently correct results:
#include <stdio.h>
#include <string.h>
#include <time.h>
/*******************************************************************************
* \fn adjust_date()
*******************************************************************************/
int adjust_date(
char *original_date,
char *adjusted_date,
char *pattern_in,
char *pattern_out,
int adjustment,
size_t out_size)
{
/*
struct tm {
int tm_sec; // seconds 0-59
int tm_min; // minutes 0-59
int tm_hour; // hours 0-23
int tm_mday; // day of the month 1-31
int tm_mon; // month 0-11
int tm_year; // year minus 1900
int tm_wday; // day of the week 0-6
int tm_yday; // day in the year 0-365
int tm_isdst; // daylight saving time
};
*/
struct tm day;
time_t one_day = 86400;
// time_t interval = (one_day * adjustment) - 3600;
time_t interval = (one_day * adjustment);
strptime(original_date, pattern_in, &day);
day.tm_isdst = -1;
time_t t1 = mktime(&day);
if (t1 == -1) {
printf("The mktime() function failed");
return -1;
}
time_t t2 = t1 + interval;
struct tm *ptm = localtime(&t2);
if (ptm == NULL) {
printf("The localtime() function failed");
return -1;
}
strftime(adjusted_date, out_size, pattern_out, ptm);
return 0;
}
/*******************************************************************************
* \fn main()
*******************************************************************************/
int main()
{
char in_date[64] = "20190321000000" ,
out_date[64],
pattern_in[64] = "%Y%m%d%H%M%S",
pattern_out[64] = "%Y-%m-%d %H:%M:%S";
int day_diff = -1,
ret = 0;
size_t out_size = 64;
memset(out_date, 0, sizeof(out_date));
ret = adjust_date(in_date, out_date, pattern_in, pattern_out, day_diff, out_size);
if (ret == 0)
{
printf("Adjusted date: '%s'\n", out_date);
}
return ret;
}
Hopefully, this will be of some help to somebody. Your constructive comments are greatly appreciated.
handling date time is very error prone and usually badly tested. i always recommend using boost::date_time http://www.boost.org/doc/libs/1_52_0/doc/html/date_time.html
here are nice examples http://en.highscore.de/cpp/boost/datetime.html
Did you try this ? :
time_t rawtime;
struct tm * today;
time ( &rawtime );
today= localtime ( &rawtime );
puts(asctime (today));

retrieving time including time zone using ctime

I want to retrieve time zone from struct tm as the format below
2011-12-32 12:13:05 +0530(obtained using gtime)
I could get the first two sets but could not get the way getting the time zone value. Please let me know how it should get the time zone using c++ time.
Regards,
iSight
If you really want to use standard C library to get timezone, try using external variable 'timezone' declared in time.h. Keep in mind that its value is set after tzset() function call. Every time conversion function that depends on the timezone implicitly calls this function. As an alternative you can call tzset() explicitly.
The 'timezone' variable should be declared like this in time.h:
extern long timezone;
It contains time difference between local time and UTC in seconds.
Also you can use exern char* tzname[2] to get the symbolic timezone names for DST and non-DST periods.
You can not calculate the timezone information from struct tm directly, unless you know exactly the UTC time corresponding to time stored in that structure;
I think tm structure retrieved via time.h contains timezone information, if all you require is difference from GMT.
struct tm {
int tm_sec; /* seconds after the minute [0-60] */
int tm_min; /* minutes after the hour [0-59] */
int tm_hour; /* hours since midnight [0-23] */
int tm_mday; /* day of the month [1-31] */
int tm_mon; /* months since January [0-11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday [0-6] */
int tm_yday; /* days since January 1 [0-365] */
int tm_isdst; /* Daylight Savings Time flag */
long tm_gmtoff; /* offset from CUT in seconds */
char *tm_zone; /* timezone abbreviation */
};
Something like the following can help:
uint64_t diff;
{
time_t secs = time (NULL);
tm timeParts;
memset(&timeParts, 0, sizeof(timeParts));
tm *timeInfo = localtime_r( &secs, &timeParts );
diff = mktime( timeInfo );
memset(&timeParts, 0, sizeof(timeParts));
timeInfo = gmtime_r ( &secs, &timeParts );
diff -= mktime( timeInfo );
}
return diff;
Please note that this code does something else but it shows all the functions that you can use to retrieve information that you may require.

Converting a unix time to a human readable format

I'm building my own unix time to human readable conversion, and I'm stuck.
I can extract the year just fine, but the day is proving too tricky.
/*
Converts a 32-bit number of seconds after 01-01-1970 to a _SYSTEMTIME structure
*/
static _SYSTEMTIME Convert(unsigned long a_UnixTime)
{
newtime.wMilliseconds = 0;
newtime.wYear = (unsigned long)((float)a_UnixTime / (364.24f * 24.f * 60.f * 60.f));
newtime.wDay = (a_UnixTime - (unsigned long)((float)newtime.wYear * 364.24f * 24.f * 60.f * 60.f)); // returns 65177
return newtime;
}
Or is there a built-in function that I've overlooked?
Thanks in advance.
UPDATE:
Hmm... it seems Windows Mobile doesn't support strftime, time or localtime, so I'll still have to roll my own. :(
Are you looking for gmtime?
struct tm * gmtime(const time_t *clock);
External declarations, as well as the tm structure definition, are contained in the <time.h> include file. The tm structure includes at least the following fields:
int tm_sec; /* seconds (0 - 60) */
int tm_min; /* minutes (0 - 59) */
int tm_hour; /* hours (0 - 23) */
int tm_mday; /* day of month (1 - 31) */
int tm_mon; /* month of year (0 - 11) */
int tm_year; /* year - 1900 */
int tm_wday; /* day of week (Sunday = 0) */
int tm_yday; /* day of year (0 - 365) */
int tm_isdst; /* is summer time in effect? */
char *tm_zone; /* abbreviation of timezone name */
long tm_gmtoff; /* offset from UTC in seconds */
If you want to format to print, you need strftime(), it's the standard solution, used together with e.g. localtime() to convert the raw timestamp to a more human-friendly format.