2013-04-11 41 views
32

Làm cách nào để trích xuất năm, tháng, ngày, giờ, phút, giây và mili giây từ đối tượng std::chrono::time_point?Trích xuất năm/tháng/ngày, vv từ std :: chrono :: time_point trong C++

Tôi chỉ thấy các ví dụ về cách trích xuất tổng số tiền, ví dụ: giây từ một số duration.

+0

bản sao có thể có của [Ho w để chuyển đổi std :: chrono :: time \ _point thành chuỗi datetime lịch với số thập phân?] (http://stackoverflow.com/questions/12835577/how-to-convert-stdchronotime-point-to-calendar-datetime- string-with-fraction) – Ali

Trả lời

48

Bạn chỉ có thể trích xuất thông tin này từ system_clock::time_point. Đây là đồng hồ duy nhất do hệ thống cung cấp có mối quan hệ với lịch dân sự. Sau đây là cách để có được những time_point hiện sử dụng đồng hồ này:

system_clock::time_point now = system_clock::now(); 

Sau đó bạn có thể chuyển đổi này vào một time_t với:

time_t tt = system_clock::to_time_t(now); 

Sử dụng thư viện C thì bạn có thể chuyển đổi một time_t đến một tm, nhưng bạn phải chọn xem bạn muốn chuyển đổi đó xảy ra trong múi giờ UTC hay múi giờ địa phương của bạn:

tm utc_tm = *gmtime(&tt); 
tm local_tm = *localtime(&tt); 

Sau đó, bạn c một in ra các thành phần của tm, ví dụ:

std::cout << local_tm.tm_year + 1900 << '\n'; 
std::cout << local_tm.tm_mon + 1 << '\n'; 
std::cout << local_tm.tm_mday << '\n'; 

Ngoài

Nếu bạn muốn, bạn có thể tận dụng lợi thế của thông tin không được bảo đảm này:

Mỗi thi hành system_clock tôi Nhận thức được dựa trên unix time. I E. số giây kể từ năm mới UTC năm 1970, bỏ qua giây nhảy vọt. Và độ chính xác của số này thường là tốt hơn giây. Dưới đây là một chương trình hoàn toàn được chiết xuất tất cả các thông tin này:

#include <chrono> 
#include <ctime> 
#include <iostream> 

int 
main() 
{ 
    using namespace std; 
    using namespace std::chrono; 
    typedef duration<int, ratio_multiply<hours::period, ratio<24> >::type> days; 
    system_clock::time_point now = system_clock::now(); 
    system_clock::duration tp = now.time_since_epoch(); 
    days d = duration_cast<days>(tp); 
    tp -= d; 
    hours h = duration_cast<hours>(tp); 
    tp -= h; 
    minutes m = duration_cast<minutes>(tp); 
    tp -= m; 
    seconds s = duration_cast<seconds>(tp); 
    tp -= s; 
    std::cout << d.count() << "d " << h.count() << ':' 
       << m.count() << ':' << s.count(); 
    std::cout << " " << tp.count() << "[" 
       << system_clock::duration::period::num << '/' 
       << system_clock::duration::period::den << "]\n"; 

    time_t tt = system_clock::to_time_t(now); 
    tm utc_tm = *gmtime(&tt); 
    tm local_tm = *localtime(&tt); 
    std::cout << utc_tm.tm_year + 1900 << '-'; 
    std::cout << utc_tm.tm_mon + 1 << '-'; 
    std::cout << utc_tm.tm_mday << ' '; 
    std::cout << utc_tm.tm_hour << ':'; 
    std::cout << utc_tm.tm_min << ':'; 
    std::cout << utc_tm.tm_sec << '\n'; 
} 

Nó rất thuận tiện để tạo ra một tùy chỉnh duration để mô hình ngày:

typedef duration<int, ratio_multiply<hours::period, ratio<24> >::type> days; 

Bây giờ bạn có thể nhận được thời gian kể từ khi kỷ nguyên, là có độ chính xác cao như có thể quản lý, với:

system_clock::duration tp = now.time_since_epoch(); 

Sau đó cắt ngắn đến ngày và trừ đi.

Sau đó cắt bớt nó thành giờ và trừ đi.

Tiếp tục cho đến khi bạn đã trừ số giây.

Những gì bạn còn lại là phần nhỏ của giây với đơn vị system_clock::duration. Vì vậy, in ra giá trị thời gian chạy và các đơn vị thời gian biên dịch của giá trị đó như được hiển thị.

Đối với tôi chương trình này in ra:

15806d 20:31:14 598155[1/1000000] 
2013-4-11 20:31:14 

đầu ra của tôi chỉ ra system_clock::duration chính xác là micro giây.Nếu muốn, có thể được rút ngắn đến mili giây với:

milliseconds ms = duration_cast<milliseconds>(tp); 

Cập nhật

This header-only C++11/14 library gói gọn công việc trên, giảm công việc của khách hàng xuống:

#include "date.h" 
#include <iostream> 

int 
main() 
{ 
    // Reduce verbosity but let you know what is in what namespace 
    namespace C = std::chrono; 
    namespace D = date; 
    namespace S = std; 

    auto tp = C::system_clock::now(); // tp is a C::system_clock::time_point 
    { 
     // Need to reach into namespace date for this streaming operator 
     using namespace date; 
     S::cout << tp << '\n'; 
    } 
    auto dp = D::floor<D::days>(tp); // dp is a sys_days, which is a 
             // type alias for a C::time_point 
    auto ymd = D::year_month_day{dp}; 
    auto time = D::make_time(C::duration_cast<C::milliseconds>(tp-dp)); 
    S::cout << "year  = " << ymd.year() << '\n'; 
    S::cout << "month  = " << ymd.month() << '\n'; 
    S::cout << "day   = " << ymd.day() << '\n'; 
    S::cout << "hour  = " << time.hours().count() << "h\n"; 
    S::cout << "minute  = " << time.minutes().count() << "min\n"; 
    S::cout << "second  = " << time.seconds().count() << "s\n"; 
    S::cout << "millisecond = " << time.subseconds().count() << "ms\n"; 
} 

nào chỉ ra cho tôi:

2015-07-10 20:10:36.023017 
year  = 2015 
month  = Jul 
day   = 10 
hour  = 20h 
minute  = 10min 
second  = 36s 
millisecond = 23ms 
+0

Vấn đề với 'tm' là nó không có độ chính xác mili giây, là thứ tôi cần. – bytecode77

+0

@Devils Child: Trong trường hợp đó, bạn có thể chuyển đổi time_t kết quả trở lại thành system_clock :: time_point bằng cách sử dụng 'from_time_t'. Và sau đó trừ hai. Bạn sẽ nhận được một khoảng thời gian có chứa các số thập phân, mà bạn có thể thao tác thêm. –

+0

Cảm ơn. Tôi sẽ đi với giải pháp của bạn :) – bytecode77