I am looking in to the code about getting utc time.
static const long long SECSEPOCHS = 11644473600ll;
static const long long SECSto100nanosecs = 10000000ll;
static const long long MSECSto100nanosecs = 10000ll;
longlong mytime;
struct timeb now;
ftime(&now);
mytime = now.time;
mytime += SECSEPOCHS
mytime *= SECSto100nanosecs;
mytime += now.millitm * MSECSto100nanosecs;
I have following questions about above code.
What is the magic number "11644473600ll", how we got that number, and why we are adding this number to now.time that is returned by ftime. What is epcoh mean here?
Thanks
Epoch refers to the reference time that is used to calculate further events. For example if I decide that 1st Jan 2000 is the reference time (EPOCH) so whenever we I say "1 year past". It will mean that it is 1st Jan 2001 as our reference was year 2000.
Windows NT time is specified as the number of 100 nanosecond intervals since January 1, 1601. UNIX time is specified as the number of seconds since January 1, 1970. There are 134,774 days (or 11,644,473,600 seconds) between these dates.
The epoch is Midnight UTC, Jan 1 1970, the base for unixtime. The magic number is used to convert in between unixtime and microsoft's filetime which starts at Midnight UTC, Jan 1 1601.
Your code does the following:
ftime(&now);
mytime = now.time; // Get unixtime right now
mytime += SECSEPOCHS; // Adjust to seconds since microsoft's 1601 epoch
mytime *= SECSto100nanosecs; // Convert to 100-nanosecond units
mytime += now.millitm * MSECSto100nanosecs; // Add the millisecond part of the unixtime
The result is a value which is suitable for MS's FILETIME structure.
ftime returns Unix time, which is counted in seconds since 1 January 1970 00:00:00 UTC. The rest of the code converts it to a Windows NT file time, which is counted in units of 100 nanoseconds since 1 January 1601 00:00:00 UTC. The "epoch" is the "start of time", and 11644473600 is the Unix epoch expressed in seconds since the NT filetime epoch.
Related
How can I convert number of seconds since 1970 to DateTime in c++?
I am getting the time in the below format:
1296575549:573352
The left part of the colon is in seconds and the right part in micro seconds.
Please help.
Thanks,
Syd
Try and use gmtime() (see http://www.cplusplus.com/reference/clibrary/ctime/gmtime/) or localtime() to convert a time_t to a struct tm
Use boost::Date_Time to do this. Code below assumes _interval is number of seconds since 1970. Note this code example doesn't handle the micro-second portion, but I am sure it could be modified to do so.
#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
double interval(1296575549.0f);
boost::posix_time::ptime m_DateTime = ptime(date(1970, 1, 1),
time_duration(0, 0, 0,
time_duration::ticks_per_second() *
(time_duration::fractional_seconds_type)_interval));
Three important things about converting time using C/C++ library.
gmtime() or localtime() from standard library convert from time_t to struct tm, but the resolution for time_t is seconds from epoch. So fractional seconds will not count.
mktime() converts backwards from struct tm to time_t, but it will return -1 if the input date is out of range. (Reference: year 2038 problem)
If you are not using 64bit timestamp, even you run programs on 64bit machines, you still have year 2038 problem. There are 64bit version functions like gmtime64(), localtime64(), mktime64() that may resolve the year out of range issue. (Reference)
New answer for a very old question. Rationale: Better tools.
Starting in C++11, one can easily store this quantity in a std::chrono::system_clock::time_point:
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace std::chrono;
istringstream in{"1296575549:573352"};
long si, usi;
char sep;
in >> si >> sep >> usi;
system_clock::time_point tp{seconds{si} + microseconds{usi}};
}
Though the epoch of system_clock is unspecified in C++11, every implementation is tracking Unix Time (time since 1970-01-01 00:00:00 UTC, excluding leap seconds). Different implementations will have different precisions for system_clock::time_point, but you don't really have to care about that when converting into system_clock::time_point as shown above. The <chrono> library will just do the right thing.
Starting in C++20 the Unix Time measure of system_clock::time_point will be specified, and you will be able to stream it out in a human readable form:
cout << tp << '\n';
For this example that will output:
2011-02-01 15:52:29.573352
On some platforms there may be a few trailing zeroes on this output, depending on the precision of system_clock::time_point on that platform. This is a UTC date/time. There will also be ways to convert this to a particular time zone if desired (in C++20).
You can experiment with this part of C++20 today by using Howard Hinnant's date/time library. This will require an additional #include "date/date.h" ("date/tz.h" for time zone functionality), and a using namespace date; to enable the system_clock::time_point streaming operator.
If it is known that your count of seconds includes leap seconds (Unix Time stamps don't), C++20 also provides a way to deal with that:
Just change system_clock to utc_clock in the above example and the new output will be:
2011-02-01 15:52:05.573352
which accounts for the 24 leap seconds inserted prior to this date.
As an example of duration available in seconds, let's assume you want to have an idea of the running time of your program:
#include <ctime>
time_t startRawTime;
time( &startRawTime );
//...your program performs computations...
time_t endRawTime;
time( &endRawTime );
time_t elapsedSec = difftime( endRawTime, startRawTime );
// but elapsedSec can be any duration, e.g. 3734, as long as it is in seconds
tm * ptm = gmtime( &elapsedSec );
printf( "elapsed time: %02dh %02dm %02ds\n",
ptm->tm_hour,
ptm->tm_min,
ptm->tm_sec );
You would get something like this for instance:
elapsed time: 01h 02m 14s
Well, the most complex case:
86'400 s/day
31'557'600 s/year (365.25 d)
1296575549/31557600 = 41 years
1296575549-41*31557600 = 2'713'949 s
2713949/86400 ==> 31 d
2713949-31*86400 =35'549
35549/(60*60) = 9h
35549-9*60*60 = 3'149
3'149/(60*60) = 0h
3'149- 0* (60*60) = 3'149
3149/60 = 52 m
3149-52*60 = 29s
--> year = 1970 + 41
--> month = 1 + 0
--> day = 31 (+1?)
--> Time 00:52:29
==> 2011, Jan 31, 00:52:29 GMT
To calculate the month from the day, you need to copy paste an isLeapYear function, because of February.
Hmm, looks like one also needs to account for the leap years until last leap year, which were subtracted in surplus. Hmm, effects of daylight saving time...
Go sleep !
I have a long int variable wich containes seconds since Jan. 1, 1970 in this format:
long int seconds = 1231241242144214;
i need to convert this seconds to double precision floating-point value. The integer part of the value is the number of days since midnight, 30 December 1899.
The fractional part of the value represents time. .5 is equal to 12:00 PM.
how can i convert?
There are 86400 seconds in a day, and 25569 days between these epochs. So the answer is:
double DelphiDateTime = (UnixTime / 86400.0) + 25569;
You really do need to store the Unix time in an integer variable though.
I am trying to take the difference of two dates by first reading the local time saving the tm structure and going to sleep for 5 seconds and read another local time and saving to another tm structure. I was hoping once I take the differences of the two dates to get a value 5 or greater. However, I am getting 0.
I get the correct result if comment out the following lines:
oldyear.tm_year = oldyear.tm_year + 1900;
oldyear.tm_mon = oldyear.tm_mon + 1;
newyear.tm_year = newyear.tm_year + 1900;
newyear.tm_mon = newyear.tm_mon + 1;
My code:
void timeTest()
{
time_t now;
struct tm newyear, oldyear;
double seconds;
time(&now); /* get current time; same as: now = time(NULL) */
oldyear = *localtime(&now);
oldyear.tm_year = oldyear.tm_year + 1900;
oldyear.tm_mon = oldyear.tm_mon + 1;
int epoch1 = mktime(&oldyear);
sleep(5);
time(&now); /* get current time; same as: now = time(NULL) */
newyear = *localtime(&now);
newyear.tm_year = newyear.tm_year + 1900;
newyear.tm_mon = newyear.tm_mon + 1;
int epoch2 = mktime(&newyear);
seconds = difftime(mktime(&newyear),mktime(&oldyear));
printf ("%.f seconds since new year in the current timezone.\n", seconds);
}
If I compile this on Linux, a 64-bit system, I get the output
5 seconds since new year in the current timezone.
However, if I compile for 32-bit system,
% gcc -m32 test2.c
% ./a.out
0 seconds since new year in the current timezone.
Note that mktime expects that the year is 1900-based and month 0-based, so the adjustment you do is incorrect and might cause overflow on 32-bit computers. What your code does is calculate the difference of 2 points of time on date 3914-08-28 - on 32-bit systems the time_t usually is 32 bits, and the largest date representable is 03:14:07 UTC on Tuesday, 19 January 2038 aka Y2K38 jf signed time_t is used.
On errors -1 is returned:
If the specified broken-down time cannot be represented as calendar
time (seconds since the Epoch), mktime() returns (time_t) -1 and does
not alter the members of the broken-down time structure.
Thus if you print out epoch and epoch2 I could bet you get -1 for both these timestamps.
How can I convert number of seconds since 1970 to DateTime in c++?
I am getting the time in the below format:
1296575549:573352
The left part of the colon is in seconds and the right part in micro seconds.
Please help.
Thanks,
Syd
Try and use gmtime() (see http://www.cplusplus.com/reference/clibrary/ctime/gmtime/) or localtime() to convert a time_t to a struct tm
Use boost::Date_Time to do this. Code below assumes _interval is number of seconds since 1970. Note this code example doesn't handle the micro-second portion, but I am sure it could be modified to do so.
#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
double interval(1296575549.0f);
boost::posix_time::ptime m_DateTime = ptime(date(1970, 1, 1),
time_duration(0, 0, 0,
time_duration::ticks_per_second() *
(time_duration::fractional_seconds_type)_interval));
Three important things about converting time using C/C++ library.
gmtime() or localtime() from standard library convert from time_t to struct tm, but the resolution for time_t is seconds from epoch. So fractional seconds will not count.
mktime() converts backwards from struct tm to time_t, but it will return -1 if the input date is out of range. (Reference: year 2038 problem)
If you are not using 64bit timestamp, even you run programs on 64bit machines, you still have year 2038 problem. There are 64bit version functions like gmtime64(), localtime64(), mktime64() that may resolve the year out of range issue. (Reference)
New answer for a very old question. Rationale: Better tools.
Starting in C++11, one can easily store this quantity in a std::chrono::system_clock::time_point:
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace std::chrono;
istringstream in{"1296575549:573352"};
long si, usi;
char sep;
in >> si >> sep >> usi;
system_clock::time_point tp{seconds{si} + microseconds{usi}};
}
Though the epoch of system_clock is unspecified in C++11, every implementation is tracking Unix Time (time since 1970-01-01 00:00:00 UTC, excluding leap seconds). Different implementations will have different precisions for system_clock::time_point, but you don't really have to care about that when converting into system_clock::time_point as shown above. The <chrono> library will just do the right thing.
Starting in C++20 the Unix Time measure of system_clock::time_point will be specified, and you will be able to stream it out in a human readable form:
cout << tp << '\n';
For this example that will output:
2011-02-01 15:52:29.573352
On some platforms there may be a few trailing zeroes on this output, depending on the precision of system_clock::time_point on that platform. This is a UTC date/time. There will also be ways to convert this to a particular time zone if desired (in C++20).
You can experiment with this part of C++20 today by using Howard Hinnant's date/time library. This will require an additional #include "date/date.h" ("date/tz.h" for time zone functionality), and a using namespace date; to enable the system_clock::time_point streaming operator.
If it is known that your count of seconds includes leap seconds (Unix Time stamps don't), C++20 also provides a way to deal with that:
Just change system_clock to utc_clock in the above example and the new output will be:
2011-02-01 15:52:05.573352
which accounts for the 24 leap seconds inserted prior to this date.
As an example of duration available in seconds, let's assume you want to have an idea of the running time of your program:
#include <ctime>
time_t startRawTime;
time( &startRawTime );
//...your program performs computations...
time_t endRawTime;
time( &endRawTime );
time_t elapsedSec = difftime( endRawTime, startRawTime );
// but elapsedSec can be any duration, e.g. 3734, as long as it is in seconds
tm * ptm = gmtime( &elapsedSec );
printf( "elapsed time: %02dh %02dm %02ds\n",
ptm->tm_hour,
ptm->tm_min,
ptm->tm_sec );
You would get something like this for instance:
elapsed time: 01h 02m 14s
Well, the most complex case:
86'400 s/day
31'557'600 s/year (365.25 d)
1296575549/31557600 = 41 years
1296575549-41*31557600 = 2'713'949 s
2713949/86400 ==> 31 d
2713949-31*86400 =35'549
35549/(60*60) = 9h
35549-9*60*60 = 3'149
3'149/(60*60) = 0h
3'149- 0* (60*60) = 3'149
3149/60 = 52 m
3149-52*60 = 29s
--> year = 1970 + 41
--> month = 1 + 0
--> day = 31 (+1?)
--> Time 00:52:29
==> 2011, Jan 31, 00:52:29 GMT
To calculate the month from the day, you need to copy paste an isLeapYear function, because of February.
Hmm, looks like one also needs to account for the leap years until last leap year, which were subtracted in surplus. Hmm, effects of daylight saving time...
Go sleep !
I am receiving from a data provider timestamps that follow this specification:
number of 100 nanoseconds since 1601
I am using boost::posix_time::ptime and I would like to convert the timestamps to posix time. Is there a simple way to do that ?
When did the switch from the Julian to Gregorian calendar occur for this system? Some countries switched before 1st January 1601; others didn't switch until much later. This will critically affect your calculation - by 11 days or so.
Since there are 107 units of 100 ns each in one second, you divide the starting number by 107 to produce the number of seconds since the reference time (the remainder is the fraction of a second). You then divide that by 86400 to give the number of days (the remainder is the time of day). Then you can compute the date from the number of days.
Since POSIX time uses 1970-01-01 00:00:00 as the reference, you may simply need to compute the correct number of seconds between 1601-01-01 00:00:00 and the POSIX epoch (as it is known), and subtract that number from the number of seconds you calculated.
number of 100 nanoseconds since 1601
It is Windows FILETIME value.
Boost.DateTime actually use Windows FILETIME for Windows platform.
Below is the relevant Boost source code that convert FILETIME to boost::posix_time::ptime:
(from boost/date_time/microsec_time_clock.hpp)
static time_type create_time(time_converter converter)
{
winapi::file_time ft;
winapi::get_system_time_as_file_time(ft);
uint64_t micros = winapi::file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
// and cannot be before 1970-Jan-01
std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
// microseconds -- static casts supress warnings
boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
std::tm curr;
std::tm* curr_ptr = converter(&t, &curr);
date_type d(curr_ptr->tm_year + 1900,
curr_ptr->tm_mon + 1,
curr_ptr->tm_mday);
//The following line will adjust the fractional second tick in terms
//of the current time system. For example, if the time system
//doesn't support fractional seconds then res_adjust returns 0
//and all the fractional seconds return 0.
int adjust = static_cast< int >(resolution_traits_type::res_adjust() / 1000000);
time_duration_type td(curr_ptr->tm_hour,
curr_ptr->tm_min,
curr_ptr->tm_sec,
sub_sec * adjust);
return time_type(d,td);
}
You can browse your Boost installation for the detailed implementation.