Convert a string to a date in C++ - c++

I know this may be simple but being C++ I doubt it will be. How do I convert a string in the form 01/01/2008 to a date so I can manipulate it? I am happy to break the string into the day month year constituents. Also happy if solution is Windows only.

#include <time.h>
char *strptime(const char *buf, const char *format, struct tm *tm);

I figured it out without using strptime.
Break the date down into its components i.e. day, month, year, then:
struct tm tm;
time_t rawtime;
time ( &rawtime );
tm = *localtime ( &rawtime );
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
mktime(&tm);
tm can now be converted to a time_t and be manipulated.

For everybody who is looking for strptime() for Windows, it requires the source of the function itself to work. The latest NetBSD code does not port to Windows easily, unfortunately.
I myself have used the implementation here (strptime.h and strptime.c).
Another helpful piece of code can be found here. This comes originally from Google Codesearch, which does not exist anymore.
Hope this saves a lot of searching, as it took me quite a while to find this (and most often ended up at this question).

#include <time.h>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
int main ()
{
time_t rawtime;
struct tm * timeinfo;
int year, month ,day;
char str[256];
cout << "Inter date: " << endl;
cin.getline(str,sizeof(str));
replace( str, str+strlen(str), '/', ' ' );
istringstream( str ) >> day >> month >> year;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
mktime ( timeinfo );
strftime ( str, sizeof(str), "%A", timeinfo );
cout << str << endl;
system("pause");
return 0;
}

Why not go for a simpler solution using boost
using namespace boost::gregorian;
using namespace boost::posix_time;
ptime pt = time_from_string("20150917");

You can utilize the boost library(cross platform)
#include <stdio.h>
#include "boost/date_time/posix_time/posix_time.hpp"
int main()
{
std::string strTime = "2007-04-11 06:18:29.000";
std::tm tmTime = boost::posix_time::to_tm(boost::posix_time::time_from_string(strTime));
return 0;
}
But the format should be as mentioned :)

Related

How to convert a "%Y%m%d" format string into a time_t variable in C++?

I'm trying to convert strings into time_t variables. Here's the code I tried:
#include "pch.h"
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace std;
time_t String_to_timet1(string endDate) {
tm tm = { 0 };
stringstream ss(endDate);
ss >> get_time(&tm, "%Y-%m-%d %H:%M:%S");
time_t epoch = mktime(&tm);
return epoch;
}
time_t String_to_timet2(string endDate) {
tm tm = { 0 };
stringstream ss(endDate);
ss >> get_time(&tm, "%Y%m%d");
time_t epoch = mktime(&tm);
return epoch;
}
int main()
{
time_t time_certainTime1 = String_to_timet1("2019-01-01 00:00:00");
cout << time_certainTime1 << endl;
time_t time_certainTime2 = String_to_timet2("20190101");
cout << time_certainTime2 << endl;
return 0;
}
I expected that the results would be the same, but when I run the code with Visual Studio 2017, the results are:
1546268400
-1
and when I run the same code on https://www.onlinegdb.com/online_c++_compiler, the results are:
1546300800
1546300800
Question: Why does Visual Studio give me -1 when it gets a "%Y%m%d" typed string (when the online compiler gives me the result I expected)? How to make a time_t variable with such format?
In the documentation for both %m and %d it says leading zeros permitted but not required. This means that it's actually underspecified if it will work without separators or not.

How to get the day of the week from a tm object in C++?

I'm trying to write a program which parses a string representing a date formatted as YYYYMMDD (using strptime()) and prints it in the form of dayOfWeek, Month Day, Year (using put_time()). Here's what I have so far:
#include <iostream>
#include <sstream>
#include <ctime>
#include <iomanip>
using namespace std;
int main() {
struct tm tm;
string s("20131224");
if (strptime(s.c_str(), "%Y%m%e", &tm)) {
cout << put_time(&tm, "%A, %B %e, %Y") << endl;
}
}
The problem is that the day of the week is always a Sunday, regardless of the date.
It appears to be a problem with strptime() not populating the day of the week information if only given a year, month, and day, and then put_time() not filling in this information either.
According to this documentation for strftime(), "missing fields in the tm structure may be filled in by strftime() if given enough information." I haven't found the same information regarding put_time() (which strftime() appears to be based on), so perhaps I'm expecting too much of the function.
Can strptime() automatically fill in the day of the week (tm_wday) on input, given a year, month, and day? Or can put_time() automatically fill this information on output? If not, is there another way to add this information to a tm object?
Here's a way to do it without using the C API, but instead the C++11/14 <chrono> facilities and this free, open-source, header-only library.
#include "date.h"
#include <iostream>
#include <sstream>
using namespace std;
int main() {
istringstream s("20131224");
date::sys_days tp;
s >> date::parse("%Y%m%e", tp);
if (!s.fail())
cout << date::format("%A, %B %e, %Y", tp) << endl;
}
Output:
Tuesday, December 24, 2013
date::sys_days above is just a typedef for a std::chrono::system_clock::time_point but with a precision of days instead of whatever your platform provides (microseconds, nanoseconds, whatever). And that means you can easily add other durations to it, such as std::chrono::hours, minutes, seconds, milliseconds, etc.
cout << date::format("%A, %B %e, %Y %H:%M", tp + 2h + 35min ) << endl;
Tuesday, December 24, 2013 02:35
You can paste the above code into this wandbox demo and try it out for yourself for various versions of clang and gcc:
http://melpon.org/wandbox/permlink/PodYB3AwdYNFKbMv
Try this (compiled in Mac)
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
const string DAY[]={"Sun","Mon","Tue",
"Wed","Thu","Fri","Sat"};
time_t rawtime;
tm * timeinfo;
time(&rawtime);
timeinfo=localtime(&rawtime);
int weekday=timeinfo->tm_wday;
cout << "Today is: " << DAY[weekday] << "\n" << endl;
return 0;
}

How to correctly add the date to the date?

I'm new in C++, and i have a problem with Unixtime adding. For example, I have a date 8.10.2014 14:49
I need to add 26 days, 12 hours, 44 minutes to it. This is my code:
#include <iostream>
#include <ctime>
struct Date {
int Minute;
int Hour;
int Day;
int Month;
int Year;
};
int main(){
time_t rawtime;
struct tm * timeinfo;
Date startDate;
std::cin >> startDate.Year;
std::cin >> startDate.Month;
std::cin >> startDate.Day;
std::cin >> startDate.Hour;
std::cin >> startDate.Minute;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
timeinfo->tm_year = startDate.Year - 1900;
timeinfo->tm_mon = startDate.Month -1;
timeinfo->tm_mday = startDate.Day;
timeinfo->tm_hour = startDate.Hour;
timeinfo->tm_min = startDate.Minute;
rawtime = mktime ( timeinfo ) + 2555027;
std::cout << rawtime << std::endl;
struct tm *tm = localtime(&rawtime);
char date[80];
strftime(date, sizeof(date), "%Y %m %d %H %M", tm);
std::cout << date;
}
The answers is approximately similar to the truth, but don't correct. Why?
If you have C++11 (or C++14) and a relatively up-to-date compiler, you can use this library:
http://howardhinnant.github.io/date/tz.html
like so:
#include <chrono>
#include <iostream>
#include "tz.h"
int
main()
{
using namespace date;
using namespace std::chrono_literals;
auto zone = current_zone();
auto time = make_zoned(current_zone(), local_days{8_d/10/2014} + 14h + 49min);
time = time.get_sys_time() + days{26} + 12h + 44min;
std::cout << time << '\n';
}
This is roughly equivalent to what you have, which assumes that the date you specified is in your computer's local timezone, and that you also want the results in your computer's local timezone. For me this outputs:
2014-11-04 02:33:00 EST
However you also mentioned "Unixtime", which to me means Unix time. This time is measured in UTC, which lacks complications such as daylight saving time. If it is the intent to do this in Unix time, you can do this more easily and cheaply with this library:
http://howardhinnant.github.io/date/date.html
like this:
#include <chrono>
#include <iostream>
#include "date.h"
int
main()
{
using namespace date;
using namespace std::chrono_literals;
auto time = sys_days{8_d/10/2014} + 14h + 49min + days{26} + 12h + 44min;
std::cout << time << '\n';
}
which will portably output:
2014-11-04 03:33
The use of the "chrono literals" (e.g. 14h) implies C++14. If you are in C++11, you can substitute in the more verbose hours{14} (hours is in namespace std::chrono). If you are in C++03, well, then, never mind. :-)

Inverse of strftime() [duplicate]

I know this may be simple but being C++ I doubt it will be. How do I convert a string in the form 01/01/2008 to a date so I can manipulate it? I am happy to break the string into the day month year constituents. Also happy if solution is Windows only.
#include <time.h>
char *strptime(const char *buf, const char *format, struct tm *tm);
I figured it out without using strptime.
Break the date down into its components i.e. day, month, year, then:
struct tm tm;
time_t rawtime;
time ( &rawtime );
tm = *localtime ( &rawtime );
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
mktime(&tm);
tm can now be converted to a time_t and be manipulated.
For everybody who is looking for strptime() for Windows, it requires the source of the function itself to work. The latest NetBSD code does not port to Windows easily, unfortunately.
I myself have used the implementation here (strptime.h and strptime.c).
Another helpful piece of code can be found here. This comes originally from Google Codesearch, which does not exist anymore.
Hope this saves a lot of searching, as it took me quite a while to find this (and most often ended up at this question).
#include <time.h>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
int main ()
{
time_t rawtime;
struct tm * timeinfo;
int year, month ,day;
char str[256];
cout << "Inter date: " << endl;
cin.getline(str,sizeof(str));
replace( str, str+strlen(str), '/', ' ' );
istringstream( str ) >> day >> month >> year;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
mktime ( timeinfo );
strftime ( str, sizeof(str), "%A", timeinfo );
cout << str << endl;
system("pause");
return 0;
}
Why not go for a simpler solution using boost
using namespace boost::gregorian;
using namespace boost::posix_time;
ptime pt = time_from_string("20150917");
You can utilize the boost library(cross platform)
#include <stdio.h>
#include "boost/date_time/posix_time/posix_time.hpp"
int main()
{
std::string strTime = "2007-04-11 06:18:29.000";
std::tm tmTime = boost::posix_time::to_tm(boost::posix_time::time_from_string(strTime));
return 0;
}
But the format should be as mentioned :)

String representation of time_t?

time_t seconds;
time(&seconds);
cout << seconds << endl;
This gives me a timestamp. How can I get that epoch date into a string?
std::string s = seconds;
does not work
Try std::stringstream.
#include <string>
#include <sstream>
std::stringstream ss;
ss << seconds;
std::string ts = ss.str();
A nice wrapper around the above technique is Boost's lexical_cast:
#include <boost/lexical_cast.hpp>
#include <string>
std::string ts = boost::lexical_cast<std::string>(seconds);
And for questions like this, I'm fond of linking The String Formatters of Manor Farm by Herb Sutter.
UPDATE:
With C++11, use to_string().
Try this if you want to have the time in a readable string:
#include <ctime>
std::time_t now = std::time(NULL);
std::tm * ptm = std::localtime(&now);
char buffer[32];
// Format: Mo, 15.06.2009 20:20:00
std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", ptm);
For further reference of strftime() check out cppreference.com
The top answer here does not work for me.
See the following examples demonstrating both the stringstream and lexical_cast answers as suggested:
#include <iostream>
#include <sstream>
int main(int argc, char** argv){
const char *time_details = "2017-01-27 06:35:12";
struct tm tm;
strptime(time_details, "%Y-%m-%d %H:%M:%S", &tm);
time_t t = mktime(&tm);
std::stringstream stream;
stream << t;
std::cout << t << "/" << stream.str() << std::endl;
}
Output: 1485498912/1485498912
Found here
#include <boost/lexical_cast.hpp>
#include <string>
int main(){
const char *time_details = "2017-01-27 06:35:12";
struct tm tm;
strptime(time_details, "%Y-%m-%d %H:%M:%S", &tm);
time_t t = mktime(&tm);
std::string ts = boost::lexical_cast<std::string>(t);
std::cout << t << "/" << ts << std::endl;
return 0;
}
Output: 1485498912/1485498912
Found: here
The 2nd highest rated solution works locally:
#include <iostream>
#include <string>
#include <ctime>
int main(){
const char *time_details = "2017-01-27 06:35:12";
struct tm tm;
strptime(time_details, "%Y-%m-%d %H:%M:%S", &tm);
time_t t = mktime(&tm);
std::tm * ptm = std::localtime(&t);
char buffer[32];
std::strftime(buffer, 32, "%Y-%m-%d %H:%M:%S", ptm);
std::cout << t << "/" << buffer;
}
Output: 1485498912/2017-01-27 06:35:12
Found: here
Standard C++ does not have any time/date functions of its own - you need to use the C localtime and related functions.
the function "ctime()" will convert a time to a string.
If you want to control the way its printed, use "strftime". However, strftime() takes an argument of "struct tm". Use "localtime()" to convert the time_t 32 bit integer to a struct tm.
The C++ way is to use stringstream.
The C way is to use snprintf() to format the number:
char buf[16];
snprintf(buf, 16, "%lu", time(NULL));
Here's my formatter -- comments welcome. This q seemed like it had the most help getting me to my a so posting for anyone else who may be looking for the same.
#include <iostream>
#include "Parser.h"
#include <string>
#include <memory>
#include <ctime>
#include <chrono>
#include <iomanip>
#include <thread>
using namespace std;
string to_yyyyMMddHHmmssffffff();
string to_yyyyMMddHHmmssffffff() {
using namespace std::chrono;
high_resolution_clock::time_point pointInTime = high_resolution_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(pointInTime);
microseconds micros = duration_cast<microseconds>(pointInTime.time_since_epoch());
std::size_t fractional_microseconds = micros.count() % 1'000'000;
std:stringstream microstream;
microstream << "00000" << fractional_microseconds;
string formatted = microstream.str();
int index = formatted.length() - 6;
formatted = formatted.substr(index);
std::stringstream dateStream;
dateStream << std::put_time(std::localtime(&now_c), "%F %T") << "." << formatted;
formatted = dateStream.str();
return formatted;
}
There are a myriad of ways in which you might want to format time (depending on the time zone, how you want to display it, etc.), so you can't simply implicitly convert a time_t to a string.
The C way is to use ctime or to use strftime plus either localtime or gmtime.
If you want a more C++-like way of performing the conversion, you can investigate the Boost.DateTime library.
localtime did not work for me. I used localtime_s:
struct tm buf;
char dateString[26];
time_t time = time(nullptr);
localtime_s(&buf, &time);
asctime_s(dateString, 26, &buf);