임베디드 리눅스에서 작업 중이며 시스템/컨트롤러 시간은 1/1/1970부터 밀리 초 형태로 유지됩니다. gmtime을 사용하려고하지만 정확한 결과를 얻을 수 없습니다. 이 시간 (밀리 초)을 실시간 시간 : 분 : 초 : 일 : 월로 변환하는 예제가 유용 할 것입니다.gmtime() 함수는 윤년을 고려합니까?
답변
, 그것은 또한 tm_sec
필드의 범위는 [0..60]까지로 정의된다 이유 인 윤초에 대한 gmtime()
지원 윤년 계정 않습니다뿐만 아니라.
'C' 표준에 따르면'gmtime()'은 윤초를 설명하기 위해 _ 필수가 아니지만 허용됩니다. 이 특성은 지정되지 않은 상태로 남습니다. POSIX에 따르면,'time_t'가 1970-01-01T00 : 00 : 00 UTC부터 그 카운트에 _not_를 포함하지 않기 때문에'gmtime()'은 윤년을 고려하지 않습니다. 결과적으로'gmtime()'의 구현이 윤초를 설명하는 경우는 거의 없다. 도약 년, 네. 도약 초, 아니. 당신이'tm_sec'의 범위에 대해서 정확 하긴하지만. 그런 점에서,'struct tm'는 윤초를 나타낼 수 있습니다.'time_t'만이 할 수 없습니다. –
@HowardHinnant'time_t'가 리눅스와 FreeBSD에서의 윤초를 포함하는지 (아마도 다른 것들도) 설정 가능합니다. 윤초를 포함하면,'gmtime()'은'tm_sec' 값'60'을 리턴 할 수 있습니다. http://coliru.stacked-crooked.com/a/622da23fd57dabca를 참조하십시오. – hvd
@hvd :'putenv ("TZ = right/UTC")와 좋은 데모, 고마워. –
Howard Hinnant의 chrono-Compatible Low-Level Date Algorithms에서 파생되고 자세히 설명 된 civil_from_days
을 사용할 수 있습니다. 이 함수는 1970 년 1 월 1 일부터 일수를 취하여 {y, m, d}
필드로 변환합니다. 완료하면 밀리 초 타임 스탬프에서 일 수를 뺀 다음 자정부터 밀리 초를 가져와 h:M:s.ms
으로 분해해야합니다. 그냥 내가 입력 1490285505123ms
으로 사용 된 예로서
#include <iostream>
#include <iomanip>
#include <cstdint>
int
main()
{
using namespace std;
int64_t t = 1490285505123; // milliseconds since epoch
int32_t z = (t >= 0 ? t : t - (1000*86400-1))/(1000*86400); // days since epoch
t -= z * (1000LL * 86400); // milliseconds since midnight
z += 719468;
int32_t era = (z >= 0 ? z : z - 146096)/146097;
int32_t doe = z - era * 146097;
int32_t yoe = (doe - doe/1460 + doe/36524 - doe/146096)/365;
int32_t y = yoe + era * 400;
int32_t doy = doe - (365*yoe + yoe/4 - yoe/100);
int32_t m = (5*doy + 2)/153;
int32_t d = doy - (153*m + 2)/5 + 1; // day
m += m < 10 ? 3 : -9; // month
y += m <= 2; // year
int32_t h = t/(1000 * 3600); // hour
t -= h * (1000 * 3600);
int32_t M = t/(1000 * 60); // minute
t -= M * (1000 * 60);
int32_t s = t/1000; // second
int32_t ms = t - s * 1000; // ms
cout.fill('0');
cout << setw(4) << y << '-' << setw(2) << m << '-' << setw(2) << d
<< ' ' << setw(2) << h << ':' << setw(2) << M
<< ':' << setw(2) << s << '.' << setw(3) << ms << '\n';
}
, 출력은 다음과 같습니다 :
여기에 전체 코드의
는2017-03-23 16:11:45.123
이 계좌로 도약 년이 걸린다. 윤초를 고려하지 않습니다. 임베디드 리눅스 시스템/컨트롤러 중 하나를 사용하는 것은 거의 불가능하므로 그렇게 시도하는 것은 잘못 될 수 있습니다.
-5877641-06-23 00:00:00.000 <= t <= 5880010-09-09 23:59:59.999
(+/- 5,800,000년)
당신이 t
0000-03-01 00:00:00.000
의 하한을 제한 괜찮다면 :
위의 알고리즘은 t
에 대한 유효성의 매우 큰 범위가 당신이 낮은 리터를 제한 할 수있는 경우
int32_t era = z/146097;
: 당신은에 era
의 계산을 단순화 할 수 있습니다
2000-03-01 00:00:00.000 <= t <= 2400-02-29 23:59:59.999
그런 다음 era
간단하게 될 수 있습니다 :이 4백년 범위에 t
을 제한하고자하는 경우, 마지막으로
int32_t z = t/(1000 * 86400); // days since epoch
그리고 : t
1970-01-01 00:00:00.000
의 IMIT는 z
의 계산을 단순화 할 수있다 :
int32_t const era = 5;
FWIW, 여기에 활용 high-level date/time library 인 C++ 1분의 11 4 <chrono>
정확히 똑같은 연산을하는 라이브러리, 더 깨끗한 구문. std :: lib는 <chrono>
을 사용하여이 라이브러리를 사용할 수 있습니다.
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
cout << sys_time<milliseconds>(1490285505123ms) << '\n';
}
확실히해야합니다. 귀하가 얻고 있다고 말하는 부정확 한 결과의 예가 그것들을 생산하는 [mcve]와 함께 도움이 될 것입니다. 실제로 질문에 대한 답변을 얻으려면 필수적입니다. ('tm_mday'는 1 기반이고,'tm_mon'은 0 기반이고,'tm_year'는 1900 기반입니다, 맞습니까?) –