반응형

Modern C++ 날짜 date 시간 time

  • C++20에서는 날짜와 시간을 다루는 방법이 크게 개선되었으며, 이를 처리하기 위해 std::chrono 라이브러리를 사용할 수 있습니다.
  • 이 글에서는 std::chrono를 이용해 날짜와 시간(년, 월, 일, 시, 분, 초) 그리고 시간대를 처리하는 방법을 설명하고, 이를 활용한 예제를 제공합니다.


1. C++11 날짜와 시간 처리하기

  • 기본적으로 C++11에서 날짜와 시간을 다루기 위해서는 std::chrono를 사용하여 시간 단위를 표현할 수 있습니다.

  • std::chrono::system_clock은 시스템의 현재 시간을 제공하는데, 이를 통해 초, 분, 시, 날짜 등 다양한 단위로 시간을 계산할 수 있습니다.

  • cpp

      #include <iostream>
      #include <chrono>
      #include <format>
      #include <ctime>      
      
      int main() {
          using namespace std::chrono; // C++11 
      
          // 현재 시간 얻기
          auto now = system_clock::now();
          
          // 날짜와 시간 출력
          std::time_t now_c = system_clock::to_time_t(now);
          std::cout << "현재 시간: " << std::ctime(&now_c);
          
          // 지역 시간(Local Time), 한국(Korea)일 경우 KST
          std::tm* local_tm = std::localtime(&now_c);
          // C++11에서는 날짜와 시간 전용 구조체(Date, Time)는 없고, std::tm 하나로 모두 처리합니다.
          std::cout << "[지역 시간]\n";
          std::cout << "년: " << 1900 + local_tm->tm_year << '\n';
          std::cout << "월: " << 1 + local_tm->tm_mon << '\n';
          std::cout << "일: " << local_tm->tm_mday << '\n';
          std::cout << "시: " << local_tm->tm_hour << '\n';
          std::cout << "분: " << local_tm->tm_min << '\n';
          std::cout << "초: " << local_tm->tm_sec << "\n\n";
      
          // UTC 시간. UTC와 GMT는 시간 오프셋(+00:00)이 동일하다. KST는 UTC보다 9시간 크다(+09:00).
          std::tm* utc_tm = std::gmtime(&now_c);
          std::cout << "[UTC 시간]\n";
          std::cout << "년: " << 1900 + utc_tm->tm_year << '\n';
          std::cout << "월: " << 1 + utc_tm->tm_mon << '\n';
          std::cout << "일: " << utc_tm->tm_mday << '\n';
          std::cout << "시: " << utc_tm->tm_hour << '\n';
          std::cout << "분: " << utc_tm->tm_min << '\n';
          std::cout << "초: " << utc_tm->tm_sec << '\n';
      
          return 0;
      }
    
  • 위 코드는 시스템 시계로부터 현재 시간을 얻어와 출력하는 간단한 예입니다.

  • system_clock::now()는 현재 시간을 std::time_t로 변환하여 std::ctime()으로 출력할 수 있습니다.



2. C++20 시간대(Time Zone) 처리하기

  • C++20부터는 시간대를 처리하기 위한 std::chrono::zoned_time이 도입되었습니다.
  • 이 기능을 사용하면 다양한 지역의 시간대를 쉽게 다룰 수 있습니다.
  • 예를 들어, 현재 시간을 UTC 및 서울 시간으로 출력하는 방법은 다음과 같습니다.
  • cpp

    #include <iostream>
    #include <chrono>
    #include <format>
    #include <string>
    
    int main() {
        using namespace std::chrono;
        
        // UTC 시간 가져오기
        auto now = system_clock::now();
        
        // 시간대를 적용하여 UTC 시간 출력
        zoned_time zt{"UTC", now};
        std::cout << "UTC 시간: " << format("{:%Y-%m-%d %H:%M:%S %Z}", zt) << std::endl;
    
        // 다른 시간대(예: 한국 시간대) 적용
        zoned_time zt_korea{"Asia/Seoul", now};
        std::cout << "서울 시간: " << format("{:%Y-%m-%d %H:%M:%S %Z}", zt_korea) << std::endl;
        
        return 0;
    }
    

  • 위 코드는 zoned_time을 사용하여 UTC 시간과 서울 시간(Asia/Seoul)을 출력합니다.
  • zoned_timeIANA 시간대 데이터베이스의 문자열을 통해 다양한 시간대를 적용할 수 있습니다.
  • 이를 통해 글로벌 애플리케이션에서 시간대 문제를 쉽게 해결할 수 있습니다.


3. C++20 년, 월, 일, 시, 분, 초 처리하기

  • 날짜와 시간을 보다 구체적으로 다루기 위해, C++20std::chronoyear_month_dayduration_cast와 같은 기능을 제공합니다.

  • 이를 이용하여 년/월/일/시/분/초를 각각 추출할 수 있습니다. 다음 예제는 이를 실제로 사용하는 방법을 보여줍니다.

  • cpp

    #include <iostream>
    #include <chrono>
    #include <format>
    
    int main() {
        using namespace std::chrono;
        using namespace std;
    
        // 현재 시간 얻기
        auto now = system_clock::now();
    
        // 연/월/일/시/분/초 구하기
        auto time = floor<seconds>(now);  // 초 단위로 현재 시간을 자름
        auto dp = floor<days>(now);       // 날짜(일) 단위로 자름
        year_month_day ymd = year_month_day{dp}; // 년/월/일 구성
    
        // 시간대에서 시/분/초 추출
        auto time_since_midnight = time - dp;  // 자정 이후의 시간(시/분/초)
        auto hours = duration_cast<std::chrono::hours>(time_since_midnight);
        auto minutes = duration_cast<std::chrono::minutes>(time_since_midnight - hours);
        auto seconds = duration_cast<std::chrono::seconds>(time_since_midnight - hours - minutes);
    
        // 결과 출력
        cout << "현재 날짜와 시간: " 
             << static_cast<int>(ymd.year()) << "년 "
             << static_cast<unsigned>(ymd.month()) << "월 "
             << static_cast<unsigned>(ymd.day()) << "일 "
             << hours.count() << "시 "
             << minutes.count() << "분 "
             << seconds.count() << "초" << endl;
    
        return 0;
    }
    
  • 이 코드는 현재 시간을 초 단위로 자르고, 이를 통해 year_month_day 구조체로 년/월/일을 추출합니다.

  • 또한 duration_cast를 사용해 자정 이후 경과된 시간에서 시, 분, 초를 각각 계산하고 출력합니다.

  • 이를 통해 C++에서 시간과 날짜를 매우 세밀하게 다룰 수 있습니다.



4. C++11 HowardHinnant/date 라이브러리 사용하기

4.1. 준비 사항

  • (1) date.h 라이브러리를 GitHub에서 클론:
    • sh
       git clone https://github.com/HowardHinnant/date
      
  • (2) date/include 경로를 프로젝트에 포함(#include)시키세요.
  • (3) tz.cpp를 빌드할 때 함께 링크해야 합니다.

4.2. 예제 코드 (C++11)

  • cpp

      #include <iostream>
      #include <chrono>
      
      #include "date/date.h"
      #include "date/tz.h"  // 시간대 관련 기능 제공
      
      int main() {
          using namespace date;
          using namespace std::chrono;
      
          // 현재 UTC 시간 가져오기
          auto now = system_clock::now();
          auto utc_time = floor<seconds>(now);
      
          // UTC 출력
          std::cout << "UTC 시간: " 
                    << format("%F %T UTC", utc_time) << std::endl;
      
          // 서울 시간대 적용 및 출력
          auto korea_tz = date::locate_zone("Asia/Seoul");
          auto korea_time = make_zoned(korea_tz, now);
      
          std::cout << "서울 시간: " 
                    << format("%F %T %Z", korea_time) << std::endl;
      
          return 0;
      }
    

4.3. 빌드 예시

  • bash (gcc)

      g++ -std=c++11 -I./date/include -o datetime_example datetime_example.cpp date/src/tz.cpp -lpthread
    
  • cmake 파일 등을 빌드할 때 사용하시는 것이 더 편합니다.


4.4. 특징

  • format() 함수는 date.h에서 제공하며, strftime과 유사하지만 훨씬 유연합니다.
  • make_zoned() 함수를 통해 원하는 시간대를 적용할 수 있습니다.
  • tz.cppIANA TimeZone DB를 읽어야 하므로 처음 실행 시 자동으로 데이터베이스를 다운로드할 수도 있습니다.
4.4.1. Howard Hinnant/date IANA TimeZone DB 오프라인 사용
  • date 라이브러리에서는 TZDIR 환경 변수 또는 date::set_install 함수로 타임존 DB 경로를 지정할 수 있습니다.
4.4.1.1. IANA TimeZone Database 다운로드
  • IANA 공식 사이트에서 최신 버전을 다운로드할 수 있습니다:
  • 보통 tzdata20xxa.tar.gz 같은 파일 형태입니다.
  • 최신 버전 중 하나를 다운로드한 후 압축을 풀면 africa, asia, northamerica 등 파일이 나옵니다.
4.4.1.2. 경로 지정 방법
  • cpp

      #include "date/tz.h"
      
      int main() {
          // 오프라인 경로로 타임존 DB 경로 지정
          date::set_install("/path/to/your/iana_timezone_database");
          // 이후 locate_zone(), make_zoned() 등을 정상적으로 사용할 수 있습니다.
      }
    
  • 경로에는 tzdata.zi, leapseconds, version, 그리고 지역별 데이터 파일이 포함되어야 합니다.

  • date 라이브러리의 tz.cpp는 내부적으로 해당 디렉토리에서 데이터를 읽습니다.


4.5. C++11 -> C++20 이식 예제

  • C++11에서 HowardHinnant/date를 사용하다가 C++20으로 이식하는 경우의 예제 코드 입니다.
4.5.1. C++11 (Howard Hinnant date 라이브러리)
  • cpp

      #include <iostream>
      #include <chrono>
      #include "date/date.h"
      #include "date/tz.h"  // 시간대 기능 포함
      
      int main() {
          using namespace date;
          using namespace std::chrono;
      
          // 현재 UTC 시간 가져오기
          auto now = system_clock::now();
          auto utc_time = floor<seconds>(now);
      
          // UTC 시간 출력
          std::cout << "UTC 시간: "
                    << format("%F %T UTC", utc_time) << std::endl;
      
          // 서울 시간대 가져오기 및 출력
          auto korea_tz = locate_zone("Asia/Seoul");
          auto korea_time = make_zoned(korea_tz, now);
      
          std::cout << "서울 시간: "
                    << format("%F %T %Z", korea_time) << std::endl;
      
          return 0;
      }
    
4.5.2. C++20 표준 chrono 이식 버전
  • cpp

    #include <iostream>
    #include <chrono>
    #include <format>
    
    int main() {
        using namespace std::chrono;
    
        // 현재 UTC 시간 가져오기
        auto now = system_clock::now();
        auto utc_time = floor<seconds>(now);
    
        // UTC 시간 출력
        std::cout << "UTC 시간: "
                  << std::format("{:%F %T UTC}", utc_time) << std::endl;
    
        // 서울 시간대 가져오기 및 출력
        auto korea_tz = locate_zone("Asia/Seoul");
        zoned_time korea_time{korea_tz, now};
    
        std::cout << "서울 시간: "
                  << std::format("{:%F %T %Z}", korea_time) << std::endl;
    
        return 0;
    }
    
4.5.3. 차이점 정리
  • 항목 C++11
    (HowardHinnant/date 라이브러리)
    C++20 (표준)
    네임스페이스 date:: std::chrono::
    시간대 객체 생성 auto tz = date::locate_zone() auto tz = std::chrono::locate_zone()
    시간대 적용 make_zoned(zone, time_point) zoned_time(zone, time_point) 생성자 사용
    시간 포맷 출력 date::format("%F %T %Z", zoned_time) std::format("{:%F %T %Z}", zoned_time)
    tz.cpp 빌드 필요 여부 필요 (직접 포함 후 빌드) 필요 없음 (표준 라이브러리에 내장)





  • 도움이 되셨으면 하단의 ❤️ 공감 버튼 부탁 드립니다. 감사합니다! 😄
  • 일부 모바일 환경에서는 ❤️ 버튼이 보이지 않습니다.

728x90
반응형

+ Recent posts