difftime returns 0 in C++ - c++

I am trying to calculate the elapsed time between the date a book was borrowed and today, but difftime always returns 0.
This is what I have :
#include <string>
#include <iostream>
#include <locale>
#include <stdio.h>
#include <ctime>
#include <time.h>
#include "library.h"
using namespace std;
int max_inventory = 3;
int i;
void Menu(){
book_inventory book[3];
book[0] = {1, "Lord of the Flies", 1954, "Golding, William", "2022-02-01", 0001, false};
book[1] = {2, "The Fault in Our Stars", 2012, "Green, John", "2022-01-28", 0002, true};
book[2] = {3, "Dune", 1965, "Herbert, Frank", "2022-01-28", 0001, false};
struct tm* b_date;
int i;
//getting current date/time
struct tm today = {0};
struct tm lt = {0};
time_t now;
time(&now); // get current time; same as: now = time(NULL)
lt = *localtime(&now);
//Defining "today" - making sure it is in the current year and current month
today.tm_year = 1900 + lt.tm_year;
today.tm_mon = 1 + lt.tm_mon;
today.tm_mday = lt.tm_mday;
today.tm_hour = 0;
today.tm_min = 0;
today.tm_sec = 0;
std::cout << "\nToday's date:" << today.tm_year <<"."<< today.tm_mon <<"." << today.tm_mday << endl;
tm tm1 = {0};
std::cout << "\nList of books checked out\n" << endl;
for (i = 0; i < 3; i++){
if (book[i].availability == false){ //if a book is borrowed, the book title is displayed
std::cout << book[i].title << endl;
const char* lstbrddate_str = book[i].lastborroweddate;
//getting the dates from the string
sscanf(lstbrddate_str, "%4d-%2d-%2d", &tm1.tm_year,&tm1.tm_mon,&tm1.tm_mday);
std::cout << "Date checked out:" << tm1.tm_year <<"."<< tm1.tm_mon <<"." << tm1.tm_mday << endl;
tm1.tm_sec = 0;
tm1.tm_min = 0;
tm1.tm_hour = 0;
long long b_days;
b_days = difftime(mktime(&today), mktime(&tm1)); //calculating the elapsed time between today and tm1
printf("Checked out for %lld seconds\n\n", b_days);
}
}
}
int main() {
Menu();
return 0;
}
and here is library.h:
#include <iostream>
#include <string>
#include <locale>
#include <ctime>
using namespace std;
struct book_inventory {
int id;
string title;
int year;
string author;
const char* lastborroweddate;
int lastborrowerid;
bool availability;
};
The result I get is the following :
Today's date:2022.2.22
List of books checked out
Lord of the Flies
Date checked out:2022.2.1
Checked out for 0 seconds
Dune
Date checked out:2022.1.28
Checked out for 0 seconds
From what I've read I suspect it might be an error with mktime though I am uncertain. What am I doing wrong?

Related

Calculate time difference using c++

I have a chunk of code where I am trying to convert the string time into time_t and then use the difftime() method to do a comparison. However, currently, the difftime returns 0 instead of the number of seconds differences. Can someone help me on this please.
Here's my C++ code:
const char *time_details = "16:35:12";
const char *another_time = "18:35:15";
struct tm tm = { 0 };
struct tm tm1 = { 0 };
istringstream ss(time_details);
istringstream ss1(another_time);
ss >> get_time(&tm, "%H:%M:%S"); // or just %T in this case
ss1 >> get_time(&tm1, "%H:%M:%S");
std::time_t time1 = mktime(&tm);
std::time_t time2 = mktime(&tm1);
double a = difftime(time2, time1);
cout << "the diff is : " << a;
I am following this stackoverflow solution as my reference. Really appreciate your helps on this one.
Maybe your compiler version is too low.I have no problem compiling the following code in g++ 9.
#include <ctime>
#include <sstream>
#include <iomanip>
#include <time.h>
#include <iostream>
using namespace std;
int main()
{
const char *time_details = "16:35:12";
const char *another_time = "18:35:15";
struct tm tm = { 0 };
struct tm tm1 = { 0 };
istringstream ss(time_details);
istringstream ss1(another_time);
ss >> get_time(&tm, "%H:%M:%S"); // or just %T in this case
ss1 >> get_time(&tm1, "%H:%M:%S");
std::time_t time1 = mktime(&tm);
std::time_t time2 = mktime(&tm1);
double a = difftime(time2, time1);
cout << "the diff is : " << a;
return 0;
}
The output is the diff is : 7203

How to get seconds into human readable dates

I'm trying to turn arbitrary integer values representing the seconds since Jan 1, 1970 into human readable dates.
This is as close as I've gotten, but I keep getting the current date. How can I get a struct tm of a date that is not the current date?
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
int main() {
struct tm * timeStruct;
time_t myTime = 946684800; //s from 1970 to 2000
int timeStamp = time(&myTime); //I thought this would set the date to the values of myTime, it just sets it to now
timeStruct = localtime(&myTime);
cout << timeStamp;
cout << "\n";
cout << asctime(timeStruct); //This should read Jan 1, 2000, instead it keeps giving me the current time
cout << "\n";
system("pause");
return 0;
}
time(&myTime) was setting the value of myTime to the current time (this is apparently to be expected).
Solution:
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
int main() {
struct tm * timeStruct;
time_t myTime = 946684800; //s from 1970 to 2000
int timeStamp = myTime;
timeStruct = localtime(&myTime);
cout << timeStamp;
cout << "\n";
cout << asctime(timeStruct);
cout << "\n";
system("pause");
return 0;
}

Generating a random date

I wrote this code snippet to generate random dates:
std::time_t curr_time = time(0);
std::time_t ten_years = 365 * 12 * 30 * 24 * 60;
std::time_t rand_date = curr_time - std::rand() % ten_years;
tm *ltm = std::localtime(&rand_date);
std::cout << ltm->tm_year + 1900 << " " << ltm->tm_mon + 1 << " " << ltm->tm_mday << std::endl;
However it always gives me the current date. What am i doing wrong?
std::rand() may return rather small values, 0..32767 is the minimum range, and does so on some popular 32-bit platforms (MSVC among them). With time_t in seconds this only gives you about eight hours of random noise.
Try combining the results from a pair of std::rand calls instead. E.g.
(std::time_t) std::rand() * RAND_MAX + std::rand() or switch to a better random number generator.
I would suggest you don't modify a time_t directly, as the implementation is not specified by the standard. Better to convert it a la this question: How to add one day to a time obtained from time()
I would suggest to do it differently, based on the CPP Reference:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main() {
time_t timer;
struct tm x_years;
struct tm* current;
int how_many_years = 10;
srand (time(NULL));
int randomYear = (rand()%how_many_years)+1;
int randomMonth = (rand()%12)+1;
int randomDays = (rand()%30)+1;
time(&timer); /* get current time; same as: timer = time(NULL) */
current = localtime(&timer);
x_years.tm_hour = 0;
x_years.tm_min = 0;
x_years.tm_sec = 0;
x_years.tm_year = current->tm_year - randomYear;
x_years.tm_mon = (current->tm_mon - randomMonth) <= 0 ? current->tm_mon + (12-randomMonth) : current->tm_mon - randomMonth;
x_years.tm_mday = (current->tm_mday - randomDays) <= 0 ? current->tm_mday + (30-randomDays) : current->tm_mday - randomDays;
//returns seconds ever since the random generated date until now
cout << "Years rolled back: " << randomYear << endl;
cout << "Months rolled back: " << randomMonth << endl;
cout << "Days rolled back: " << randomDays << endl;
cout << endl;
cout << "Current Year: " << current->tm_year+1900 << endl;
cout << "Current Month: " << current->tm_mon << endl;
cout << "Current Day: " << current->tm_mday << endl;
cout << endl;
cout << "Year: " << x_years.tm_year+1900 << endl;
cout << "Month: " << x_years.tm_mon << endl;
cout << "Day: " << x_years.tm_mday << endl;
}
EDIT
I have edited the code, and with it, you can even select how many years you want to go back. Basically, you go back X years in the time, and you can get the date rollbacked in the x_years struct.
Hope this helped!
The following solution uses C++11 with an internal uniform_int_distribution:
// uniform_time_dist.h
#include <chrono>
#include <random>
template <class TimePoint>
class uniform_time_distribution{
public:
uniform_time_distribution(TimePoint start, TimePoint end)
: m_start(start), m_end(end),
m_seconds(std::chrono::duration_cast<std::chrono::seconds>(end - start))
{}
template <class Generator>
TimePoint operator()(Generator && g){
std::uniform_int_distribution<std::chrono::seconds::rep> d(0, m_seconds.count());
return m_start + std::chrono::seconds(d(g));
}
private:
TimePoint m_start;
TimePoint m_end;
std::chrono::seconds m_seconds;
};
You can use it like any other distribution function with a generator:
// uniform_time_dist.h -- continuation
template <class TimePoint>
TimePoint randomTime(TimePoint start, TimePoint end){
static std::random_device rd;
static std::mt19937 gen(rd());
uniform_time_distribution<TimePoint> t(start, end);
return t(gen);
}
You can combine this method with your time_t functions by using clock::to_time_t:
#include <iostream>
#include "uniform_time_dist.h" // see above
using namespace std::chrono;
int main(){
auto k = system_clock::to_time_t(randomTime(
system_clock::now(),
system_clock::now() + hours(24 * 365 * 10)));
std::cout << std::ctime(&k);
}
Note that the class above is just a small sketch, you should be able to improve it vastly in order to match the other distribution functions.
I managed to create a solution based on Phil's answer:
time_t currTime = time(0);
tm *ltm = std::localtime(&currTime);
ltm->tm_mday = std::rand() % 3650 * -1;
time_t next = mktime(ltm);
ltm = std::localtime(&next);
std::cout << ltm->tm_year + 1900 << " " << ltm->tm_mon + 1 << " " << ltm->tm_mday << std::endl;
If you are using boost libs you can use this class that I wrote to get random dates:
#include <iostream>
#include <ctime>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/variate_generator.hpp>
#include "boost/date_time/posix_time/posix_time.hpp"
#include "boost/date_time/gregorian/gregorian.hpp"
using namespace std;
using namespace boost;
using namespace boost::posix_time;
using namespace boost::gregorian;
class Randomizer {
private:
static const bool debug_mode = false;
random::mt19937 rng_;
// The private constructor so that the user can not directly instantiate
Randomizer() {
if(debug_mode==true){
this->rng_ = random::mt19937();
}else{
this->rng_ = random::mt19937(current_time_nanoseconds());
}
};
int current_time_nanoseconds(){
struct timespec tm;
clock_gettime(CLOCK_REALTIME, &tm);
return tm.tv_nsec;
}
// C++ 03
// ========
// Dont forget to declare these two. You want to make sure they
// are unacceptable otherwise you may accidentally get copies of
// your singleton appearing.
Randomizer(Randomizer const&); // Don't Implement
void operator=(Randomizer const&); // Don't implement
public:
static Randomizer& get_instance(){
// The only instance of the class is created at the first call get_instance ()
// and will be destroyed only when the program exits
static Randomizer instance;
return instance;
}
bool method() { return true; };
int rand(unsigned int floor, unsigned int ceil){
random::uniform_int_distribution<> rand_ = random::uniform_int_distribution<> (floor,ceil);
return (rand_(rng_));
}
// Is not considering the millisecons
time_duration rand_time_duration(){
boost::posix_time::time_duration floor(0, 0, 0, 0);
boost::posix_time::time_duration ceil(23, 59, 59, 0);
unsigned int rand_seconds = rand(floor.total_seconds(), ceil.total_seconds());
return seconds(rand_seconds);
}
date rand_date_from_epoch_to_now(){
date now = second_clock::local_time().date();
return rand_date_from_epoch_to_ceil(now);
}
date rand_date_from_epoch_to_ceil(date ceil_date){
date epoch = ptime(date(1970,1,1)).date();
return rand_date_in_interval(epoch, ceil_date);
}
date rand_date_in_interval(date floor_date, date ceil_date){
return rand_ptime_in_interval(ptime(floor_date), ptime(ceil_date)).date();
}
ptime rand_ptime_from_epoch_to_now(){
ptime now = second_clock::local_time();
return rand_ptime_from_epoch_to_ceil(now);
}
ptime rand_ptime_from_epoch_to_ceil(ptime ceil_date){
ptime epoch = ptime(date(1970,1,1));
return rand_ptime_in_interval(epoch, ceil_date);
}
ptime rand_ptime_in_interval(ptime floor_date, ptime ceil_date){
time_duration const diff = ceil_date - floor_date;
long long gap_seconds = diff.total_seconds();
long long step_seconds = Randomizer::get_instance().rand(0, gap_seconds);
return floor_date + seconds(step_seconds);
}
};

How to convert std::chrono::time_point to calendar datetime string with fractional seconds?

How to convert std::chrono::time_point to calendar datetime string with fractional seconds?
For example:
"10-10-2012 12:38:40.123456"
If system_clock, this class have time_t conversion.
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std::chrono;
int main()
{
system_clock::time_point p = system_clock::now();
std::time_t t = system_clock::to_time_t(p);
std::cout << std::ctime(&t) << std::endl; // for example : Tue Sep 27 14:21:13 2011
}
example result:
Thu Oct 11 19:10:24 2012
EDIT:
But, time_t does not contain fractional seconds.
Alternative way is to use time_point::time_since_epoch() function. This function returns duration from epoch.
Follow example is milli second resolution's fractional.
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std::chrono;
int main()
{
high_resolution_clock::time_point p = high_resolution_clock::now();
milliseconds ms = duration_cast<milliseconds>(p.time_since_epoch());
seconds s = duration_cast<seconds>(ms);
std::time_t t = s.count();
std::size_t fractional_seconds = ms.count() % 1000;
std::cout << std::ctime(&t) << std::endl;
std::cout << fractional_seconds << std::endl;
}
example result:
Thu Oct 11 19:10:24 2012
925
Self-explanatory code follows which first creates a std::tm corresponding to 10-10-2012 12:38:40, converts that to a std::chrono::system_clock::time_point, adds 0.123456 seconds, and then prints that out by converting back to a std::tm. How to handle the fractional seconds is in the very last step.
#include <iostream>
#include <chrono>
#include <ctime>
int main()
{
// Create 10-10-2012 12:38:40 UTC as a std::tm
std::tm tm = {0};
tm.tm_sec = 40;
tm.tm_min = 38;
tm.tm_hour = 12;
tm.tm_mday = 10;
tm.tm_mon = 9;
tm.tm_year = 112;
tm.tm_isdst = -1;
// Convert std::tm to std::time_t (popular extension)
std::time_t tt = timegm(&tm);
// Convert std::time_t to std::chrono::system_clock::time_point
std::chrono::system_clock::time_point tp =
std::chrono::system_clock::from_time_t(tt);
// Add 0.123456 seconds
// This will not compile if std::chrono::system_clock::time_point has
// courser resolution than microseconds
tp += std::chrono::microseconds(123456);
// Now output tp
// Convert std::chrono::system_clock::time_point to std::time_t
tt = std::chrono::system_clock::to_time_t(tp);
// Convert std::time_t to std::tm (popular extension)
tm = std::tm{0};
gmtime_r(&tt, &tm);
// Output month
std::cout << tm.tm_mon + 1 << '-';
// Output day
std::cout << tm.tm_mday << '-';
// Output year
std::cout << tm.tm_year+1900 << ' ';
// Output hour
if (tm.tm_hour <= 9)
std::cout << '0';
std::cout << tm.tm_hour << ':';
// Output minute
if (tm.tm_min <= 9)
std::cout << '0';
std::cout << tm.tm_min << ':';
// Output seconds with fraction
// This is the heart of the question/answer.
// First create a double-based second
std::chrono::duration<double> sec = tp -
std::chrono::system_clock::from_time_t(tt) +
std::chrono::seconds(tm.tm_sec);
// Then print out that double using whatever format you prefer.
if (sec.count() < 10)
std::cout << '0';
std::cout << std::fixed << sec.count() << '\n';
}
For me this outputs:
10-10-2012 12:38:40.123456
Your std::chrono::system_clock::time_point may or may not be precise enough to hold microseconds.
Update
An easier way is to just use this date library. The code simplifies down to (using C++14 duration literals):
#include "date.h"
#include <iostream>
#include <type_traits>
int
main()
{
using namespace date;
using namespace std::chrono;
auto t = sys_days{10_d/10/2012} + 12h + 38min + 40s + 123456us;
static_assert(std::is_same<decltype(t),
time_point<system_clock, microseconds>>{}, "");
std::cout << t << '\n';
}
which outputs:
2012-10-10 12:38:40.123456
You can skip the static_assert if you don't need to prove that the type of t is a std::chrono::time_point.
If the output isn't to your liking, for example you would really like dd-mm-yyyy ordering, you could:
#include "date.h"
#include <iomanip>
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
using namespace std;
auto t = sys_days{10_d/10/2012} + 12h + 38min + 40s + 123456us;
auto dp = floor<days>(t);
auto time = make_time(t-dp);
auto ymd = year_month_day{dp};
cout.fill('0');
cout << ymd.day() << '-' << setw(2) << static_cast<unsigned>(ymd.month())
<< '-' << ymd.year() << ' ' << time << '\n';
}
which gives exactly the requested output:
10-10-2012 12:38:40.123456
Update
Here is how to neatly format the current time UTC with milliseconds precision:
#include "date.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
std::cout << date::format("%F %T\n", time_point_cast<milliseconds>(system_clock::now()));
}
which just output for me:
2016-10-17 16:36:02.975
C++17 will allow you to replace time_point_cast<milliseconds> with floor<milliseconds>. Until then date::floor is available in "date.h".
std::cout << date::format("%F %T\n", date::floor<milliseconds>(system_clock::now()));
Update C++20
In C++20 this is now simply:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
auto t = sys_days{10d/10/2012} + 12h + 38min + 40s + 123456us;
std::cout << t << '\n';
}
Or just:
std::cout << std::chrono::system_clock::now() << '\n';
std::format will be available to customize the output.
In general, you can't do this in any straightforward fashion. time_point is essentially just a duration from a clock-specific epoch.
If you have a std::chrono::system_clock::time_point, then you can use std::chrono::system_clock::to_time_t to convert the time_point to a time_t, and then use the normal C functions such as ctime or strftime to format it.
Example code:
std::chrono::system_clock::time_point tp = std::chrono::system_clock::now();
std::time_t time = std::chrono::system_clock::to_time_t(tp);
std::tm timetm = *std::localtime(&time);
std::cout << "output : " << std::put_time(&timetm, "%c %Z") << "+"
<< std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count() % 1000 << std::endl;
This worked for me for a format like YYYY.MM.DD-HH.MM.SS.fff. Attempting to make this code capable of accepting any string format will be like reinventing the wheel (i.e. there are functions for all this in Boost.
std::chrono::system_clock::time_point string_to_time_point(const std::string &str)
{
using namespace std;
using namespace std::chrono;
int yyyy, mm, dd, HH, MM, SS, fff;
char scanf_format[] = "%4d.%2d.%2d-%2d.%2d.%2d.%3d";
sscanf(str.c_str(), scanf_format, &yyyy, &mm, &dd, &HH, &MM, &SS, &fff);
tm ttm = tm();
ttm.tm_year = yyyy - 1900; // Year since 1900
ttm.tm_mon = mm - 1; // Month since January
ttm.tm_mday = dd; // Day of the month [1-31]
ttm.tm_hour = HH; // Hour of the day [00-23]
ttm.tm_min = MM;
ttm.tm_sec = SS;
time_t ttime_t = mktime(&ttm);
system_clock::time_point time_point_result = std::chrono::system_clock::from_time_t(ttime_t);
time_point_result += std::chrono::milliseconds(fff);
return time_point_result;
}
std::string time_point_to_string(std::chrono::system_clock::time_point &tp)
{
using namespace std;
using namespace std::chrono;
auto ttime_t = system_clock::to_time_t(tp);
auto tp_sec = system_clock::from_time_t(ttime_t);
milliseconds ms = duration_cast<milliseconds>(tp - tp_sec);
std::tm * ttm = localtime(&ttime_t);
char date_time_format[] = "%Y.%m.%d-%H.%M.%S";
char time_str[] = "yyyy.mm.dd.HH-MM.SS.fff";
strftime(time_str, strlen(time_str), date_time_format, ttm);
string result(time_str);
result.append(".");
result.append(to_string(ms.count()));
return result;
}
I would have put this in a comment on the accepted answer, since that's where it belongs, but I can't. So, just in case anyone gets unreliable results, this could be why.
Be careful of the accepted answer, it fails if the time_point is before the epoch.
This line of code:
std::size_t fractional_seconds = ms.count() % 1000;
will yield unexpected values if ms.count() is negative (since size_t is not meant to hold negative values).
In my case I use chrono and c function localtime_r which is thread-safe (in opposition to std::localtime).
#include <iostream>
#include <chrono>
#include <ctime>
#include <time.h>
#include <iomanip>
int main() {
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::chrono::milliseconds now2 = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
struct tm currentLocalTime;
localtime_r(&currentTime, &currentLocalTime);
char timeBuffer[80];
std::size_t charCount { std::strftime( timeBuffer, 80,
"%b %d %T",
&currentLocalTime)
};
if (charCount == 0) return -1;
std::cout << timeBuffer << "." << std::setfill('0') << std::setw(3) << now2.count() % 1000 << std::endl;
return 0;
}
If you are to format a system_clock::time_point in the format of numpy datetime64, you could use:
std::string format_time_point(system_clock::time_point point)
{
static_assert(system_clock::time_point::period::den == 1000000000 && system_clock::time_point::period::num == 1);
std::string out(29, '0');
char* buf = &out[0];
std::time_t now_c = system_clock::to_time_t(point);
std::strftime(buf, 21, "%Y-%m-%dT%H:%M:%S.", std::localtime(&now_c));
sprintf(buf+20, "%09ld", point.time_since_epoch().count() % 1000000000);
return out;
}
sample output: 2019-11-19T17:59:58.425802666

C++ Mingw: Two objects of the same class are changing the data across eachother

I am a newbie. Using class clsMRDateTime and am creating 2 instances of objects in the main code. When I activate the line:
clsMRDateTime objMRDateTimeURL("10_05_2011");//THIS CAUSES THE PROBLEM!!!!!
It causes the date in the first instance of the class to match the second instance of the class. I checked for static class variables, and cannot figure this out.
I removed all of the inactive methods.
Thank you for any help you can provide.
Michael
Sample Test Main():
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "clsMRConvert.h"
#include "clsMRDebug.h"
#include "clsMRDateTime.h"
int main(int argc, char *argv[])
{
printf("Content-type: text/html\n\n");
cout << "";
cout << "Hello Test";
clsMRDateTime objMRDateTimeToday("08_25_2010");
cout << "<BR>";
string strTodayDate = objMRDateTimeToday.strGetFormatedTime("%m/%d/%Y");
cout << "objMRDateTimeToday: " << strTodayDate;
cout << "<BR>";
cout << "<BR>";
clsMRDateTime objMRDateTimeURL("10_05_2011");//THIS CAUSES THE PROBLEM!!!!!
cout << "<BR>";
//string strURLDate = objMRDateTimeURL.strGetFormatedTime("%m/%d/%Y");
//cout << "objMRDateTimeURL: " << strURLDate;
cout << "<BR>";
cout << "<BR>";
strTodayDate = objMRDateTimeToday.strGetFormatedTime("%m/%d/%Y");
cout << "objMRDateTimeToday: " << strTodayDate << " [SHOULD BE SAME AS ABOVE!!!]";
}
Class clsMRDateTime:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include "clsMRDateTime.h"
using namespace std;
clsMRDateTime::clsMRDateTime(string strDateAsString)
{
size_t found = strDateAsString.find('_');
if (found!=string::npos)
{
this->intSetDateTimeURL(strDateAsString);
}
else
{
}
}
clsMRDateTime::clsMRDateTime( time_t timetDateAsTimeT)
{
this->intSetDateTime(timetDateAsTimeT);
}
int clsMRDateTime::intSetDateTime(string strDateAsString)
{
int intDay, intMonth, intYear;
sscanf((char *)(strDateAsString.c_str()), "%d/%d/%d", &intMonth, &intDay, &intYear);
this->timetClassMainTime = this->timetMakeTime(12, 0, 0,
intMonth, intDay, intYear);
this->tmClassMainTimeTM = this->tmGetTimeInTMFormat();
}
int clsMRDateTime::intSetDateTimeURL(string strDateAsString)
{
int intDay, intMonth, intYear;
sscanf((char *)(strDateAsString.c_str()), "%d_%d_%d", &intMonth, &intDay, &intYear);
this->timetClassMainTime = this->timetMakeTime(12, 0, 0,
intMonth, intDay, intYear);
this->tmClassMainTimeTM = this->tmGetTimeInTMFormat();
}
int clsMRDateTime::intSetDateTime(time_t timetDateAsTimeT)
{
this->timetClassMainTime = timetDateAsTimeT;
this->tmClassMainTimeTM = this->tmGetTimeInTMFormat();
}
int clsMRDateTime::intSetDateTime(struct tm * tmDateAsStructTM)
{
this->timetClassMainTime = mktime(tmDateAsStructTM);
this->tmClassMainTimeTM = this->tmGetTimeInTMFormat();
}
time_t clsMRDateTime::timetMakeTime(int intHour, int intMin, int intSec,
int intMonth, int intDay, int intYear)
{
struct tm * timeinfo;
time_t time_tSeconds;
time_t rawtime;
try{
//time ( &rawtime );
timeinfo = localtime ( &this->timetClassMainTime );
timeinfo->tm_year = intYear-1900;
timeinfo->tm_mon = intMonth -1;
timeinfo->tm_mday = intDay;
timeinfo->tm_hour = intHour;
timeinfo->tm_min = intMin;
timeinfo->tm_sec = intSec;
timeinfo->tm_isdst = 0;
time_tSeconds = mktime(timeinfo);
}
catch (char * str )
{
cout << "Exception raised: " << str << '\n';
return(1);
}
return(time_tSeconds);
}
string clsMRDateTime::strGetFormatedTime(string strFormat)
{
string strFormattedTime = "";
strFormattedTime = this->strGetFormatedTimeForNewDates(strFormat, this->tmClassMainTimeTM);
return(strFormattedTime);
}
string clsMRDateTime::strGetFormatedTimeForNewDates(string strFormat, struct tm *tmNewDate)
{
string strFormattedTime;
char s[80];
size_t i;
strftime(s,80,strFormat.c_str(),tmNewDate);
strFormattedTime = s;
return(strFormattedTime);
}
time_t clsMRDateTime::timetGetGregoreanTimeStamp()
{
return(this->timetClassMainTime);
}
struct tm *clsMRDateTime::tmGetTimeInTMFormat()
{
this->tmClassMainTimeTM = localtime(&this->timetClassMainTime);
}
clsMRDateTime::tmClassMainTimeTM is a pointer to a struct tm, so when you do this->tmClassMainTimeTM = localtime(&this->timetClassMainTime); you are in fact saving off a pointer to the return value from localtime.
The localtime function reuses a static tm structure, so the return value is the same every time. What you've done is set it up so each instance of clsMRDateTime winds up storing a pointer to the same struct tm so they all end up representing the most recently set date/time.
What you need to do is make tmClassMainTimeTM NOT a pointer (make it just a struct tm) and then do something like this->tmClassMainTimeTM = *localtime(&this->timetClassMainTime);.
Better is to review the man page for localtime_r which is thread safe and allows you to pass in your own struct and use that instead.
You don't show clsMRDateTime.h, but I'm betting in that file you have your member variables declared as static. They shouldn't be.
I would scrutinize any calls to gmtime() or localtime() since they share and reuse a statically allocated structure.
The only other candidate that sticks out is the empty else statement in the first constructor.