1

I am getting String from server 11/07/2020 10:57:13 which I am converting to double value 1604723233, however converted double value is less than actual value by 1 hour.

Below is how I am trying to convert...

double StringDateToDouble(string &strDate, string format)
{
    tm currentTime = CurrentTimeToTM();
    tm timeinfo;

    string strTimeZone = currentTime.tm_zone;

    strDate.append("");
    strDate.append(strTimeZone);
    strptime(strDate.c_str(), format.c_str(), &timeinfo);

    time_t timeInSec = mktime(&timeinfo);
    return static_cast<double>(timeInSec);
 }

tm CurrentTimeToTM()
{
 struct tm timeinfo = {0};
 time_t rawtime;
 rawtime = time(&rawtime);

 localtime_r(&rawtime, &timeinfo);
 return timeinfo;
}

What is the correct way? is anything missed here? Any suggetion is appreciated.

David Ranieri
  • 39,972
  • 7
  • 52
  • 94
Vijay
  • 156
  • 1
  • 14
  • 1
    What is the purpose of the code? Why do you need a `double` of a date? How is a date represented using a `double`? – Some programmer dude Nov 07 '20 at 06:21
  • The C++ standard does not guarantee that `time_t(0)` is `1970-01-01T00:00Z`. C++20 introduced a guarantee that `time_since_epoch` will be relative to the UNIX epoch. – brc-dd Nov 07 '20 at 06:34
  • By the way, there's no guarantee that [`std::time_t`](https://en.cppreference.com/w/cpp/chrono/c/time_t) is an integer type, or that its value is a number of seconds since some epoch. – Some programmer dude Nov 07 '20 at 06:37
  • Is the date in your string DD/MM/YYYY or MM/DD/YYYY? – brc-dd Nov 07 '20 at 06:47
  • 1
    Oh, times off by exactly one hour sounds like a daylight savings issue. – Some programmer dude Nov 07 '20 at 07:03
  • Try this : https://wandbox.org/permlink/dgHrTPRBMx27M8zr. Run this on the same system you were running your earlier code as on the server the timezone may be different from yours. I noticed from your profile that you are from India. So, this code should give : `1604726833` as the output (`3600` (1hr) more than `1604723233`, i.e. what you were expecting) . – brc-dd Nov 07 '20 at 07:07
  • @brc-dd I tried `11/07/2020 12:59:22` and output was `1604721562` which online converter shows(https://www.timestampconvert.com) `11/7/2020, 9:29:22` – Vijay Nov 07 '20 at 07:33
  • 1
    @Vijay it is because of difference in time zones. The response which you are getting from your server is in which time zone? – brc-dd Nov 07 '20 at 07:55
  • @brc-dd oh we are getting timezone as a IST – Vijay Nov 07 '20 at 08:00
  • @Vijay I had clearly written in my comment to run the code on your system, not on wandbox itself. Wandbox servers are located in Japan most probably that's why `std::mktime` is giving you different localtime. If your server sends time in IST then better use this code : https://wandbox.org/permlink/y9KJPXKoiuaQHY1o I have specified time zone here. So the local timezone of the system or say the app that you are building won't matter now. – brc-dd Nov 07 '20 at 08:32

1 Answers1

0

Here is my suggested code:

#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

const int IST = (5 * 60 + 30) * 60; // GMT+05:30 (in s)

double StringDateToDouble(std::string &&strDate,
                          std::string &&format = "%D %T") {
  std::tm tm;
  std::istringstream ss(strDate);
  ss >> std::get_time(&tm, format.c_str());
  return (std::mktime(&tm) - timezone) - IST;
}

int main() { std::cout << (long)StringDateToDouble("11/07/2020 12:59:22"); }

References:

  1. How to convert a string variable containing time to time_t type in c++?

  2. std::mktime and timezone info

  3. Get Unix timestamp with C++


As mentioned in the second reference, std::mktime(&tm) - timezone will give time in GMT. Now since your server is sending responses in IST, you need to manually subtract that from it to get the time since the Epoch.


Note that it is not guaranteed by the C++ standard that 1970-01-01T00:00Z is std::time_t(0).

Citing from std::time:

The encoding of calendar time in std::time_t is unspecified, but most systems conform to POSIX specification and return a value of integral type holding the number of seconds since the Epoch. Implementations in which std::time_t is a 32-bit signed integer (many historical implementations) fail in the year 2038.

Refer to the thread mentioned as reference 3 for more discussion on this.

brc-dd
  • 10,788
  • 3
  • 47
  • 67