1

I am getting the beginning of Epoch, where I should get current time:

date.hpp:

#ifndef DATE_HPP
#define DATE_HPP

#include <time.h>
#include <iostream>
#include <sstream>

class Date
{
    std::stringstream format;
    struct tm *date_tm;
    time_t date;

public:
    Date() : date(time(NULL)), date_tm(localtime(&date)) {}
    Date(std::istream &in);
    Date(std::string str);

    const std::string getDate();
};

#endif //DATE_HPP

date.cpp:

#include "date.hpp"
#include <iostream>
#include <sstream>
#include <iomanip>

Date::Date(std::istream &in)
{
    std::cout << "enter date [mm/dd/yy]: ";
    format.basic_ios::rdbuf(in.rdbuf());
    format >> std::get_time(date_tm, "%m/%d/%y");
}

Date::Date(std::string str)
{
    format << str;
    format >> std::get_time(date_tm, "%m/%d/%y");
}

const std::string Date::getDate()
{
    format << std::put_time(date_tm, "%m/%d/%y");
    return format.str();
}

main.cpp:

#include "date.hpp"
#include <iostream>

int main()
{
    Date now;
    std::cout << now.getDate() << std::endl;
}

When I run it ./a.out, I get 01/01/70. Well obviously, I would expect current time, since the time(NULL) which is used in localtime(now), should contain seconds from Epoch till now. So what could went wrong?

kaylum
  • 13,833
  • 2
  • 22
  • 31
milanHrabos
  • 2,010
  • 3
  • 11
  • 45

1 Answers1

1

Aside from the defects mentioned in the comments (localtime() returns a pointer to a global) you're running into a construction order issue.

In your class, date_tm is constructed/initialized before date, regardless of their order in the initialization list.

Change your class definition to see the results you expect:

class Date
{
    std::stringstream format;
    time_t date;        // ensure date is constructed/initialized before date_tm
    struct tm *date_tm;

    // ...
}

(see: https://ideone.com/FRJrdB)

As stated in the comments, the compiler should warn you about this if you have the proper warning levels enabled.

Chad
  • 18,706
  • 4
  • 46
  • 63
  • what is "pointer to global", how it differs to "pointer to local"? – milanHrabos Nov 17 '20 at 20:24
  • I thought, having pointer declared *inside* of class declaration, would not make it global – milanHrabos Nov 17 '20 at 20:24
  • @milanHrabos, The global thing is the object being pointed to by the return value of `localtime`, and hence pointed to by your class member as well. Calling `localtime` twice (or a few other functions that share that state) can overwrite the object while you're still pointing to it and return the same pointer instead of returning a pointer to a new object. If it helps, you can think of the `localtime` implementation as something like `tm g_state; tm* localtime(const time_t* t) { g_state = calculate_local_time(t); return &g_state; }` – chris Nov 17 '20 at 21:25