Conversion of times in C++ - c++

This is what I am trying to do:
Get the local time (from the system);
Convert that time to the UTC format and associate it with some member variable of current object.
Later on, given the timezone of the user, I wish to convert it into the correct local time and display it to the user.
Looking up few things on SO and CppReference, I could come up with the following snippet:
#include <iostream>
#include <iomanip>
#include <ctime>
#include <string>
using namespace std;
int main()
{
time_t lt = std::time(0);
//time(0) gives current time, but LTime shows the UTC time (not local time)
string LTime = std::ctime(&lt); //localtime() gives error
cout<<LTime;
//timestamp = mktime(&tm) - timezone;
//time_t timestamp = mktime(&tm) - _timezone;
//std::cout << "timestamp: " << std::put_time(timestamp, "%c %Z") << '\n';
return 0;
}
The example on cppreference.com illustrates how the value can be printed using put_time(); but how to store it in a variable?
How to convert the UTC time format to current timezone (given some timezone as the input)? I tried using the commented code above as per this link but it does not take any parameter.

You can use local time get the local time and gmt time for UTC
You can set the Time zone using the list Time zone wiki
#include <iostream>
#include <iomanip>
#include <ctime>
int main()
{
std::time_t result = std::time(nullptr);
auto local = std::asctime(std::localtime(&result));
std::cout <<local;
std::cout << "UTC: " << std::put_time(std::gmtime(&result), "%c %Z") << '\n';
putenv("TZ=Asia/Singapore");
local = std::asctime(std::localtime(&result));
std::cout <<"Asia/Singapore Time "<<local;
}
Output
Thu Sep 14 21:59:37 2017
UTC: Fri Sep 15 01:59:37 2017 UTC
Asia/Singapore Time Fri Sep 15 09:59:37 2017
Program ended with exit code: 0

Related

Converting time in milliseconds since epoch to time in yy-dd-hh-ss format

I have a bunch of tasks which are in the order of microseconds, the below code prints only until seconds (Thu Oct 21 12:48:20 2021) so comparing the values of start and finish always ends up giving 0. I want to be able to compare in the order of milliseconds and microseconds. Is there a function to help with this?
Also, is there a way to convert uint64_t current1 = std::chrono::system_clock::now().time_since_epoch().count(); to time_t to print out the current time based on the count()?
const auto p1 = std::chrono::system_clock::now();
std::time_t now = std::chrono::system_clock::to_time_t(p1);
std::cout << "now: " << std::ctime(&now);
I recommend skipping the C timing API entirely. It is error-prone and doesn't handle sub-second precision.
If UTC (as opposed to local time) is ok, then there is a header-only, open-source preview of C++20 that works with C++11/14/17:
#include "date/date.h"
#include <chrono>
#include <iostream>
int
main()
{
using date::operator<<;
const auto p1 = std::chrono::system_clock::now();
std::cout << "now: " << p1 << '\n';
}
Output:
now: 2021-10-21 20:28:15.754423
To port the above program to C++20 (which is already shipping in the latest Visual Studio), just drop the #include "date/date.h" and using date::operator<<;.
If you need local time, that can be also be had in C++20 (shipping in VS), but the open-source preview of C++20 is no longer header only. There exists one source file that needs to be compiled, and depending on your needs, might require a download of the IANA tz database.
#include "date/tz.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
const auto p1 = system_clock::now();
std::cout << "now: " << zoned_time{current_zone(), p1} << '\n';
}
Output:
now: 2021-10-21 16:28:15.754423 EDT
The above syntax assumes C++17. For C++11/14 the template parameter for zoned_time needs to be specified: zoned_time<system_clock::duration>.
The above program ports to C++20 by dropping #include "date/tz.h" and using namespace date;.
In either program you can truncate to millisecond precision with:
const auto p1 = floor<milliseconds>(system_clock::now());
time_t is usually an integer specifying (whole) seconds.
You could get the millseconds by subtracting the whole-second time_t from now:
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
p1 - std::chrono::system_clock::from_time_t(now)).count();
or using operator%:
auto ms = std::chrono::time_point_cast<std::chrono::milliseconds>p1)
.time_since_epoch() % std::chrono::seconds(1);
std::cout << ms.count();
Example how you could do the formatting:
#include <chrono>
#include <iostream>
#include <iomanip>
int main() {
using Clock = std::chrono::system_clock;
using Precision = std::chrono::milliseconds;
auto time_point = Clock::now();
// extract std::time_t from time_point
std::time_t t = Clock::to_time_t(time_point);
// output the part supported by std::tm
std::cout << std::put_time(std::localtime(&t), "%FT%T."); // select format here
// get duration since epoch
auto dur = time_point.time_since_epoch();
// extract the sub second part from the duration since epoch
auto ss =
std::chrono::duration_cast<Precision>(dur) % std::chrono::seconds{1};
// output the millisecond part
std::cout << std::setfill('0') << std::setw(3) << ss.count();
}

Get date and time in UTC format in c++ [duplicate]

This question already has answers here:
Convert time_t from localtime zone to UTC
(4 answers)
Closed 2 years ago.
How can I get a datetime in UTC time in this format ('2002-05-30T09:30:10Z') in C++?
This is the function I have made.
void settime(){
// Current date/time based on current system
time_t now = time(0);
// Convert now to tm struct for local timezone
tm* localtm = localtime(&now);
cout << "The local date and time is: " << asctime(localtm) << endl;
// Convert now to tm struct for UTC
tm* gmtm = gmtime(&now);
if (gmtm != NULL) {
cout << "The UTC date and time is: " << asctime(gmtm) << endl;
}
else {
cerr << "Failed to get the UTC date and time" << endl;
}
}
This function print in this format 'The UTC date and time is: Mon Oct 12 18:56:59 2020' right now.
Using this free, open-source, header-only preview of C++20 <chrono>:
#include "date/date.h"
#include <chrono>
#include <iostream>
int
main()
{
namespace cr = std::chrono;
std::cout << date::format("%FT%TZ", cr::floor<cr::seconds>(cr::system_clock::now())) << '\n';
}
This will easily port to C++20 by:
Drop #include "date/date.h"
Change date::format to std::format
Change "%FT%TZ" to "{:%FT%TZ}"

how to get UTC time in micro-seconds with leap seconds

How to get UTC time in micro-seconds with leap seconds adjusted?
I am using boost::universal_clock()
boost::posix_time::time_duration utc_time =
boost::posix_time::microsec_clock::universal_time() -
boost::posix_time::from_time_t(0);
int64_t total_microsec = utc_time.total_microseconds();
But the result of this is same as
std::chrono::time_point_cast<std::chrono::duration<int64_t, std::microseconds>>(
std::chrono::system_clock::now())
.time_since_epoch()
.count();
which seems that boost is not adjusting leap seconds. However when I use C gmtime() I get different result:
time_t mytime;
struct tm *ptm;
time(&mytime); // Get local time in time_t
ptm = gmtime(&mytime); // Find out UTC time
time_t utctime = mktime(ptm); // Get UTC time as time_t
How to achieve it using boost library?
Using Howard Hinnant's date/time library this is very easy:
#include "date/tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
auto now = floor<microseconds>(utc_clock::now());
cout << now << '\n';
cout << now.time_since_epoch() << '\n';
cout << clock_cast<system_clock>(now).time_since_epoch() << '\n';
}
This is a preview of the C++20 additions to <chrono>, but in namespace date.
utc_clock counts time since 1970-01-01 00:00:00 UTC including leap seconds. The clock_cast casts the time_point from this clock back to that of system_clock just for comparison purposes.
This program just output for me:
2019-08-10 00:19:04.388788
1565396371388788µs
1565396344388788µs
Some installation required.

Converting 13 decimals to datetime

I have a project about cars with GPS. I need to return the start and the finish moment for each car.
So we have:
time_t x, y;
Because I will use later them for a transformation.
I have a problem. I read from an external file data in this format:
auto1
1439467747492
auto1
1439467748512
...etc.
auto1->name of the car;
1439467747492->the moment in time of the car
I tried to get the first position of the first moment and the last moment for each car. This is the code in C++:
long test = momenti[choice1]/1000;
time_t x = test;
cout << " Momentul initial:\n " << ctime(&x) << endl;
long test1 = momentf[choice1] / 1000;
time_t y = test1;
cout << " Momentul final:\n " << ctime(&y) << endl;
I receive the same date for every car. Is something like momenti[i]=momentf[i]
What did I do wrong?
It is not good. According epoch converter we should get this : GMT: Thu, 13 Aug 2015 12:09:07 GMT
Here is how you can get this output with C++11/14 and using this free, open source date library which extends the C++ <chrono> library to handle dates.
#include "date.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
using namespace std;
using namespace date;
using time_point = std::chrono::time_point<system_clock, milliseconds>;
auto tp = time_point{1439467747492ms};
auto dp = floor<days>(tp);
auto time = make_time(tp - dp);
auto ymd = year_month_day{dp};
cout << "GMT: " << weekday{dp} << ", " << ymd.day() << ' ' << ymd.month()
<< ' ' << ymd.year() << ' ' << time << " GMT\n";
}
Output:
GMT: Thu, 13 Aug 2015 12:09:07.492 GMT
I threw in the fractional seconds for fun, and it seemed a shame to waste them (the C lib won't give them to you). If you really don't want them, it is easy to fix:
auto time = make_time(floor<seconds>(tp) - dp);
Now the output is:
GMT: Thu, 13 Aug 2015 12:09:07 GMT
You need C++14 for the 1439467747492ms above. If you only have C++11 you can sub in this instead: milliseconds{1439467747492}. If you only have C++03, then you are 13 years behind the times and stuck with ctime. ;-)
The chrono solution will offer you greater type safety, more flexibility, and greater performance.
If i can fix and the latitude and longitude problem would be great lol
If you can translate latitude and longitude into an IANA timezone name (and there are tools to do this), I've got a IANA timezone database parser for you which interoperates with <chrono> and "date.h".
#include <iostream>
#include <cstring>
#include <time.h>
using namespace std;
int main()
{
long test = 1439467747492;
time_t x = test;
cout << ctime( &x ) << endl;
return 0;
}
Produces
Tue Sep 18 20:15:32 1990

boost local_date_time CET to UTC

I try to convert a boost local_date_time to UTC but I'm confused about the returned time of utc_time(). Here is a simplified code :
#include "boost/date_time/local_time/local_time.hpp"
int main()
{
using namespace boost::gregorian;
using namespace boost::local_time;
using namespace boost::posix_time;
ptime dt = ptime(date(2015, Mar, 2), hours(0));
time_zone_ptr tz_cet(new boost::local_time::posix_time_zone("CET"));
local_date_time local_dt = boost::local_time::local_date_time(dt, tz_cet);
std::cout << local_dt << std::endl;
std::cout << local_dt.utc_time() << std::endl;
time_zone_ptr tz_utc(new boost::local_time::posix_time_zone("UTC"));
std::cout << local_dt.local_time_in(tz_utc) << std::endl;
}
output:
2015-Mar-02 00:00:00 CET
2015-Mar-02 00:00:00
2015-Mar-02 00:00:00 UTC
UTC should be 1 hour behind CET (Central European Time).
Is this a bug or am I missing something?
The boost::local_time::posix_time_zone("CET") constructor call creates a zone with the CET abbreviation and missing information about offset from UTC, time shift for DST, etc, i.e. the calls boost::local_time::posix_time_zone("CET") and boost::local_time::posix_time_zone("UTC") are different only in the TZ abbreviation names, the rest is the same. The coliru code demonstrates it. The base_utc_offset method calls of the both TZs return 00:00:00.
To fix the issue is necessary either to set time parameters of the CET zone, something like, "CET+01:00:00" or to use the tz_database class to load the timezones from a CSV file.
The following code is the original modified code demonstrating how to fix the problem. Please note that the CET time zone description is not complete and provided only as an example.
#include "boost/date_time/local_time/local_time.hpp"
#include <iostream>
int main()
{
using namespace boost::gregorian;
using namespace boost::local_time;
using namespace boost::posix_time;
ptime dt = ptime(date(2015, Mar, 2), hours(0));
time_zone_ptr tz_cet(new boost::local_time::posix_time_zone("CET+01:00:00"));
local_date_time local_dt = boost::local_time::local_date_time(dt, tz_cet);
std::cout << local_dt << std::endl;
std::cout << local_dt.utc_time() << std::endl;
time_zone_ptr tz_utc(new boost::local_time::posix_time_zone("UTC"));
std::cout << local_dt.local_time_in(tz_utc) << std::endl;
}
The same code on coliru is available by this link.