2013-01-02 1 views
7
#include <stdio.h> 
#include <time.h> 

int main(int argc, char* argv[]) 
{ 
    struct tm stm; 
    stm.tm_sec = 27; 
    stm.tm_min = 5; 
    stm.tm_hour = 18; 
    stm.tm_mday = 2; 
    stm.tm_mon = 0; 
    stm.tm_year = 43; 
    stm.tm_wday = 0; 
    stm.tm_yday = 0; 
    printf("%d\n", mktime(&stm)); 
    getchar(); 
    return 0; 
} 
을 부여

인쇄 -1한다 mktime 반환 -1 때 유효한 구조체 TM

나는 무엇을 오해입니까?

[+ 편집] 이것은 32 비트 대상이있는 Visual Studio 2012를 사용하고 있습니다. 후속 질문은 '임의의 날짜/시간 값 (즉, 1900 년 이전 일 수있는 값)을 저장하는 데 권장되는 방법은 무엇입니까?'라고 추측합니다.

+1

왜 'errno'를 확인하거나'perror'를 사용하여 잘못된 것을 찾으십니까? –

+0

누군가가 해가 유효하지 않은 해답을 삭제했습니다. 1900 년이 아니라 1970 년을 기준으로 한 strptime 버전을 사용하고있었습니다. –

+0

일시적으로 내 대답을 삭제했는데, 뭔가를 확인해야합니다. (처음 옳았습니다.) – benjarobin

답변

13

43 (1943)은 유효하지 않은 것으로 간주됩니다. 그 이유는 mktimetime_t 유형을 반환하기 때문입니다. 이 유형은 실제로 표준화되지 않았습니다. 어떤 문서은 말했다 :

time_t 형식 00:00 시간 경과 초 1970 년 1 월 1 일 UTC를 나타내는 정수 값입니다. 그리고 tm_year 1900

이 링크 이후 년의 수입니다 What is ultimately a time_t typedef to? 말한다 : 1970 년 1 월 1 일 자정 UTC (:

time_t 유닉스 시대의 시작 이후의 초 수를 나타냅니다 윤초를 세지 않음). 일부 시스템에서는 음수 시간 값을 올바르게 처리하지만 다른 시스템에서는 을 수행하면 이 아닌이됩니다. 우리가 time_t가 부호있는 32 비트 정수가 최선의 시나리오에서 당신은 귀하의 경우 ~ 13/12/1901 및 19/1/2038

그러나 사이의 날짜를 만들 수 있음을 고려하는 경우

구현에서는 time_t의 음수 부분을 사용하지 않으므로 1970 년 이전의 날짜는 mktime으로 만들 수 없습니다.

+1

실제로, POSIX는 'time_t'는 서명 된 타입 ([link] (http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to))이므로 , 32 비트 정수로 구현되면 1970 년 이전에 68 년까지 표현할 수 있습니다. –

+0

@Mat 그것은 실제로 구현에 의존합니다. Matteo Italia http://stackoverflow.com 링크를 읽어주십시오./questions/471248/what-is-ultiately-a-time-t-typedef-to. time_t는 Unix 신기원이 시작된 이후의 초 수를 나타내며, 1970 년 1 월 1 일 자정 UTC (윤초가 포함되지 않음)입니다. 일부 시스템에서는 부정적인 시간 값을 올바르게 처리하지만 다른 시스템에서는 **을 사용하지 않습니다. – benjarobin

+0

1970 년 이전 날짜 계산이 구현 된 time_t에 서명 되었기 때문에 이것은 아닙니다. 표준은 이에 대해 아무 것도 말하지 않기 때문에 1970 년 이전의 지원은 추가되지 않을 수도 있습니다. – benjarobin

0

"1943 년 1 월 2 일"날짜를 나타내려고합니다.
Unix/Linux 시스템에서이 날짜는 참조 날짜로 "January 1, 1970"을 사용하기 때문에 time_t 값으로 표시 할 수 없습니다.

업데이트 :
POSIX는 mktime이 "Epoch 이후 초"(Epoch = 01-01-1970 00:00:00)로 시간을 반환하도록 지정합니다. 엄격한 해석에서, 1970 년 1 월 1 일 이전의 날짜는 'seconds since'가 원래 양수이기 때문에 표현할 수 없습니다.

ANSI/ISO C는 mktime의 결과에 대한 음수 값의 가능성에 대해 명확하지 않습니다.

+1

'time_t '에 서명하면 1943이 범위를 벗어납니다. – Mat

2

time_t은 시스템의 64 비트 정수이며 잘못된 형식 플래그 지정자를 사용하여 인쇄합니다. 당신이 64 비트의 것을 나타 내기 위해 ll 수정을 사용할 필요가 : 시간이 시대 이전 (1970 년 1 월 1 일)이기 때문에

time_t t = mktime(&stm); 
printf("%lld", (int64_t)t); // This will be correct if time_t is 32 or 64 bits 

, 시간이 진수의 0xffffffffcd38df27입니다 -851910873 같은 음의 값이며, 64 비트 정수로. 32 비트 정수로 출력하려고하면 0xffffffff 또는 -1 인 상위 32 비트를 얻습니다. (기술적으로 C 표준에 따라 정의되지 않은 동작이기 때문에 이에 의존하지 마십시오).

다른 언급했듯이 실제 크기는 time_t으로 지정되어 있지 않으므로 이에 대해 아무런 가정을해서는 안됩니다. 가장 안전한 방법은 실제로 얼마나 큰지 알아야 할 경우 항상 64 비트로 늘리는 것입니다.