timegm cross platform

Elvis Dukaj picture Elvis Dukaj · May 20, 2013 · Viewed 17.3k times · Source

I'm using Visual Studio c++ Compiler ( 2010 ), but the library has different implementation of ANSI C and POSIX libraries function.

What is the difference between ANSI C function and Windows CRT implementation? For example what is the difference between tzset() and _tzset() or setenv() ans _setenv()? It seems the do the same thing in the same way...

I'm using msvc ( 2010 ), have I to prefer the Windows CRT Implementation?

EDIT 1

Well I want convert in a portable way a struct tm expressed in UTC in a time_t, but there's no portable way to do that. I've to write the function for different platform (Android, Linux, Windows, Windows CE ).

I've seen this stackoverflow post that uses setenv, getenv and tzset

Edit2

Unfortunately after some test I've discovered that getenv("TZ") returns a null pointer on windows. But why is so difficult transform a UTC time struct to a time_t?

Edit 3

From Boost I discovered this fragment of code in boost/chrono/io/time_point_io.hpp. Hope this helps me.

inline int32_t is_leap(int32_t year)
{
  if(year % 400 == 0)
  return 1;
  if(year % 100 == 0)
  return 0;
  if(year % 4 == 0)
  return 1;
  return 0;
}
inline int32_t days_from_0(int32_t year)
{
  year--;
  return 365 * year + (year / 400) - (year/100) + (year / 4);
}
inline int32_t days_from_1970(int32_t year)
{
  static const int days_from_0_to_1970 = days_from_0(1970);
  return days_from_0(year) - days_from_0_to_1970;
}
inline int32_t days_from_1jan(int32_t year,int32_t month,int32_t day)
{
  static const int32_t days[2][12] =
  {
    { 0,31,59,90,120,151,181,212,243,273,304,334},
    { 0,31,60,91,121,152,182,213,244,274,305,335}
  };
  return days[is_leap(year)][month-1] + day - 1;
}

inline time_t internal_timegm(std::tm const *t)
{
  int year = t->tm_year + 1900;
  int month = t->tm_mon;
  if(month > 11)
  {
    year += month/12;
    month %= 12;
  }
  else if(month < 0)
  {
    int years_diff = (-month + 11)/12;
    year -= years_diff;
    month+=12 * years_diff;
  }
  month++;
  int day = t->tm_mday;
  int day_of_year = days_from_1jan(year,month,day);
  int days_since_epoch = days_from_1970(year) + day_of_year;

  time_t seconds_in_day = 3600 * 24;
  time_t result = seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec;

  return result;
}

Answer

Naszta picture Naszta · Apr 2, 2015

I use the following macro on Windows:

#define timegm _mkgmtime

as _mkgmtime does the same.