C++ strftime在iOS上返回不正确的星期几

C++ strftime在iOS上返回不正确的星期几,c++,ctime,C++,Ctime,我有以下代码: #include <iostream> #include <ctime> using namespace std; int main() { tm _tm; strptime("2017-04-17", "%Y-%m-%d", &_tm); char buf[16]; strftime(buf, sizeof(buf), "%A", &_tm); cout << buf <&

我有以下代码:

#include <iostream>
#include <ctime>
using namespace std; 

int main() {
    tm _tm;
    strptime("2017-04-17", "%Y-%m-%d", &_tm);

    char buf[16];
    strftime(buf, sizeof(buf), "%A", &_tm);

    cout << buf << endl;
}
#包括
#包括
使用名称空间std;
int main(){
tm_tm;
STRTIME(“2017-04-17”,%Y-%m-%d”,&U tm);
char-buf[16];
strftime(buf,sizeof(buf),“%A”和_tm);

cout
strptime()
仅更新提供的
struct tm
中格式字符串中指定的字段。其他字段单独保留(在您的情况下未初始化)。

有两个问题导致问题中的行为

  • strtime
    似乎在解析日期时意外地使本地时区生效(但仅用于设置一周中的某一天!)。它似乎在解析“2017-04-17”时,至少对于一周中的某一天,它将其视为类似UTC午夜的东西——这意味着UTC在该“时间”的一周中的某一天会出现负偏移是早了一天

    基本上,
    strtime
    总是给我
    tm_wday
    一个小于正确值的值。当解析“2017-04-17”(星期一)和“2017-04-18”(星期二)时,它将返回
    0
    (星期日)

    非常奇怪的是,它不会填充其他时区数据,如
    tm_isdst
    tm_gmtoff
    。它会保持这些数据不变——只需为
    tm_wday
    选择一个不正确的值

    我可以通过调用从
    strptime
    返回的生成的
    tm
    结构上的
    mktime
    来解决这个问题。我没有使用从
    mktime
    返回的
    time
    ,但是在
    tm
    结构上调用
    mktime
    的行为正确地设置了
    tm\u-wday
    的值,并且纠正了错误仅设置
    tm_isdst
    tm_gmtoff
    等的值

  • 我没有将
    tm
    结构初始化为零。这只有在我开始调用
    mktime
    时才真正起作用。没有正确的初始化,
    mktime
    会因为
    tm\gmtoff
    的垃圾值而损坏日期。正确初始化后,调用
    mktime
    会给出一个格式良好的日期正确的
    tm_wday
    设置

  • 因此,一个有效的例子如下:

    tm _tm = {};
    strptime("2017-04-17", "%Y-%m-%d", &_tm); // Incorrect tm_wday after this call
    mktime(&_tm); // Correct tm_wday after this call
    
    char buf[16];
    strftime(buf, sizeof(buf), "%A", &_tm);
    

    这不是一个答案,但可能是一个解决方案:

    如果您可以在C++11或更高版本中工作,您可以在两种平台上得到相同的答案

    #include "date.h"
    #include <iostream>
    #include <sstream>
    
    int
    main()
    {
        using namespace std;
        istringstream in{"2017-04-17"};
        date::year_month_day ymd;
        in >> parse("%Y-%m-%d", ymd);
        cout << format("%A\n", ymd);
    }
    
    此库将解析和格式化解释为以UTC隐式表示,没有时区或计算机当前本地时区的诡计。如果您需要该功能,它将存在于一个数据库中

    “%F”
    也可用作
    “%Y-%m-%d”
    的简写,作为POSIX
    strtime
    规范的扩展

    in >> parse("%F", ymd);
    

    这是一个非常完整的DATE时间库,可以处理一年中的粗糙特征,以及与纳秒一样高的时间戳。它都是在C++的代码> < /C>库中建立的,因此完全是类型安全的。随后比C/POSIX API更容易使用,在编译时检测到许多逻辑错误。/p> 在man7.org上,“使用了环境变量TZ和LC_TIME。”运行程序时,您可能需要检查每个系统上的两个值。@WeatherVane我认为这也是一个有效的C问题。请不要删除标记。@Olaf您真的需要我将其重新格式化为C以显示它也是一个有效的C问题吗?@Aardvark…是吗?在其当前形式中,问题中没有与C相关的内容on.和

    strtime
    不是标准函数。ideone当然不是自动循环引用。在这种情况下,
    tm_wday
    实际上设置为0。我尝试手动将其设置为1,但
    strtime
    将其重置为0(星期日,而不是星期一)。因此,我不认为这是问题所在,尽管将结构初始化为零显然是我的最佳实践。但这并不能解决问题。我认为@yellowantphil可能是对的?这可能是一个时区问题。我提供的日期被解释为时间(可能是UTC)。因为我的UTC偏移量是负数,所以它会将工作日计算为前一天?这是我的运行理论……我相信它可能与
    tm_isdst
    (与时区相关)。我不太确定这个答案-在删除它之前,我会让它保留一段时间,但我想有人会想出一个更好的答案。哦,
    mktime
    确实需要零初始化值,否则它会将日期转换为一个非常不稳定的值!所以基本上我必须对值retu进行零初始化并调用
    mktime
    strtime
    调用,将其转换为本地时区值,以便检索正确的
    wday
    值。
    Monday
    
    in >> parse("%F", ymd);