I'd like to get the unix timestamp of the beginning of current (or any given maybe) hour in c/c++.
I have this:
time_t get_current_hour() {
time_t beginning_of_hour;
struct tm * ptm;
time(&beginning_of_hour);
ptm = gmtime(&beginning_of_hour);
ptm->tm_min = 0;
ptm->tm_sec = 0;
ptm->tm_zone = (char*) "GMT";
beginning_of_hour = mktime(ptm);
return beginning_of_hour;
}
Which works, but under high load many of the result are not the beginning of the current hour but the actual time.
Is there a better way to solve the problem?
Why does the function returns the current time?
Please advise,
Akos
You can do it all with time_t, without breaking it apart and rebuilding.
Just round it down to a multiple of 3600:
time_t get_current_hour(void) {
time_t now;
time(&now);
return now - (now % 3600);
}
Perhaps it isn't nice to treat time_t as an integer. But I think it is guaranteed to be seconds since the epoch, so it should be fine.
It could be that you have a multi-threaded application, and calls to gmtime are not thread-safe (re-entrant). If this is the case, try using the re-entrant version: gmtime_r
Is your application by any chance multi-threaded? gmtime returns a
pointer to static memory, which will be overwritten the next time the
function is called. Such functions are not thread-safe (and this is
about the only thing I can think of which would account for your
symptoms). Under Unix, there is also a gmtime_r, which allows you to
declare a local buffer, and avoid the issue; Windows has a _gmtime_s
which is (I think) similar.
Related
I'm trying to print a timestamp like this.
2018-05-24T20:16:07.339271
I don't want to use Boost or any third party libraries. I want to only use the standard library. I'm using Clang 6, so I should be able to use C++ 17 if necessary.
I started looking at chrono and have something like this.
auto now = std::chrono::high_resolution_clock::now();
But, I'm unsure how to get the datetime format that I want from above.
guess your best bet is using std::localtime + std::put_time
The following code uses standard C++ only. The data contained in *loc_time and milli_secs can be used to produce the desired output in local time. To get the output in UTC, use std::gmtime instead of std::localtime.
// get actual system time
const auto now = std::chrono::system_clock::now();
// get seconds since 1970/1/1 00:00:00 UTC
const auto sec_utc = std::chrono::system_clock::to_time_t(now);
// get pointer to tm struct (not thread safe!)
const auto loc_time = std::localtime(&sec_utc);
// get time_point from sec_utc (note: no milliseconds)
const auto now_s = std::chrono::system_clock::from_time_t(sec_utc);
// get milliseconds (difference between now and now_s
const auto milli_secs = std::chrono::duration<double, std::milli>(now - now_s).count() * .001;
standard library c++ does not provide a proper date type, so you can use
structs and functions from c which is inherited on c++. <ctime> header
file need to include in c++ program. i think below code will help you.
time_t now = time(0);
cout<<now<<endl;
tm *lt = localtime(&now);
I have a lot of strings that are in the form "HH:MM" and I constantly have to do arithmetic on them (for example add 5 minutes, add 24 hours, etc).
I am wondering if there is any built in class in the standard library that can handle such arithmetic instead of having to manually change the string and handle corner cases?
If you don't have strptime available, and if you have <chrono> and don't want to fool around with the C API, you can use Howard Hinnant's free, open-source, portable datetime library to write helpers to convert to and from std::chrono::minutes.
So convert from string to minutes, do whatever computation you need, and then convert back to string:
#include "date.h"
#include <iostream>
#include <string>
#include <sstream>
std::chrono::minutes
to_minutes(const std::string& s)
{
std::istringstream in{s};
in.exceptions(std::ios::failbit);
std::chrono::minutes m;
in >> date::parse("%H:%M", m);
return m;
}
std::string
to_string(std::chrono::minutes m)
{
return date::format("%H:%M", m);
}
int
main()
{
using namespace std::chrono_literals;
std::cout << to_string(to_minutes("5:47") + 2h + 168min) << '\n';
}
Output:
10:35
This library has been ported to recent versions of VS, gcc and clang.
You can also use this library to work with different precisions quite seamlessly, for example seconds, or even milliseconds, and even mix all the precisions you need together:
std::chrono::milliseconds
to_milliseconds(const std::string& s)
{
std::istringstream in{s};
in.exceptions(std::ios::failbit);
std::chrono::milliseconds ms;
in >> date::parse("%T", ms);
return ms;
}
std::string
to_string(std::chrono::milliseconds ms)
{
return date::format("%T", ms);
}
// ...
std::cout << to_string(to_minutes("5:47") + 2h + 168min +
122s + 465ms + to_milliseconds("1:23:02.123")) << '\n';
Output:
12:00:04.588
Using <ctime> you can convert your HH:MM string to a struct tm as follows:
struct tm time_components;
memset(&time_components, 0, sizeof(struct tm));
time_components.tm_year = 2017;
strptime("01:45", "%H:%M", &time_components);
This assumes you have strptime available. If not, use sscanf or something similar to extract your hour and minute components--I'm sure you're doing this already. I'm setting tm_year there because otherwise it's zero, which is not a valid year for the conversion to time_t later on.
We can easily convert the tm struct back into a HH:MM string using strftime.
char buf[6];
strftime(buf, 6, "%H:%M", &time_components);
printf("time_components before manipulation: %s\n", buf);
But how about manipulating it? My first thought was 'just convert to time_t and add/subtract however many seconds you want'. But time_t isn't guaranteed to be in seconds, so don't do that. Instead, add whatever number of minutes you like to the tm_min component of the tm struct, then call mktime with it, which will correctly handle any values that are outside the normal bounds of hours/minutes/seconds. At that point you have a time_t, which we don't want to mess with, so just convert that back into a tm using localtime. localtime will mirror the conversion that occurred in mktime, so you shouldn't have to worry about time zones and so on. Now you've essentially normalized the tm structure, and your overflowing minutes have been converted to hours, and your overflowing hours have been converted to days.
time_components.tm_min += 65; // Add 65 minutes. Negative values work as expected too!
time_t temp_time = mktime(&time_components);
struct tm* adjusted_time = localtime(&temp_time);
strftime(buf, 6, "%H:%M", adjusted_time);
printf("adjusted_time: %s\n", buf);
That adjusted_time pointer seems to point to an internal tm struct that will change in any subsequent calls to mktime or gmtime, FYI.
There's no doubt this is a fairly hellish approach. If all you need to do is handle minute/hour overflow and simple arithmetic, I'd be tempted to roll my own or look elsewhere.
http://en.cppreference.com/w/cpp/chrono/duration supports the arithmetic and types you want, but I don't think you can construct from strings.
However you can with Boost Chrono. I tend to prefer it for most cases, because if I'm dealing with the problem of hours and minutes, I'll probably end up dealing with dates too in the future.
This question already has answers here:
Getting the current time as a YYYY-MM-DD-HH-MM-SS string
(2 answers)
Closed 8 years ago.
I have a function which returns a timestamp in unix time as int.
I need to convert this int to a string dd/mm/yy in local time. The "local" part is causing me problems, if it weren't for that, I could have just made my own function to convert it.
I have searched around , and it seems the ctime class from the standard library would be ideal for this, in a manner like this:
int unixtime;
std::cout << std::asctime(std::localtime(unixtime));
Sadly, only *time_t is accepted. Is there any way I can convert int into this format, or any better way to get local time from unix time as int?
time_t is by definition an arithmetic type, you can just do:
time_t ts = unixtime;
std::cout << std::asctime(std::localtime(&ts));
'/* localtime example */
#include <stdio.h> /* puts, printf */
#include <time.h> /* time_t, struct tm, time, localtime */
int main ()
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
printf ("Current local time and date: %s", asctime(timeinfo));
return 0;
}'
You can simply use type time_t it will give you the time.
"The ctime(), gmtime() and localtime() functions all take an argument of data type time_t which represents calendar time. When interpreted as an absolute time value, it represents the number of seconds elapsed since the Epoch, 1970-01-01 00:00:00 +0000 (UTC)."
sources:
http://linux.die.net/man/3/ctime
http://linux.die.net/man/7/time
To print current time in dd/mm/yy, you may try the following:
#include <iostream>
#include <ctime>
int main(int argc, const char** argv)
{
char date_buff[40];
time_t time_value = time(0);
struct tm* my_tm = localtime(&time_value);
strftime(date_buff, sizeof(date_buff), "%d/%m/%y\n", my_tm);
std::cout << date_buff << std::endl;
return 0;
}
The type of time_t is not guaranteed by the C specification.
Unix and POSIX-compliant systems implement the time_t type as a signed integer (typically 32 or 64 bits wide) which represents the number of seconds since the start of the Unix epoch. So you may just do the following
std::time_t my_time = static_cast<std::time_t>(unixtime);
However, it is better to not to assume time to be an int and replace your time function with the appropriate time handling and return std::time_t or struct tm
This question already has answers here:
localtime vs localtime_s and appropriate input arguments
(3 answers)
Closed 8 years ago.
I'm attempting to create timestamps for my program. On my sister's Mac (using Xcode 4.2) this code works perfectly fine:
struct tm * timeInfo;
time_t rawtime;
time (&rawtime);
timeInfo = localtime (&rawtime);
string timestamp(asctime(timeInfo));
However, on my PC running Visual Studio 2012 I get errors for localtime and asctime that tell me they are unsafe functions and it recommends using localtime_s and asctime_s. However, the function parameters are different. I've tried researching the functions as best I can, but I can't get it to work.
Any help with getting that to work would be much appreciated.
edit:
struct tm * timeInfo;
time_t rawtime;
time (&rawtime);
timeInfo = localtime_s (&rawtime);
string timestamp(asctime_s(timeInfo));
The reason those functions have different parmaters is that the lack of safety is caused by only have a single parameter. In particular, asctime() uses a single buffer to return the time. So if you do something like:
char *s1 = asctime((time_t)0); // 1-Jan-1970 00:00:00 or something like that.
time_t t = time();
char *s2 = asctime(t);
cout << "1970: " << s1 << " now:" << s2 << endl;
Then you will not see two different times printed, but the current time printed twice, as both s1 and s2 point to the same string.
The same applies to localtime, which returns a pointer to struct tm - but it's always the same struct tm, so you if you do:
struct tm* t1 = localtime(0);
struct tm* t2 = localtime(time());
you will get the same values in t1 and t2 (with the "current" time, not 1970).
So, to fix this problem, asctime_s and localtime_s have an extra parameter that is used to store the data into. asctime_s also have a second extra parameter to tell the function how much space there is in the storage buffer, as otherwise, it could overflow that buffer.
What is the best way to convert UnixTime to a date?
Is there a function for it or an algorithm?
Unix time is seconds since epoch (1970-01-01). Depending on what you mean, you can convert it to a struct tm with localtime or convert it to a string with strftime.
time_t t = time(NULL);
struct tm *tm = localtime(&t);
char date[20];
strftime(date, sizeof(date), "%Y-%m-%d", tm);
As the manual to localtime states
The return value points to a statically allocated
struct which might be overwritten by subsequent calls to any of the
date and time functions.
This is what some refer to as data races. This happens when two or more threads call localtime simultaneously.
To protect from this, some suggest using localtime_s, which is a Microsoft only function. On POSIX systems, you should use localtime_r instead
The localtime_r() function does the same,
but stores the data in a user-supplied struct.
Usage would look like
time_t t = time(NULL);
struct tm res;
localtime_r(&t, &res);
I'm going to assume you have the time in a time_t. First you need to convert that to a struct tm. You can do this with localtime or gmtime, depending on whether you want to use the local timezone or GMT.
Then you can format that struct tm as a string with strftime. For example, to get a date like 2012-11-24 you'd use the format "%Y-%m-%d".
See also Convert Unix/Linux time to Windows FILETIME
This function should convert from UnixTime into Windows SYSTEMTIME
SYSTEMTIME intChromeTimeToSysTime(long long int UnixTime)
{
ULARGE_INTEGER uLarge;
uLarge.QuadPart = UnixTime;
FILETIME ftTime;
ftTime.dwHighDateTime = uLarge.HighPart;
ftTime.dwLowDateTime = uLarge.LowPart;
SYSTEMTIME stTime;
FileTimeToSystemTime(&ftTime, &stTime);
return stTime;
}