2012-07-15 6 views
2

std::gmtime은 최대 std::time_t을 전달하면 실패합니다.std :: tm 또는 std :: gmtime의 한계는 무엇입니까?

std::cout << "sizeof(std::time_t): " << sizeof(std::time_t) << '\n' 
      << "sizeof(long long): " << sizeof(long long) << '\n' 
      << "sizeof(unsigned int): " << sizeof(unsigned int) << "\n\n"; 

auto testgmtime = [](std::time_t time) 
{ 
    std::tm* ptm = std::gmtime(&time); 
    std::cout << (ptm ? "succeeded\n" : "failed\n"); 
}; 

testgmtime(std::numeric_limits<std::time_t>::max()); 
testgmtime(std::numeric_limits<long long>::max()); 
testgmtime(std::numeric_limits<long long>::max()-1); 
testgmtime(static_cast<std::time_t>(std::numeric_limits<unsigned int>::max())*2); 
testgmtime(std::numeric_limits<int>::max()); 

출력 : 내가 VS2012를 사용하고

sizeof(std::time_t): 8 
sizeof(long long): 8 
sizeof(unsigned int): 4 

failed 
failed 
failed 
succeeded 
succeeded 

다음 테스트를 참조하십시오. 표준 제한이 보이지 않습니까? 아니면이 VS가 엉터리입니까? 어떤 대안을 사용할 수 있습니까? ?

답변

2

VS2012가 엉터리되지 않는 (내 리눅스 설치에 from_time_t는() gmtime보다 천장 이전 칠 나타납니다 있지만). 수학 해. time_t 경우

64 비트 정수가 부호있는 정수라면는 부호없는 정수 2 63 -1 인 경우는 2 64 -1에서 초 후 최대 수이다.

대략 2 63초 2 63/(60 * 60 * 24 * 365) ≈ 2.9 * 10 11 년에 대응한다.

time_ttm_year은 그 최대 값이 31 -1 * 10 9 ≈ 2.1 32 비트 int이다.

분명히 ~ 2.9 * 10 을 32 비트 부호있는 정수로 저장할 수 없습니다. 그리고 물어 보면 gmtime()이 정당하게 실패합니다.

매우 큰 값을 처리하기 위해 gmtime()의 구현을 this answer에서 수정할 수 있습니다. SecondsSinceEpoch + 11644473600ULL에서 오버플로를 해결하고 intsuintsuint64s으로 변경해야합니다.

+0

감사합니다. 매우 높은 숫자를 설명합니다. 그러나''(std :: numeric_limits :: max() - 1)/10000000'도 역시 ~ 29247years의 범위가 될 것이므로 2924 년의 범위를 가지며 결국에는 292 개의 작업 범위를 벗어납니다. 나는 정확히 어디에서 멈출 지 모르지만이 일은 ~ 300 년 ~ 3000 년 사이에 실패합니다. 나는 당신이 제안한 것처럼 내 자신을 써야한다고 생각한다. – David

+0

바이너리 검색을하여 컷 - 오프 날짜/시간을 결정할 수있다. 나는 그것이 무엇인지 알고 싶어합니다. 그것은 논리를 나타낼 수 있습니다. –

+0

~ 300 ~ 3000 년은 33 비트에서 37 비트가 소요됩니다. 나는'time_t'가 64 비트 임에도 불구하고 (기본적으로'time_t' 크기를 선택할 수 있음) 구현이 기본적으로 32 비트인지 궁금합니다. –

1

C++은 gmtime이 실패 할 수 있다고 말합니다. 큰 입력에 gmtime의 동작을 지정하는 기준은 POSIX이고 : 에러가 검출

경우 gmtime() 널 포인터를 반환하고 오류를 나타내는 errno를 설정한다.

가 [EOVERFLOW] 결과가 표시되지 않을 수

ERRORS

gmtime() 및 gmtime_r() 함수 경우 실패한다.

Epoch 이후의 초가 음수이면 실제 시간과의 관계는 undefined입니다.하지만 한계를 직접 말하지는 않습니다.

대안으로 밀어 시도

auto testgmtime = [](std::time_t time) 
{ 
    std::cout << boost::posix_time::from_time_t(time) << '\n'; 
}; 

관련 문제