콘텐츠로 건너뛰기

std::chrono 라이브러리

chrono 라이브러리는 C++ 표준 템플릿 라이브러리(Standard Template Library, STL) 중에서 시간 관련 기능을 담당하고 있는 라이브러리입니다. 본 글에서 chrono 라이브러리 사용 방법 및 함수에 대해서 알아보겠습니다.

chrono 라이브러리란?

chrono 라이브러리는 c++11에서 처음 도입되었으며 좀 더 다양한 정확도로 시간을 측정할 수 있고 조작할 수 있는 기능을 제공합니다. <chrono> 헤더 파일을 포함해야 하며 std::chrono 네임스페이스를 사용합니다.

주요 컴포넌트

시간 지속 시간(Duration)

지속 시간은 두 시간 지점 사이의 차이를 나타냅니다. std::chrono::duration을 사용하여 다양한 단위로 지속 시간을 표현할 수 있습니다. 예를 들어 std::chrono::secondsstd::chrono::milliseconds 등의 타입을 사용하여 지속 시간을 쉽게 표현할 수 있습니다.

시점(Time Point)

시점은 특정 시간을 표현하는 데 사용합니다. std::chrono::time_point 클래스를 사용하여 시점을 표현할 수 있습니다.

시계(Clock)

시간을 측정하는 데 사용하는 시계를 의미합니다. 대표적인 예로는 시스템 시계(std::chrono::system_clock), 고정된 시간 간격을 가진 시계(std::chrono::steady_clock), 그리고 고해상도 시계(std::chrono::high_resolution_clock)가 있습니다.

달력(Calendar)

std::chrono::year_month_day 등의 클래스를 사용하여 날짜를 구성할 수 있습니다.

chrono 사용 예제

현재 시간 얻기

std::chrono::system_clock을 사용하여 현재 시스템 시간을 얻는 간단한 예제입니다.

#include <chrono>
#include <format>
#include <iostream>
#include <string>

int main()
{
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    
    // C++20
    std::string s = std::format("{:%F %T}", now);
    std::cout << s << '\n';

    return 0;
}
2024-03-03 04:39:29.932223

경과 시간 계산

std::chrono::duration을 사용하여 실행 시간을 계산해보겠습니다.

#include <chrono>
#include <iostream>

int main()
{
    std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now();

    int sum = 0;
    for (int i = 0; i < 999999999; i++)
        sum += i;

    std::chrono::system_clock::time_point end_time = std::chrono::system_clock::now();

    std::chrono::microseconds duration = 
      std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);

    std::cout << duration.count() << " ms\n";

    return 0;
}
877522 ms

template를 사용하여 다음과 같이 함수 실행 시간을 계산할 수 있습니다.

#include <chrono>
#include <iostream>

template<typename Func, typename... Params>
std::chrono::microseconds MeasureTime(Func func, Params&&... params)
{
    std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now();

    func(std::forward<Params>(params)...);

    std::chrono::system_clock::time_point end_time = std::chrono::system_clock::now();

    std::chrono::microseconds duration = 
      std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);

    return duration;
}

void MyFunc()
{
    int sum = 0;
    for (int i = 0; i < 999999999; i++)
        sum += i;
}

int main()
{
    auto duration = MeasureTime(MyFunc);

    std::cout << duration.count() << " ms\n";

    return 0;
}
911098 ms

시간 지연(Duration Delay)

std::this_thread::sleep_for 함수와 함께 chrono 라이브러리를 사용하여 특정 시간 동안 실행을 지연시키는 예제입니다. 1초 간격으로 화면에 숫자를 표시합니다.

#include <iostream>
#include <chrono>
#include <thread>

int main() 
{
    for (int i = 0; i < 10; i++)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << i << " ";
    }
    
    return 0;
}
0 1 2 3 4 5 6 7 8 9

TimeZone

now()는 기본적으로 UTC 시간대를 사용합니다. zoned_time를 사용하면 특정 지역의 시간대로 변환할 수 있습니다.

#include <chrono>
#include <iostream>

int main() {
    auto now { std::chrono::system_clock::now() };
    std::cout << "GMT+0 : " << std::format("{:%F %T}", now) << std::endl;

    std::chrono::zoned_time newyork{ "America/New_York", now };
    std::cout << "GMT-4 : " << std::format("{:%F %T}", newyork) << std::endl;

    std::chrono::zoned_time seoul{ "Asia/Seoul", now };
    std::cout << "GMT+9 : " << std::format("{:%F %T}", seoul) << std::endl;

    return 0;
}
GMT+0 : 2024-04-03 07:37:53.3239012
GMT-4 : 2024-04-03 03:37:53.3239012
GMT+9 : 2024-04-03 16:37:53.3239012

Literals

#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono;

    // Literals
    auto year = 10y;
    auto day = 10d;
    auto hours = 10h;
    auto minutes = 10min;
    auto seconds = 10s;
    auto milliseconds = 10ms;
    auto microseconds = 10us;
    auto nanoseconds = 10ns;
   
    return 0;
}

Calendar

#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono;

    // 요일은 미리 정의되어 있습니다.
    static_assert(std::chrono::Sunday == std::chrono::weekday(0)); 
    static_assert(std::chrono::Saturday == std::chrono::weekday(6));

    // 월은 미리 정의되었습니다.
    static_assert(std::chrono::January == std::chrono::month(1));
    static_assert(std::chrono::December == std::chrono::month(12));

    // 오늘 날짜
    time_point now{ system_clock::now() };
    year_month_day date{ floor<std::chrono::days>(now) };       // 2024 April 3rd

    // 2024년 04월 03일
    year_month_day var1{ year{2024}, month{4}, day{3} };        // 2024 April 3rd
    year_month_day var2{ year{2024}, April, day{3} };           // 2024 April 3rd
    year_month_day var3{ day{3} / month{4} / year{2024} };      // 2024 April 3rd
    year_month_day var4{ 2024y, April, 3d };                    // 2024 April 3rd

    // 2024년 04월 말일
    year_month_day var5{ 2024y / April / last };               // 2024 April 30th

    // 2024년 04월 마지막 일요일
    year_month_weekday_last var6{ 2024y, April, Sunday[last] }; // Last Sunday of April, 2024
    year_month_day var7{ var6 };                                // 2024 April 28th

    // 2024년 04월 2째주 일요일
    weekday_indexed week{ Sunday, 2 };
    year_month_weekday var8{ 2024y, April, week };              // 2nd Sunday of April, 2024
    year_month_day var9{ var8 };                                // 2024 April 14th

    // datediff
    year_month_day start_date{ 2024y, April, 3d };
    year_month_day end_date{ 2024y, April, 28d };

    // 25d
    std::chrono::days duration_days{ std::chrono::sys_days(end_date) - std::chrono::sys_days(start_date) };

    // 25 * 24 = 600h
    std::chrono::hours duration_hours{ std::chrono::sys_days(end_date) - std::chrono::sys_days(start_date) };

    return 0;
}

참고 자료

보다 자세한 내용은 cppreference 사이트에서 확인할 수 있습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다