timegm cross platform
timegm cross platform
我使用Visual Studio c++ Compiler(2010),但该库具有不同的ANSI c和POSIX库功能实现。
ANSI C函数和Windows CRT实现的区别是什么?例如,tzset()
和_tzset()
或者setenv()
和_setenv()
有什么区别?似乎他们用同样的方法做同样的事情……
我使用msvc(2010),我更喜欢Windows CRT实现吗?
EDIT 1
我想以一种可移植的方式转换在time_t
中以UTC表示的struct tm,但是没有可移植的方式来做到这一点。我必须为不同的平台(Android, Linux, Windows, Windows CE)编写函数。
我看到这个stackoverflow帖子使用setenv
, getenv
和tzset
不幸的是,经过一些测试,我发现getenv("TZ")
在windows上返回一个空指针。但是为什么将UTC时间结构转换为time_t
时间结构如此困难呢?
从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;
}
我在Windows上使用以下宏:
#define timegm _mkgmtime
1989年,当David Cutler的团队开始设计Windows NT时,他们还不知道哪个api将占据主导地位。所以他们创造了三个。Win32是对16位版本的Windows api的改编。OS/2得到了支持,这个操作系统被认为会取代DOS,但并没有。Posix是第三个,因为当时美国政府规定他们只考虑使用遵循新兴Posix标准的操作系统。
你提到的tzset()函数是从Posix api遗留下来的。你可能拼错了putenv(),同样的故事。这个子系统的表现并不好,Win32在api大战中大获全胜,Windows在2001年取消了对Posix的支持。微软保留了对Posix函数的支持,但将它们重命名为前导下划线,因为它们不是标准C库的一部分。当您使用函数的无前缀版本时,应该会得到弃用警告。听起来像你#定义_CRT_NONSTDC_NO_DEPRECATE来抑制它们。最好不要那样做。使用标准的C库函数
// Algorithm: http://howardhinnant.github.io/date_algorithms.html
int days_from_epoch(int y, int m, int d)
{
y -= m <= 2;
int era = y / 400;
int yoe = y - era * 400; // [0, 399]
int doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365]
int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
return era * 146097 + doe - 719468;
}
// It does not modify broken-down time
time_t timegm(struct tm const* t)
{
int year = t->tm_year + 1900;
int month = t->tm_mon; // 0-11
if (month > 11)
{
year += month / 12;
month %= 12;
}
else if (month < 0)
{
int years_diff = (11 - month) / 12;
year -= years_diff;
month += 12 * years_diff;
}
int days_since_epoch = days_from_epoch(year, month + 1, t->tm_mday);
return 60 * (60 * (24L * days_since_epoch + t->tm_hour) + t->tm_min) + t->tm_sec;
}
这是一个将UTC中的tm转换为time_t的可移植方法。
请注意,它不会修改/规范化tm结构,也不会改变任何tz设置。
对于我所知道的大多数函数,这是没有区别的。
名称中的下划线是为了强调这些不是标准C函数:AFAIK,在ANSI C中没有tzset
和setenv
函数。它们主要是POSIX函数,由MS CRT实现,以帮助从其他操作系统移植。
但是它们没有声明POSIX兼容性,这就是下划线的原因。这就是为什么你应该仔细阅读微软关于这些函数的文档…那里有恶魔!
我的timegm
实现在windows上工作。
time_t timegm(struct tm * a_tm)
{
time_t ltime = mktime(a_tm);
struct tm tm_val;
gmtime_s(&tm_val, <ime);
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;
}
- 如何解决"no Qt platform plugin could be initialized"问题?
- WinAPI IcmpSendEcho on 64-bit platform
- Webots Visual Studio Cross-complitation
- 如何将Unix库添加到Visual Studio for Cross Compilation?
- Visual Studio Platform 工具集和运行时库
- 尝试在构造函数中的"glm::cross"处初始化我的类段错误
- Platform::String 和 std::string 之间的区别
- NetBeans C++ Cross-Plattform(Mac和Linux)同时与Git
- Cross Compile WebRTC+OpenCV for Raspberry PI
- Eclipse Oxygen C++ Hello World Cross GCC error
- C++/CX - 我需要将一个 Platform::String 传递到一个接受常量字符*的方法中
- 类似的函数,如sp.linalg.norm,sp.cross在C++
- 如何将Platform::String转换为char*
- 将Platform::String转换为std::String
- Cross-platform WebViews
- BeagleBoneBlack Cross Compile on Mac Error
- 如何使用 Debian 制作一个 Cross-toolchain 来编译从 Win7+Eclipse+MinGW+wxW
- 什么是视觉工作室项目中"Platform Toolset"设置
- timegm cross platform
- C vs C++ - cross-platform