Порядок элементов в strptime

Я пытаюсь использовать strptime(buf, &pattern,&result) для преобразования char[], содержащего дату, в структуру tm.

Я использую такую ​​функцию:

if(strptime(buf, &pattern,&result) == NULL)
   {
      printf("\nstrptime failed\n");
...

и все работает, если мои переменные определены так:

char buf[] = "26/10/2011";
char pattern[] = "%d/%m/%y";
struct tm result;

но если я изменю их на:

char buf[] = "2011/26/10";
char pattern[] = "%y/%d/%m";
struct tm result;

Я получаю "strptime failed". Обратите внимание, что я поставил только год в начале (как в buf, так и в pattern).

Помощь приветствуется. Моя конечная цель - преобразовать строку в этот формат: 2011-10-26T08:39:21


person Adam Pierzchała    schedule 26.10.2011    source источник
comment
Вы уверены, что правильно скопировали сюда код? Переменная pattern не должна использовать оператор адреса в вызове strptime.   -  person Some programmer dude    schedule 26.10.2011


Ответы (2)


Это потому, что %y в нижнем регистре обозначает двузначный год внутри века. Попробуйте изменить его на верхний регистр %Y, и он будет работать нормально. Вы можете увидеть это из следующей программы:

#include <stdio.h>
#include <time.h>
int main (void) {
    char buf[] = "26/10/2011";
    char pattern[] = "%d/%m/%y";
    struct tm result;
    if (strptime (buf, pattern, &result) == NULL) {
        printf("strptime failed\n");
        return -1;
    }
    printf ("%d\n", 1900 + result.tm_year);
    return 0;
}

Это выводит 2020, что означает, что год читается как часть 20 от 2011, а остальная часть игнорируется. Если вы используете %Y в верхнем регистре, вместо этого выводится правильное 2011.

Код, который генерирует ошибку преобразования с использованием обратного формата:

#include <stdio.h>
#include <time.h>
int main (void) {
    char buf[] = "2011/10/26";
    char pattern[] = "%y/%m/%d";
    struct tm result;
    if (strptime (buf, pattern, &result) == NULL) {
        printf("strptime failed\n");
        return -1;
    }
    printf ("%d\n", 1900 + result.tm_year);
    return 0;
}

будет работать нормально (т. е. выводить 2011), когда вы измените значение pattern на "%Y/%m/%d".

person paxdiablo    schedule 26.10.2011
comment
аааа, такая опечатка... Ненавижу. Просто чтобы убедиться, что я получаю tm_mon: 9 вместо 10? - person Adam Pierzchała; 26.10.2011
comment
Это в стандарте: int tm_mon Month of year [0,11]. Итак, январь 0, а не 1. - person cnicutar; 26.10.2011
comment
@cnicutar здесь я нашел месяц [1-12].... - person Adam Pierzchała; 26.10.2011
comment
@AdamPierzchała Это для strptime. Я говорил о struct tm (то же, о чем вы говорили в своем предыдущем комментарии). - person cnicutar; 26.10.2011

Используя мои собственные команды «strptime» и «timestamp», я получаю:

$ strptime -T '%y/%d/%m' 2011/26/11
strptime: failed to convert <2011/26/11> using format <%y/%d/%m>
$ strptime -T '%Y/%d/%m' 2011/26/11
1322294400 = 2011/26/11
$ strptime -T '%d/%m/%y' 26/11/2011
1606377600 = 26/11/2011
$ timestamp 1322294400 1606377600
1322294400 = Sat Nov 26 00:00:00 2011
1606377600 = Thu Nov 26 00:00:00 2020
$

(Часовой пояс США/Тихий океан, в настоящее время UTC-7.)

Обратите внимание, что формат '%d/%m/%y' создает дату в 2020 году, а не в 2011 году.

person Jonathan Leffler    schedule 26.10.2011