2012-02-10 6 views
8

У меня есть временная метка эпохи эпохи, представленная как double, что я хотел бы преобразовать в соответствующий std::chrono::time_point. Эпоха - обычная эпоха UNIX с 01.01.1970 года. Я знаю, что существует std::chrono::system_clock::from_time_t, но time_t не имеет дробной части. Каким будет лучший способ сделать это с помощью C++ 11?Как преобразовать временную метку дробной эпохи (double) в std :: chrono :: time_point?

Этот вопрос связан с unix timestamp to boost::posix_time::ptime, за исключением того, что он запрашивает версию C++ 11, а не Boost.

+0

Вы читали над [N2661] (http://www.open-std.org/jtc1/sc22/ wg21/документы/документы/2008/n2661.htm)? – ildjarn

+0

"(...) дробная временная метка эпохи, представленная как« двойная ». Какие единицы? Вы знаете эпоху? –

+0

@ R.MartinhoFernandes: это стандартная эпоха UNIX с 01.01.1970. – mavam

ответ

12

Предполагая, что эпоха такая же, как у известного типа clock, вы можете использовать продолжительность с представлением double и конвертировать в длительность, используемую этими часами.

// change period to appropriate units - I'm assuming seconds 
typedef std::chrono::duration<double, std::ratio<1>> d_seconds; 

d_seconds since_epoch_full(324324.342); 
auto since_epoch = std::chrono::duration_cast<clock::duration>(since_epoch_full); 
clock::time_point point(since_epoch); 

Это должно быть хорошо для любых расчетов с участием, что часы, так как вы используете ту же точность, как часы, но он может потерять некоторые точности преобразования. Если вы не хотите потерять это, вам придется использовать специализацию time_point, которая использует этот тип времени, который используется на основе double. А затем используйте это в своих расчетах (конечно, со всеми оговорками математики с плавающей запятой).

typedef std::chrono::time_point<clock, d_seconds> d_time_point; 

Однако это осложнит любые вычисления, связанные с тем же часом, поскольку для этого потребуются преобразования. Для облегчения этой задачи, вы можете создать свою собственную тактовую обертку, который делает преобразование и использование, что:

template <typename Clock> 
struct my_clock_with_doubles { 
    typedef double rep; 
    typedef std::ratio<1> period; 
    typedef std::chrono::duration<rep, period> duration; 
    typedef std::chrono::time_point<my_clock_with_doubles<Clock>> time_point; 
    static const bool is_steady = Clock::is_steady; 

    static time_point now() noexcept { 
     return time_point(std::chrono::duration_cast<duration>(
        Clock::now().time_since_epoch() 
       )); 
    } 

    static time_t to_time_t(const time_point& t) noexcept { 
     return Clock::to_time_t(typename Clock::time_point(
          std::chrono::duration_cast<typename Clock::duration>(
           t.time_since_epoch() 
          ) 
         )); 
    } 
    static time_point from_time_t(time_t t) noexcept { 
     return time_point(std::chrono::duration_cast<duration>(
        Clock::from_time_t(t).time_since_epoch() 
       )); 
    } 
}; 
+0

Что такое '324324.342'? – Puppy

+0

Спасибо за ответ. Не могли бы вы объяснить, откуда начинается потеря точности? Кроме того, может ли тип часов в 'd_time_point' быть произвольным? – mavam

+0

@Matthias: потеря точности обусловлена ​​тем, что собственный тип продолжительности часов не может представлять точную продолжительность, которую вы используете как «double». В качестве примера, если продолжительность составляет 10,5 секунд, но часы используют интегральную длительность с периодом 1 секунда, при преобразовании она станет 10 или 11 секунд. В идеале, тип часов в 'd_time_point' должен быть одним с той же эпохой. –