When I run this in my ubuntu, I get the bottom result. What could go wrong with this? There is no way the result year is 1970, and see when I do the reconvert the ms back, the result aren't the same. But when I run it at http://coliru.stacked-crooked.com/ it was fine.
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <string>
#include <iostream>
int main()
{
using namespace boost::posix_time;
ptime time_t_epoch(boost::gregorian::date(1970,1,1));
auto ms = (boost::posix_time::microsec_clock::local_time() - time_t_epoch).total_microseconds();
std::cout << "ms: " << ms << std::endl;
std::cout << "ms: " << boost::posix_time::microseconds(ms).total_microseconds() << std::endl;
ptime newTime = time_t_epoch + boost::posix_time::microseconds(ms);
std::cout << boost::posix_time::to_iso_string(time_t_epoch) << std::endl;
std::cout << boost::posix_time::to_iso_string(newTime) << std::endl;
std::stringstream ss;
ss << newTime;
std::cout << ss.str()<< std::endl;
}
Result:
ms: 1424976249761218
ms: 4576956085582
19700101T000000
19700222T232236.085582
1970-Feb-22 23:22:36.085582
Machine environment = Ubuntu 12 + cmake 2.8.7 + boost 1.48.0.2
1970/01/01 + 4576956085582 microseconds -> 1970-Feb-22 is correct
1970/01/01 + 1424976249761218 microseconds -> 2015-Feb-26 so ms is presumably correct
What is not correct is that
boost::posix_time::microseconds(ms).total_microseconds() != ms
It might be related to this bug https://svn.boost.org/trac/boost/ticket/3487 though I'm not sure.
Related
How do I get a uint unix timestamp in C++? I've googled a bit and it seems that most methods are looking for more convoluted ways to represent time. Can't I just get it as a uint?
C++20 introduced a guarantee that time_since_epoch is relative to the UNIX epoch, and cppreference.com gives an example that I've distilled to the relevant code, and changed to units of seconds rather than hours:
#include <iostream>
#include <chrono>
int main()
{
const auto p1 = std::chrono::system_clock::now();
std::cout << "seconds since epoch: "
<< std::chrono::duration_cast<std::chrono::seconds>(
p1.time_since_epoch()).count() << '\n';
}
Using C++17 or earlier, time() is the simplest function - seconds since Epoch, which for Linux and UNIX at least would be the UNIX epoch. Linux manpage here.
The cppreference page linked above gives this example:
#include <ctime>
#include <iostream>
int main()
{
std::time_t result = std::time(nullptr);
std::cout << std::asctime(std::localtime(&result))
<< result << " seconds since the Epoch\n";
}
#include<iostream>
#include<ctime>
int main()
{
std::time_t t = std::time(0); // t is an integer type
std::cout << t << " seconds since 01-Jan-1970\n";
return 0;
}
The most common advice is wrong, you can't just rely on time(). That's used for relative timing: ISO C++ doesn't specify that 1970-01-01T00:00Z is time_t(0)
What's worse is that you can't easily figure it out, either. Sure, you can find the calendar date of time_t(0) with gmtime, but what are you going to do if that's 2000-01-01T00:00Z ? How many seconds were there between 1970-01-01T00:00Z and 2000-01-01T00:00Z? It's certainly no multiple of 60, due to leap seconds.
As this is the first result on google and there's no C++20 answer yet, here's how to use std::chrono to do this:
#include <chrono>
//...
using namespace std::chrono;
int64_t timestamp = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
In versions of C++ before 20, system_clock's epoch being Unix epoch is a de-facto convention, but it's not standardized. If you're not on C++20, use at your own risk.
#include <iostream>
#include <sys/time.h>
using namespace std;
int main ()
{
unsigned long int sec= time(NULL);
cout<<sec<<endl;
}
I created a global define with more information:
#include <iostream>
#include <ctime>
#include <iomanip>
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__) // only show filename and not it's path (less clutter)
#define INFO std::cout << std::put_time(std::localtime(&time_now), "%y-%m-%d %OH:%OM:%OS") << " [INFO] " << __FILENAME__ << "(" << __FUNCTION__ << ":" << __LINE__ << ") >> "
#define ERROR std::cout << std::put_time(std::localtime(&time_now), "%y-%m-%d %OH:%OM:%OS") << " [ERROR] " << __FILENAME__ << "(" << __FUNCTION__ << ":" << __LINE__ << ") >> "
static std::time_t time_now = std::time(nullptr);
Use it like this:
INFO << "Hello world" << std::endl;
ERROR << "Goodbye world" << std::endl;
Sample output:
16-06-23 21:33:19 [INFO] main.cpp(main:6) >> Hello world
16-06-23 21:33:19 [ERROR] main.cpp(main:7) >> Goodbye world
Put these lines in your header file. I find this very useful for debugging, etc.
Windows uses a different epoch and time units: see
Convert Windows Filetime to second in Unix/Linux
What std::time() returns on Windows is (as yet) unknown to me (;-))
I'm trying to use a time_point to effectively represent forever by setting it to seconds::max which, I believe, should represent that much time since epoch. When doing this, though, I get -1 as the time since epoch in the resulting time_point. What am I not understanding?
#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main() {
auto tp1 = system_clock::time_point( seconds::zero() );
auto tp2 = system_clock::time_point( seconds::max() );
cout << "tp1: " << duration_cast<seconds>(tp1.time_since_epoch()).count() << endl;
cout << "tp2: " << duration_cast<seconds>(tp2.time_since_epoch()).count() << endl;
return 0;
}
The output running that is:
tp1: 0
tp2: -1
Here's a little quick&dirty program to explore the limits of system_clock time_points at different precisions:
#include <chrono>
#include <iostream>
using days = std::chrono::duration
<int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
using years = std::chrono::duration
<double, std::ratio_multiply<std::ratio<146097, 400>, days::period>>;
template <class Rep, class Period>
void
max_limit(std::chrono::duration<Rep, Period> d)
{
std::cout << "[" << Period::num << '/' << Period::den << "] ";
std::cout << years{d.max()}.count() + 1970 << '\n';
}
int
main()
{
using namespace std;
using namespace std::chrono;
max_limit(nanoseconds{});
max_limit(microseconds{});
max_limit(milliseconds{});
max_limit(seconds{});
}
This will output the year (in floating point) that time_point<system_clock, D> will max out at for any duration D. This program outputs:
[1/1000000000] 2262.28
[1/1000000] 294247
[1/1000] 2.92279e+08
[1/1] 2.92277e+11
Meaning system_clock based on nanoseconds overflows in the year 2262. If you coarsen that to microseconds, you overflow in the year 294,247. And so on.
Once you coarsen to seconds, the max goes out to a ridiculous range. But when you convert that back to system_clock::time_point, which is at least as fine as microseconds, and perhaps as fine as nanoseconds (depending on your platform), you just blow it out of the water.
To solve your problem I recommend:
auto M = system_clock::time_point::max();
Adding a few more diagnostics shows the issue (on my system):
#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main() {
auto tp1 = system_clock::time_point( seconds::zero() );
auto tp2 = system_clock::time_point( seconds::max() );
using type = decltype(system_clock::time_point(seconds::zero()));
cout << type::duration::max().count() << endl;
cout << type::duration::period::den << endl;
cout << type::duration::period::num << endl;
cout << seconds::max().count() << endl;
cout << milliseconds::max().count() << endl;
cout << "tp1: " << duration_cast<seconds>(tp1.time_since_epoch()).count() << endl;
cout << "tp2: " << duration_cast<seconds>(tp2.time_since_epoch()).count() << endl;
return 0;
}
For me, the denominator value is 1,000,000 for the system_clock's time_point. Thus max seconds is going to overflow it when converted up.
I am using Boost.Date_time to get the time difference between two dates. I want the code to consider DST change as well during these days and give me the correct interval.
Consider this example. On 1-Nov-2015, the DST is going to change in USA. At 2:00 hours, the clock will be moved back to 1:00. The output of the below code doesn't reflect that. It gives 23 hours as the difference.
date d1(2015, 11, 1);
ptime nov1_00(d1, hours(0));
ptime nov1_23(d1, hours(23));
seconds = (nov1_23 - nov1_00).total_seconds();
Output:
2015-Nov-01 00:00:00. 2015-Nov-01 23:00:00. Seconds: 82800
Is there a way in boost to specify the DST requirement in this scenario?
You should be using local times:
Live On Coliru
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/local_time/local_date_time.hpp>
#include <boost/date_time/local_time/local_time_io.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
int main() {
namespace lt = boost::local_time;
namespace pt = boost::posix_time;
using date = boost::gregorian::date;
lt::tz_database db;
db.load_from_file("/home/sehe/custom/boost/libs/date_time/data/date_time_zonespec.csv");
//for (auto region : db.region_list()) std::cout << region << "\n";
auto NY = db.time_zone_from_region("America/New_York");
date const d1(2015, 11, 1);
lt::local_date_time nov1_00(d1, pt::hours(0), NY, true);
lt::local_date_time nov1_23(d1, pt::hours(23), NY, false);
lt::local_time_period period(nov1_00, nov1_23);
std::cout << "period: " << period << "\n";
std::cout << "duration: " << period.length() << "\n";
// if you insist:
auto seconds = (nov1_23 - nov1_00).total_seconds();
std::cout << "seconds: " << seconds << "\n";
}
Prints:
period: [2015-Nov-01 00:00:00 EDT/2015-Nov-01 22:59:59.999999 EST]
duration: 24:00:00
seconds: 86400
I am using the following code to get the current date time (Mountain time)
const boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
//In mountain time I get now = 2013-Apr-08 20:44:22
Now I am using the following method for conversion
ptime FeedConnector::MountaintToEasternConversion(ptime coloTime)
{
return boost::date_time::local_adjustor <ptime, -5, us_dst>::utc_to_local(coloTime);
}
//This function is suppose to give me the time in NewYork (East standard time) and I am getting
2013-Apr-08 16:44:22
Thsi time is wrong any suggestion where I am going wrong ?
As far as I understand wrong time means that it is has one hour difference to expected, i.e. -4 hours instead of expected -5 hours. If yes, then the problem is that the us_std type is pointed as the last parameter of the local_adjustor declaration. If to specify no_dst instead of the use_dst. The code works as expatiated and the difference is -5 hours. The following code demonstrates it (link to online compiled version)
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/local_time_adjustor.hpp>
#include <iostream>
int main(void) {
const boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
const boost::posix_time::ptime adjUSDST = boost::date_time::local_adjustor<boost::posix_time::ptime, -5, boost::posix_time::us_dst>::utc_to_local(now);
const boost::posix_time::ptime adjNODST = boost::date_time::local_adjustor<boost::posix_time::ptime, -5, boost::posix_time::no_dst>::utc_to_local(now);
std::cout << "now: " << now << std::endl;
std::cout << "adjUSDST: " << adjUSDST << std::endl;
std::cout << "adjNODST: " << adjNODST << std::endl;
return 0;
}
I am trying to write a simple timestamping system that provides epoch seconds and fractional seconds from the current time. I am using boost library and have something like this:
const boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
boost::posix_time::ptime time() {
boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
return now;
}
boost::posix_time::time_duration dur = (time() - epoch);
and then use the following elements to extract the epoch values:
dur.total_seconds();
dur.fractional_seconds();
Specifically, will this return a proper unix time? If not, any suggestions as to how to correct it? Thanks.
Yes, that should work, but, to be certain, there's always experimental evidence:
#include <iostream>
#include <time.h>
#include <boost/date_time.hpp>
namespace bpt = boost::posix_time;
namespace bg = boost::gregorian;
int main()
{
bpt::time_duration dur = bpt::microsec_clock::universal_time()
- bpt::ptime(bg::date(1970, 1, 1));
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
std::cout << std::setfill('0')
<< " boost: " << dur.total_seconds() << '.' << std::setw(6)
<< dur.fractional_seconds() << '\n'
<< " ctime: " << time(NULL) << '\n'
<< " posix: " << ts.tv_sec << '.' << std::setw(9)
<< ts.tv_nsec << '\n';
}
I get
Linux/gcc
boost: 1361502964.664746
ctime: 1361502964
posix: 1361502964.664818326
Sun/Sun Studio
boost: 1361503762.775609
ctime: 1361503762
posix: 1361503762.775661600
AIX/XLC
boost: 1361503891.342930
ctime: 1361503891
posix: 1361503891.342946000
and even Windows/Visual Studio
boost: 1361504377.084231
ctime: 1361504377
Looks like they all agree on how many seconds passed since date(1970,1,1)