2014-02-27 1 views
10

이것은 내가 C++ 11에서하고 싶습니다 : 타이밍 클래스와 같은 두 시간 지점을 std::chrono::steady_clock::now()으로 지정하면 시간 차이를 우아하게 인쇄 할 수 있습니다 (예 :C++ 11의 우아한 시간 프린트

).
1 day 4 hours 3 minutes 45 seconds 

또는

32 minutes 54 seconds 345 milliseconds 

나는 시간의 가장 중요한 단위부터 인쇄 할 때부터이 단순히 put_time를 사용에 관심이 아니에요 있습니다. 알아요, 그냥 차이를 인쇄하는 솔루션이지만, 그것은 예쁘지 않아요 : 우아한 솔루션을 찾고 있어요 :)

건배!

+0

지금 어떤 해결책이 있습니까? – RedX

+0

@simple이 작성한 것처럼 일, 시간, ... 등의 후속 나누기를 기반으로 사용자 지정 'put_time'서식을 사용합니다. 하지만 뭔가 더 예뻐 보이기를 바라고 있어요! :) – senseiwa

+0

@senseiwa 나는 그것을 얻지 않는다. * "나는 가장 중요한 시간 단위에서 시작하여 인쇄하기 때문에 put_time을 사용하는 것에 관심이 없다."* 왜 가장 중요한 시간 단위에서 시작하기 위해'put_time '을 사용할 수 없습니까? 나는 한 가지 요점을 놓치고있다. – Ali

답변

3
template<typename T> 
void print_time_diff(std::ostream& out, T prior, T latter) 
{ 
    namespace sc = std::chrono; 
    auto diff = sc::duration_cast<sc::milliseconds>(latter - prior).count(); 
    auto const msecs = diff % 1000; 
    diff /= 1000; 
    auto const secs = diff % 60; 
    diff /= 60; 
    auto const mins = diff % 60; 
    diff /= 60; 
    auto const hours = diff % 24; 
    diff /= 24; 
    auto const days = diff; 

    bool printed_earlier = false; 
    if (days >= 1) { 
     printed_earlier = true; 
     out << days << (1 != days ? " days" : " day") << ' '; 
    } 
    if (printed_earlier || hours >= 1) { 
     printed_earlier = true; 
     out << hours << (1 != hours ? " hours" : " hour") << ' '; 
    } 
    if (printed_earlier || mins >= 1) { 
     printed_earlier = true; 
     out << mins << (1 != mins ? " minutes" : " minute") << ' '; 
    } 
    if (printed_earlier || secs >= 1) { 
     printed_earlier = true; 
     out << secs << (1 != secs ? " seconds" : " second") << ' '; 
    } 
    if (printed_earlier || msecs >= 1) { 
     printed_earlier = true; 
     out << msecs << (1 != msecs ? " milliseconds" : " millisecond"); 
    } 
} 

http://ideone.com/bBNHQp

+0

고마워요, 지금 제가 사용하고있는 솔루션과 매우 흡사합니다. 나는 부서를 표현하는 더 일치하는 방법이 있는지 궁금 해서요. 예를 들어, 인쇄 파일 크기는'log10'을 사용하고 최대 측정 단위를 찾는 것으로 꽤 일치합니다. 이걸 시간에 맞게 바꾸는 영리한 방법이 있는지 나는 모른다. – senseiwa

3

기간은 연산을 수행 할 수 있습니다.

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

int main(){ 
    using namespace std::chrono; 
    using day_t = duration<long, std::ratio<3600 * 24>>; 
    auto start = system_clock::now(); 
    std::this_thread::sleep_for(seconds(1)); 
    auto end = system_clock::now(); 
    auto dur = end - start; 
    auto d = duration_cast<day_t>(dur); 
    auto h = duration_cast<hours>(dur -= d); 
    auto m = duration_cast<minutes>(dur -= h); 
    auto s = duration_cast<seconds>(dur -= m); 
    auto ms = duration_cast<seconds>(dur -= s); 
    std::cout << d.count() << " days, " 
     << h.count() << " hours, " 
     << m.count() << " minutes, " 
     << s.count() << " seconds, " 
     << ms.count() << " milliseconds\n"; 

    return 0; 
} 

출력 :

enter image description here

가능한 중복 : Extract year/month/day etc. from std::chrono::time_point in C++

3

여기에 가변 인자 템플릿과 재귀를 사용하여 쉽게 확장 솔루션입니다. 사용의 편의를 위해 ostream& operator<<(ostream&, const duration&)을 정의합니다.

#include <chrono> 
#include <iostream> 
#include <tuple> 

using day_t = std::chrono::duration<long long, std::ratio<3600 * 24>>; 

template<typename> struct duration_traits {}; 

#define DURATION_TRAITS(Duration, Singular, Plural) \ 
template<> struct duration_traits<Duration> { \ 
    constexpr static const char* singular = Singular; \ 
    constexpr static const char* plural = Plural; \ 
} 

DURATION_TRAITS(std::chrono::milliseconds, "millisecond", "milliseconds"); 
DURATION_TRAITS(std::chrono::seconds, "second", "seconds"); 
DURATION_TRAITS(std::chrono::minutes, "minute", "minutes"); 
DURATION_TRAITS(std::chrono::hours, "hour", "hours"); 
DURATION_TRAITS(day_t, "day", "days"); 

using divisions = std::tuple<std::chrono::milliseconds, 
          std::chrono::seconds, 
          std::chrono::minutes, 
          std::chrono::hours, 
          day_t>; 

namespace detail { 
template<typename...> struct print_duration_impl_ {}; 

template<typename Head, typename... Tail> 
struct print_duration_impl_<Head, Tail...> { 
    template <typename Duration> 
    static bool print(std::ostream& os, Duration& dur) { 
     const auto started_printing = print_duration_impl_<Tail...>::print(os, dur); 

     const auto n = std::chrono::duration_cast<Head>(dur); 
     const auto count = n.count(); 

     if (count == 0) { 
      return started_printing; 
     } 

     if (started_printing) { 
      os << ' '; 
     } 

     using traits = duration_traits<Head>; 
     os << count << ' ' << (count == 1 ? traits::singular : traits::plural); 
     dur -= n; 

     return true; 
    } 
}; 

template<> 
struct print_duration_impl_<> { 
    template <typename Duration> 
    static bool print(std::ostream& os, Duration& dur) { 
     return false; 
    } 
}; 

template<typename...> struct print_duration {}; 

template<typename... Args> 
struct print_duration<std::tuple<Args...>> { 
    template<typename Duration> 
    static void print(std::ostream& os, Duration dur) { 
     print_duration_impl_<Args...>::print(os, dur); 
    } 
}; 
} 

template<typename Rep, typename Period> 
std::ostream& operator<<(std::ostream& os, const std::chrono::duration<Rep, Period>& dur) { 
    detail::print_duration<divisions>::print(os, dur); 
    return os; 
} 

새로운 기간은 duration_traits을 전문으로하고 부문에서 올바른 위치에있는 유형을 삽입하여 추가됩니다. 예를 들어, 10 밀리미터짜리 타입을 추가하는 것은 다음을 포함합니다 :

using jiffy_t = std::chrono::duration<long long, std::centi>; 
DURATION_TRAITS(jiffy_t, "jiffy", "jiffies"); 

using divisions = std::tuple<std::chrono::milliseconds, 
          jiffy_t, 
          std::chrono::seconds, 
          std::chrono::minutes, 
          std::chrono::hours, 
          day_t>; 

3 줄의 코드는 나쁘지 않습니다!

라이브 예제는 ideone.com입니다.

+1

남자, 이것은 매우 흥미 롭다! – senseiwa