C++ - How to check if today's date is an a string? - c++

I have a C++ application I'm developing where I just need to check if the current day's date is in a char array, specifically in the format "2015-05-10". I'm pretty new to C++ coming over from PHP where it is very easy to do, but I'm struggling trying to find a good method in C++. This needs to be automated as the script runs daily on a cron job. So the process is:
If (today's date is in char array) {
do this }
else {
do nothing
}
Edit: I am obviously useless at expressing my problems, sorry!
My main issues are:
How do I get the current day's date in a nice simple string in this format - 2015-05-10
How do I then check if a char array I have stored (which I know contains a date amongst some other text) contains the current day's date (which I will, when I know how, have stored as a string).

If I understood correctly, your first want to convert the current date to the format yyyy-mm-dd and then search for the string in another string.
For the first question, you may refer to How to get current time and date in C++? where there are multiple solutions given.
For the second part of the question, if you are using strings, you should use the find (http://www.cplusplus.com/reference/string/string/find/) method and if you are using char arrays, you could use the C strstr (http://www.cplusplus.com/reference/cstring/strstr/) method.
Here's what I tried:
#include <iostream>
#include <string>
#include <cstdio>
#include <ctime>
#include <cstring>
time_t now = time(0);
struct tm tstruct;
char buf[100];
tstruct = *localtime(&now);
strftime(buf, sizeof(buf), "%Y-%m-%d", &tstruct);
//char arrays used
char ch_array[] = "This is the received string 2015-05-10 from server";
char * pch;
pch = strstr(ch_array, buf);
if (pch != nullptr)
std::cout << "Found";
//string used
std::string str("This is the received string 2015-05-10 from server");
std::size_t found = str.find(buf);
if (found != std::string::npos)
std::cout << "date found at: " << found << '\n';

Related

Conversion of date from human-readable format to epoch fails

I'd like to create a program that converts the date of a specific human-readable format to epoch.
So far I have the following code the first part of which creates this human-readable format and the second one converts it to epoch.
#include <time.h>
#include <iostream>
#include <ctime>
#include <string>
#include <cstring>
using namespace std;
int main(int argc, char const *argv[])
{
time_t timeNow;
struct tm *ltm = NULL;
time(&timeNow);
ltm = localtime(&timeNow);
char buffer[100];
strftime(buffer, sizeof(buffer), "%c %Z", ltm);
cout << "human readable timestamp is " << buffer << endl;
std::tm tmNow;
memset(&tmNow, 0, sizeof(tmNow));
strptime(buffer, "%c %Z", &tmNow);
cout << "epoch timestamp is " << mktime(&tmNow) << endl;
return 0;
}
So the printouts I get are the following :
human readable timestamp is Thu Sep 16 10:23:06 2021 EEST
epoch timestamp is 1631780586
My time zone is EEST as one can see but the epoch one is wrong because it is one hour ahead. The correct should have been 1631776986. I assume I'm doing wrong something with the local time. I've found third-party libraries examples like boost or poco that do this conversion, but I'd prefer the above conversion to be done by using native C++.
Does anyone see what I'm missing?
The C timing/calendrical API is very difficult to use correctly (which is why C++ is moving away from it).
From the C standard:
The value of tm_isdst is positive if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and negative if the information is not available.
Set tmNow.tm_isdst = -1; prior to the call to mktime.

Combine strings in C++ to rename a file to present date

I'm new to C++. I'm trying to write a small program that will take a .txt file from my desktop, sort it in a folder and rename it to current date.
My idea is in combining three strings, first string is a direction to the main directory where I want to move the file, second string is the name of the month in my native language and the third string is the string that represents the date in dd-mm.txt format.
#include <iostream>
#include <filesystem>
#include <ctime>
using namespace std;
int main() {
int result;
std::time_t t = std::time(0);
std::tm* now = std::localtime(&t);
char date_string[100];
strftime(date_string, 50, "\\%e-%m.txt", now);
string mnths[12] = { "Januar", "Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar" };
char strt[] = "C:\\Users\\B\\Desktop\\New.txt";
char fnsh[] = "C:\\Users\\B\\Desktop\\Journal\\2020\\"+ mnths[date_string[month]]+ date_string;
result = rename(strt, fnsh);
if (result == 0)
puts("File successfully renamed");
else
perror("Error renaming file");
return 0;
};
For the second string, in case of April for example, I want to get the fourth value in the mnths array. I've tried a mishmash of solutions looking up online but now I'm lost and need help. Most notable error is "Expression must have integral or unscoped enum type" and I've googled it but I still can't understand completely how it relates to my problem and how I can fix it. Thank you.

How to deal with time in C++

I have a question about managing the date and time in c++. I have two classes Plane and Flight in my program.
My Plane will consist data as:
string tailNumber;//Plane's unique trait
vector<vector<string>> planeSchedule;//2D string vector to contain plane's depature date and arrival date
My Flight class will consist data as:
string tailNumber;//Plane's unique trait
string departureDate;
string arrivalDate;
In my main class, I will input the value for departureDate and arrivalDate in format: "YYYY/MM/DD HH:MM" such as: "2019/04/15 10:30" and "2019/04/16 9:30" (I will use the 24-hour format and time will be GMT).
My question is how do I convert the two strings above to a proper format to store in my planeSchedule, so that I will be able to avoid the time conflict in the planeSchedule.
For example, If the next time I'm adding a flight with departure and arrival date beetween the: 2019/04/15 10:30" and "2019/04/16 9:30" such as: "2019/04/15 13:30" and "2019/04/16 7:30", I will get an error like "Flight conflict, plane is not available to flight."
My professor recommends using an unsigned long int to store time, but I really do not know where to start to solve this problem. Any help/suggestion is appreciated.
The go-to place regarding dates and times in C++ is <chrono>. Some of it has been with us since C++11, some of it we'll see coming with C++20. It works in conjunction with the C-style date and time utilities in <ctime>, which might even suffice for your purposes.
Trying to handle date / time as either integers or strings, parsing them from input, comparing, and converting them to strings for output, will effectively result in you reimplementing parts of what's already in those headers (a.k.a. "reinventing the wheel").
I have two pieces of advice based on long experience with systems that did it badly :-)
The first is to not store date and time information as strings or integral values, especially when C++ has very good support for that in std::chrono. If you use the correct types, comparisons and manipulations become relatively simple.
Second, make sure you use UTC for all times. You should convert local times to UTC as soon as possible after getting them, and convert back to local as late as possible when presenting them. This will also greatly simplify comparisons.
By way of example, here's a complete program which show the simplicity(a) in action:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
using std::chrono::system_clock;
using std::chrono::duration_cast;
namespace {
system_clock::time_point getTimePoint(std::string strTime) {
std::tm myTm = {};
std::stringstream ss(strTime.c_str());
ss >> std::get_time(&myTm, "%Y/%m/%d %H:%M");
return system_clock::from_time_t(std::mktime(&myTm));
}
void outputTime(const char *desc, system_clock::time_point &tp) {
std::time_t now = system_clock::to_time_t(tp);
std::cout << desc
<< std::put_time(std::localtime(&now), "%Y-%m-%d %H:%M") << "\n";
}
}
int main() {
std::string startTime = "2019/04/15 10:30";
std::string endTime = "2019/04/16 09:30";
auto startTp = getTimePoint(startTime);
auto endTp = getTimePoint(endTime);
outputTime("Start time: ", startTp);
outputTime(" End time: ", endTp);
auto duration = duration_cast<std::chrono::minutes>(endTp - startTp);
std::cout << "\nThere are " << duration.count() << " minutes between "
<< startTime << " and " << endTime << "\n";
}
The output of that program is:
Start time: 2019-04-15 10:30
End time: 2019-04-16 09:30
There are 1380 minutes between 2019/04/15 10:30 and 2019/04/16 09:30
(a) Yes, the program may seem reasonably big but that's just because of the stuff making it a complete program. The getTimePoint and outputTime functions show how to do the conversion to and from time points, and the meat of the simplicity is the line containing duration_cast to get the number of minutes between the two time points.

How do I write a message timestamp to a log file?

I'm trying to create a logging file for my C++ program. My goal is to put two timestamps at two points of my program and print in a file the CPU time period between these two points. I'm doing this because I want to know which parts of my code are the most time consuming so I can make improvements (so there may be several chunks of code I want to measure). So far, I've made a function that, when called, prints a string that I pass as an argument, to a file:
#define LOGFILE "myprog.log"
void Log (std::string message){
std::ofstream ofs;
ofs.open(LOGFILE, std::ofstream::out | std::ios::app);
ofs << message << std::endl;
ofs.close();
}
However, I'm having difficulty figuring out how to print the CPU timestamp. Firstly, I don't know what time measurement format I should use (should I use the chrono or the time_t types?) I'm trying to print a time period so it would be helpful if there was a type for duration (I've tried chrono::duration but it seems to require C++11 support). Secondly, given I know what type to use, how do I print it to the file? Is there a way to cast that type to a string? Or can I pass it directly to my function and print it somehow?
This has troubled me a lot the last couple of days and I can't seem to figure it out, so any input would be really helpful. Thanks in advance!
Get a CPU Timestamp
You'll want to use std::chrono::system_clock to get this timestamp. Do not use std::chrono::steady_clock or std::chrono::high_resolution_clock, as those are for making high-precision timing measurements, and do not guarantee fidelity or accuracy to wall-clock time.
auto now = std::chrono::system_clock::now();
//now is a time_point object describing the instant it was recorded according to your system clock
Print this CPU Timestamp in a readable format
In C++20, this is pretty trivial.
std::string formatted_time = std::format("{0:%F_%T}", now);
ofs << formatted_time << ": " << message << std::endl;
%F is a substitute for %Y-%m-%D, which will output year-month-day in ISO format, i.e. 2018-10-09.
%T is the same for %H:%M:%S, which will output a time, i.e. 17:55:34.786
See the specification for std::format and std::formatter for more information about how to specify these parameters.
As of December 2020, no major compilers support the <format> library, yet, so as an alternative you can use fmt, which is a standalone implementation of the library.
Prior to C++20
Consider Howard Hinnant's date library, most of which is being incorporated into C++20 as a new part of the chrono library. The format function found in that library uses the same syntax as suggested above for the C++20 version, although without integration with std::format.
I'm usually use my implementation for such things.
#include <chrono>
#include <ctime>
// strftime format
#define LOGGER_PRETTY_TIME_FORMAT "%Y-%m-%d %H:%M:%S"
// printf format
#define LOGGER_PRETTY_MS_FORMAT ".%03d"
// convert current time to milliseconds since unix epoch
template <typename T>
static int to_ms(const std::chrono::time_point<T>& tp)
{
using namespace std::chrono;
auto dur = tp.time_since_epoch();
return static_cast<int>(duration_cast<milliseconds>(dur).count());
}
// format it in two parts: main part with date and time and part with milliseconds
static std::string pretty_time()
{
auto tp = std::chrono::system_clock::now();
std::time_t current_time = std::chrono::system_clock::to_time_t(tp);
// this function use static global pointer. so it is not thread safe solution
std::tm* time_info = std::localtime(&current_time);
char buffer[128];
int string_size = strftime(
buffer, sizeof(buffer),
LOGGER_PRETTY_TIME_FORMAT,
time_info
);
int ms = to_ms(tp) % 1000;
string_size += std::snprintf(
buffer + string_size, sizeof(buffer) - string_size,
LOGGER_PRETTY_MS_FORMAT, ms
);
return std::string(buffer, buffer + string_size);
}
It returns current time in format: 2018-09-23 21:58:52.642.
Yes it requires --std=c++11 or above.
For the record:
If C++20 features are not available, as in my case, you can use the following:
#include <ctime>
#include <iomanip>
#include <iostream>
using namespace std ;
time_t now = time(nullptr) ;
cout << put_time(localtime(&now), "%T") << endl ;
put_time is defined in iomanip library, look at https://en.cppreference.com/w/cpp/io/manip/put_time, and time_t and localtime are from the ctime, https://en.cppreference.com/w/cpp/chrono/c/ctime
If you want a more manual approach, this is what I've used before
char buffer[MAX_BUFFER_SIZE];
time_t t = time(NULL);
struct tm *lt = localtime(&t);
snprintf(buffer, MAX_BUFFER_SIZE, "%02d/%02d/%02d %02d:%02d:%02d", lt->tm_mon+1, lt->tm_mday, lt->tm_year%100, lt->tm_hour, lt->tm_min, lt->tm_sec);
Then just output buffer, which now contains string representation of time, to your file.

C++ cannot name txt file after current sytem time and date

Hi im having issue with this code i have made. It will compile but once i hit enter in the program it says this:
Unhandled exception at 0x008E8641 in Log Test.exe: 0xC0000005: Access violation reading location 0x566D846A.
Here is the code:
#include <iostream>
#include <time.h>
#include <fstream>
using namespace std;
int main() {
cin.get();
time_t Time;
Time = time(0);
string Date = __DATE__;
string LOG = Time + "_" + Date;
ofstream TEST;
TEST.open(LOG);
TEST << "This Text Should Appear Inside Of File.";
TEST.close();
cout << "Log has been Made.";
cin.get();
return 0;
}
I beleive that the problem is the time and how i tried putting it into a string but i dont see what i did doesn't work.
I would think that Time is an integer type so this:
Time + "_"
results in pointer addition so that what gets added to the string is a bad pointer to some location beyond the beginning of "_".
You see string literals like "_" actually resolve to an address (pointer). Adding an integer like Time to it simple makes it point elsewhere in memory.
First you need to convert your Time to a string.
I happen to have this code laying around that may work for you:
std::string get_stamp()
{
time_t t = std::time(0);
char buf[sizeof("YYYY-MM-DD HH-MM-SS")];
return {buf, std::strftime(buf, sizeof(buf), "%F %H-%M-%S", std::localtime(&t))};
}
Note: Using std::localtime is not threas-safe.
If you enabled compiler warnings, it should have screamed at you about this line:
string LOG = Time + "_" + Date;
Here, Time is being converted to a pointer, and you're getting undefined behaviour. For a not completely C++ solution, I recommend this simple approach:
time_t t = time(0);
struct tm ttm;
localtime_r( &t, &ttm );
char timestamp[20]; // actually only need 17 chars plus terminator.
sprintf_s( timestamp, sizeof(timestamp), "%04d-%02d-%02d_%02d%02d%02d",
ttm.tm_year + 1900, ttm.tm_mon + 1, ttm.tm_day, ttm.tm_hour, ttm.tm_min, ttm.tm_sec );
string logfilename = string(timestamp) + ".log";
ofstream logfile( logfilename.c_str() );
Note that localtime_r is not completely portable. On windows, use localtime_s, which unfortunately also reverses the order of the arguments.