кросс-платформенный

Я использую Visual Studio c ++ Compiler (2010), но библиотека имеет другую реализацию функций библиотек ANSI C и POSIX.

В чем разница между функцией ANSI C и реализацией Windows CRT? Например, в чем разница между tzset() а также _tzset() или же setenv() анс _setenv()? Кажется, делают то же самое таким же образом …

Я использую msvc (2010), я предпочитаю реализацию Windows CRT?

РЕДАКТИРОВАТЬ 1

Ну, я хочу преобразовать переносимым способом struct tm, выраженную в UTC в time_t, но нет портативного способа сделать это. Я должен написать функцию для другой платформы (Android, Linux, Windows, Windows CE).

я видел этот стековый пост который использует setenv, getenv а также tzset

Edit2

К сожалению, после некоторого теста я обнаружил, что getenv("TZ") возвращает нулевой указатель на окна. Но почему так сложно преобразовать структуру времени UTC в time_t?

Редактировать 3

Из Boost я обнаружил этот фрагмент кода в boost / chrono / io / time_point_io.hpp. Надеюсь, это поможет мне.

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;
}

13

Решение

Я использую следующий макрос в Windows:

#define timegm _mkgmtime

как _mkgmtime делает то же самое.

19

Другие решения

Когда команда Дэвида Катлера начала разрабатывать Windows NT в далеком 1989 году, они еще не знали, какой API будет доминирующим. Так они создали три из них. Win32 была адаптацией 16-битной версии Windows API. OS / 2 была поддержана, операционная система, которая должна была заменить DOS, но не сделала этого. И Posix был третьим, добавленным, потому что правительство США тогда указало, что они рассмотрят только использование операционных систем, которые следуют за появляющимся стандартом Posix.

Упомянутая вами функция tzset () является остатком API Posix. Вы наверное неправильно написали putenv (), та же история. Подсистема работала не очень хорошо, Win32 выиграл битву api, а поддержка Posix была удалена из Windows в 2001 году. Microsoft сохранила поддержку функций Posix, но переименовала их с лидирующим подчеркиванием, поскольку они не являются частью стандарта. С библиотека. Вы должны получать предупреждения об устаревании, когда используете версию без префикса функций. Похоже, вы #defined _CRT_NONSTDC_NO_DEPRECATE, чтобы подавить их. Лучше не делать этого. Воспользуйтесь стандартными функциями библиотеки C.

7

Для большинства функций, о которых я знаю, нет никакой разницы.

Подчеркивание в именах подчеркивает, что это не стандартные функции C: AFAIK, нет tzset ни setenv функции в ANSI C. В основном это функции POSIX, которые реализованы MS CRT в качестве помощи для переносимости из других операционных систем.

Но они не претендуют на совместимость с POSIX, поэтому подчеркиваем. И именно поэтому вы должны быть осторожны и читать документацию MS об этих функциях … там есть демоны!

3

Моя реализация timegm работает на окнах.

time_t timegm(struct tm * a_tm)
{
time_t ltime = mktime(a_tm);
struct tm tm_val;
gmtime_s(&tm_val, &ltime);
int offset = (tm_val.tm_hour - a_tm->tm_hour);
if (offset > 12)
{
offset = 24 - offset;
}
time_t utc = mktime(a_tm) - offset * 3600;
return utc;
}

Все должно быть в порядке.

1