C ++ std :: chrono :: time_point를 long 및 back으로 변환하는 방법
나는 변환 할 필요 std::chrono::time_point
로하고,에서 long
유형 (정수 64 비트). 나는 일을 시작하고 있습니다 std::chrono
...
내 코드는 다음과 같습니다.
int main ()
{
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
auto epoch = now.time_since_epoch();
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
long duration = value.count();
std::chrono::duration<long> dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
이 코드는 컴파일되지만 성공하지는 않습니다.
마지막 dt
과 다른 이유는 무엇 now
입니까?
그 코드에 무엇이 빠졌습니까?
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
다음을위한 좋은 장소입니다 auto
.
auto now = std::chrono::system_clock::now();
millisecond
정확한 트래픽을 원하기 때문에 다음에서 은밀하게 진행하는 것이 좋습니다 time_point
.
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
now_ms
A는 time_point
, 기반 system_clock
,하지만의 정밀도 milliseconds
대신 무엇이든 정밀도 system_clock
있다.
auto epoch = now_ms.time_since_epoch();
epoch
이제 유형이 std::chrono::milliseconds
있습니다. 그리고 다음 문장은 본질적으로 no-op이됩니다 (간단히 복사하고 변환하지 않음).
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
여기:
long duration = value.count();
귀하와 내 코드 모두 에서 에포크 이후의 duration
수를 보유합니다 .milliseconds
system_clock
이:
std::chrono::duration<long> dur(duration);
, 및 정밀도로 duration
표현 된을 만듭니다 . 이것은 효과적으로 은 S 에 보류를 에 . 논리 오류입니다. 올바른 코드는 다음과 같습니다.long
seconds
reinterpret_cast
milliseconds
value
seconds
std::chrono::milliseconds dur(duration);
이 줄 :
std::chrono::time_point<std::chrono::system_clock> dt(dur);
의 기본 정밀도 (일반적으로 밀리 초보다 미세함)에 정밀도를 유지하는 기능으로를 time_point
기반으로를 만듭니다 . 그러나 런타임 값은 정수 밀리 초가 유지됨을 올바르게 반영합니다 (유형에 대한 수정을 가정 ).system_clock
system_clock
dur
수정을해도이 테스트는 (거의 항상) 실패합니다.
if (dt != now)
때문에이 dt
의 정수를 보유하고 milliseconds
있지만, now
(A)보다 틱 미세한의 정수 보유 millisecond
(예 : microseconds
또는 nanoseconds
). 따라서 system_clock::now()
정수 를 반환 한 드문 경우에만 milliseconds
테스트가 통과됩니다.
그러나 대신 다음을 수행 할 수 있습니다.
if (dt != now_ms)
이제 예상 한 결과를 안정적으로 얻을 수 있습니다.
함께 모아서:
int main ()
{
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
std::chrono::milliseconds dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
개인적으로 나는 모든 std::chrono
지나치게 장황한 것을 발견 하므로 다음과 같이 코딩합니다.
int main ()
{
using namespace std::chrono;
auto now = system_clock::now();
auto now_ms = time_point_cast<milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
milliseconds dur(duration);
time_point<system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
안정적으로 출력됩니다.
Success.
마지막으로 임시 time_point
유형을 제거하여 및 정수 유형 간에 변환되는 코드 를 최소화하는 것이 좋습니다 . 이러한 변환은 위험하므로 베어 정수 유형을 조작하는 코드를 적게 작성할수록 좋습니다.
int main ()
{
using namespace std::chrono;
// Get current time with precision of milliseconds
auto now = time_point_cast<milliseconds>(system_clock::now());
// sys_milliseconds is type time_point<system_clock, milliseconds>
using sys_milliseconds = decltype(now);
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
sys_milliseconds dt{milliseconds{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
The main danger above is not interpreting integral_duration
as milliseconds
on the way back to a time_point
. One possible way to mitigate that risk is to write:
sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};
This reduces risk down to just making sure you use sys_milliseconds
on the way out, and in the two places on the way back in.
And one more example: Let's say you want to convert to and from an integral which represents whatever duration system_clock
supports (microseconds, 10th of microseconds or nanoseconds). Then you don't have to worry about specifying milliseconds as above. The code simplifies to:
int main ()
{
using namespace std::chrono;
// Get current time with native precision
auto now = system_clock::now();
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
system_clock::time_point dt{system_clock::duration{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
This works, but if you run half the conversion (out to integral) on one platform and the other half (in from integral) on another platform, you run the risk that system_clock::duration
will have different precisions for the two conversions.
I would also note there are two ways to get the number of ms in the time point. I'm not sure which one is better, I've benchmarked them and they both have the same performance, so I guess it's a matter of preference. Perhaps Howard could chime in:
auto now = system_clock::now();
//Cast the time point to ms, then get its duration, then get the duration's count.
auto ms = time_point_cast<milliseconds>(now).time_since_epoch().count();
//Get the time point's duration, then cast to ms, then get its count.
auto ms = duration_cast<milliseconds>(tpBid.time_since_epoch()).count();
The first one reads more clearly in my mind going from left to right.
time_point
objects only support arithmetic with other time_point
or duration
objects.
You'll need to convert your long
to a duration
of specified units, then your code should work correctly.
as a single line:
long value_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch()).count();
'IT박스' 카테고리의 다른 글
jquery 확장 대 각도 확장 (0) | 2020.11.27 |
---|---|
HTTPS 백엔드 서버와 통신하도록 Apache 서버를 구성하는 방법은 무엇입니까? (0) | 2020.11.27 |
사용자 10102와 현재 프로세스 모두 android.permission.READ_PHONE_STATE가 없습니다. (0) | 2020.11.27 |
Error : com.android.builder.dexing.DexArchiveBuilderException : guava-21.0.jar Android 3.1 개발자 채널 처리 실패 (0) | 2020.11.27 |
Oracle 10g 데이터베이스 스키마에서 연결된 사용자 삭제 (0) | 2020.11.27 |