C ++ std :: chrono :: time_point를 long 및 back으로 변환하는 방법 auto epoch =

나는 변환 할 필요 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_mstime_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수를 보유합니다.millisecondssystem_clock .

이:

std::chrono::duration<long> dur(duration);

, 및 정밀도로 duration표현 된을 만듭니다 . 이것은 효과적으로 은 S 에 보류를 에 . 논리 오류입니다. 올바른 코드는 다음과 같습니다.longsecondsreinterpret_castmillisecondsvalueseconds

std::chrono::milliseconds dur(duration);

이 줄 :

std::chrono::time_point<std::chrono::system_clock> dt(dur);

의 기본 정밀도 (일반적으로 밀리 초보다 미세함)에 정밀도를 유지하는 기능을 사용하여을 time_point기반으로를 만듭니다 . 그러나 런타임 값은 정수 밀리 초가 유지됨을 올바르게 반영합니다 (유형에 대한 수정을 가정 ).system_clocksystem_clockdur

수정을해도이 테스트는 (거의 항상) 실패합니다.

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;
}

위의 주요 위험이되고 있지 해석 integral_duration으로 millisecondsA와 방식 뒷면에 time_point. 이러한 위험을 완화하는 한 가지 가능한 방법은 다음과 같이 작성하는 것입니다.

    sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};

이렇게하면 sys_milliseconds나가는 도중과 다시 들어오는 두 곳에서 사용하는 것만으로도 위험을 줄일 수 있습니다 .

그리고 하나 더 예 : 귀하에게 어떤 기간 나타내는 정수로 변환 할하자 말 system_clock지원 (마이크로, 10 마이크로 또는 나노 초)를. 그러면 위와 같이 밀리 초를 지정하는 것에 대해 걱정할 필요가 없습니다. 코드는 다음과 같이 단순화됩니다.

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;
}

이것은 작동하지만 한 플랫폼에서 변환의 절반 (적분으로)을 실행하고 다른 플랫폼에서 나머지 절반 (적분에서 입력)을 실행 system_clock::duration하면 두 변환에 대해 다른 정밀도를 가질 위험 이 있습니다.


답변

또한 시점에서 ms 수를 얻는 방법에는 두 가지가 있습니다. 어느 것이 더 나은지 잘 모르겠습니다. 벤치마킹을했고 둘 다 동일한 성능을 가지고 있으므로 선호도의 문제라고 생각합니다. 아마도 Howard는 다음과 같이 차임 할 수 있습니다.

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();

첫 번째는 왼쪽에서 오른쪽으로가는 내 마음 속에서 더 명확하게 읽습니다.


답변

한 줄로 :

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();

답변

time_point객체 는 다른 time_point또는duration 객체 객체 합니다.

당신은 당신을 변환해야합니다 longA를 duration다음 코드는 제대로 작동합니다, 지정된 단위.