timegm 跨平台

新手上路,请多包涵

我正在使用 Visual Studio c++ Compiler ( 2010 ),但该库具有不同的 ANSI C 和 POSIX 库函数实现。

ANSI C 函数和 Windows CRT 实现有什么区别?例如 tzset()_tzset()setenv() ans _setenv() 什么区别?似乎以同样的方式做同样的事情……

我正在使用 msvc ( 2010 ),我是否更喜欢 Windows CRT 实现?

编辑 1

好吧,我想以一种可移植的方式将 struct tm 转换为 time_t 中的 UTC,但是没有可移植的方法可以做到这一点。我必须为不同的平台(Android、Linux、Windows、Windows CE)编写函数。

我看过这个使用 setenvgetenvtzset 的stackoverflow帖子

编辑2

不幸的是,经过一些测试,我发现 getenv("TZ") 在 Windows 上返回一个空指针。但是为什么将 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;
}

原文由 Elvis Dukaj 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 881
2 个回答

我在 Windows 上使用以下宏:

 #define timegm _mkgmtime

正如 _mkgmtime 一样。

原文由 Naszta 发布,翻译遵循 CC BY-SA 3.0 许可协议

早在 1989 年,当 David Cutler 的团队开始着手 Windows NT 设计时,他们还不知道哪个 api 将占主导地位。所以他们创造了 _三个_。 Win32 是对 16 位版本的 Windows api 的改编。支持 OS/2,该操作系统应该取代 DOS,但没有。 Posix 是第三个,因为当时美国政府指定他们只会考虑使用遵循新兴 Posix 标准的操作系统。

您提到的 tzset() 函数是 Posix api 的遗留函数。你可能拼错了 putenv(),同样的故事。子系统表现不佳,Win32 在 api 大战中大获全胜,并且在 2001 年从 Windows 中删除了对 Posix 的支持。微软保留了对 Posix 函数的支持,但由于它们不是标准的一部分,所以用前导下划线重命名它们C 库。当您使用函数的非前缀版本时,您应该会收到弃用警告。听起来像你 #defined _CRT_NONSTDC_NO_DEPRECATE 来压制它们。最好不要那样做。支持标准 C 库函数。

原文由 Hans Passant 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题