2013-10-15 18 views
5

Tôi có hệ thống Linux 32 bit, trong đó tôi phải ghi lại dữ liệu được đặt dấu thời gian với khoảng bù thứ hai UINT32 từ kỷ nguyên 1901-01- 01 00:00:00.Tạo tăng :: posix_time :: đối tượng ptime từ số nguyên 64 bit số thứ hai

Tính dấu thời gian là ok cho tôi như tôi có thể sử dụng quầy và ticks_per_second() chức năng 64 bit ticks() để tạo ra giây kể từ kỷ nguyên như sau (tôi chỉ đòi hỏi độ phân giải mức độ thứ hai)

const ptime ptime_origin(time_from_string("1901-01-01 00:00:00")); 
time_duration my_utc = microsec_clock::universal_time() - ptime_origin; 
boost::int64_t tick_per_sec = my_utc.ticks_per_second(); 
boost::int64_t tick_count = my_utc.ticks(); 
boost::int64_t sec_since_epoch = tick_count/tick_per_sec; 

tác phẩm này đối với tôi vì tôi biết đó là một số nguyên không dấu, số giây sẽ không vượt quá giá trị UINT32 tối đa (cũng không phải trong nhiều năm).

Vấn đề tôi gặp phải là ứng dụng của tôi có thể nhận được một tin nhắn modbus chứa giá trị UINT32 mà tôi phải đặt đồng hồ phần cứng và hệ thống bằng một cuộc gọi ioctl sử dụng RTC_SET_TIME. UINT32 này là một lần nữa bù đắp trong vài giây kể từ kỷ nguyên của tôi 1901-01-01 00:00:00.

Vấn đề của tôi bây giờ là tôi không có cách nào để tạo một ptime đối tượng sử dụng số nguyên 64 bit - các ticks phần của time_duration đối tượng là cá nhân và tôi đang hạn chế việc sử dụng long đó trên hệ thống 32-bit của tôi chỉ là một là Số nguyên được ký 4 byte không đủ lớn để lưu trữ số giây bù đắp từ kỷ nguyên của tôi.

Tôi không kiểm soát được giá trị của thời đại và vì vậy tôi thực sự bối rối về cách tôi có thể tạo đối tượng boost::posix_time::ptime yêu cầu của mình từ dữ liệu tôi có. Tôi có thể có được một giải pháp dơ bẩn bằng cách tính toán số giây thứ hai với khoảng thời gian cụ thể và sử dụng một kỷ nguyên bổ sung để tạo cầu nối để cho phép điều này, nhưng tôi tự hỏi liệu có điều gì đó trong mã boost cho phép tôi giải quyết vấn đề hoàn toàn không bằng cách sử dụng thư viện tăng giờ. Tôi đã đọc tất cả tài liệu tôi có thể tìm thấy nhưng tôi không thể thấy bất kỳ cách rõ ràng nào để thực hiện việc này.

EDIT: Tôi thấy câu hỏi có liên quan này Convert int64_t to time_duration nhưng câu trả lời chấp nhận có không làm việc cho thời đại của tôi

Trả lời

2

Bạn có thể áp dụng time_durations trong gia số tối đa cho phép (đó là std::numeric_limits<long>::max()) kể từ khi lĩnh vực total_seconds được giới hạn trong long (đã ký).

Lưu ý: Tôi đã gọi nó là int32_t bên dưới để nó vẫn hoạt động chính xác nếu được biên dịch trên nền tảng 64 bit.

Dưới đây là một cuộc biểu tình nhỏ:

#include "boost/date_time.hpp" 
#include <iostream> 

using namespace boost::gregorian; 
using namespace boost::posix_time; 

int main() 
{ 
    uint64_t offset = 113ul*365ul*24ul*60ul*60ul; // 113 years give or take some leap seconds/days etc.? 

    static const ptime time_t_epoch(date(1901,1,1)); 
    static const uint32_t max_long = std::numeric_limits<int32_t>::max(); 
    std::cout << "epoch: " << time_t_epoch << "\n"; 

    ptime accum = time_t_epoch; 
    while (offset > max_long) 
    { 
     accum += seconds(max_long); 
     offset -= max_long; 
     std::cout << "accumulating: " << accum << "\n"; 
    } 

    accum += seconds(offset); 
    std::cout << "final: " << accum << "\n"; 
} 

Prints:

epoch: 1901-Jan-01 00:00:00 
accumulating: 1969-Jan-19 03:14:07 
final: 2013-Dec-04 00:00:00 

Xem nó Live on Coliru

+0

Cảm ơn câu trả lời. Tôi đã làm một điều tương tự bản thân mình, tôi đã chỉ hy vọng cho một giải pháp với tăng hơn là làm việc xung quanh. Tôi đoán việc thiếu câu trả lời ở đây cho thấy không có gì. Ill chấp nhận câu trả lời của bạn nếu không có gì khác xuất hiện trong một vài ngày. – mathematician1975

+0

Thật tuyệt vời khi điều này phải được thực hiện, vào tháng 10 năm 2014, bằng C++ (ngay cả với Tăng cường). Tại sao các loại này không được chuyển sang 64 bit từ lâu? –

+0

@DanNissenbaum Tôi đã thử nghiệm với câu trả lời của bạn và thực sự, nó thanh lịch hơn nhiều! ** [Coliru] (http://coliru.stacked-crooked.com/a/a0be0c728be95b1f) ** – sehe

2

Mặc dù boost::posix_time::secondskhông có thể được sử dụng nếu giây đại diện cho một số lớn hơn 32 bit (tính đến tháng 10 năm 2014), nó tu RNS ra rằng boost::posix_time::millisecondsthể dễ dàng được sử dụng (không có cách giải quyết), như sau:

inline std::string convertMsSinceEpochToString(std::int64_t const ms) 
{ 
    boost::posix_time::ptime time_epoch(boost::gregorian::date(1970, 1, 1)); 
    boost::posix_time::ptime t = time_epoch + boost::posix_time::milliseconds(ms); 
    return boost::posix_time::to_simple_string(t); 
} 

Vì vậy, chỉ cần chuyển đổi giây 64-bit của bạn để mili giây (64-bit), và bạn tốt để đi!


Note Be/rất/nhận thức hành vi phụ thuộc biên dịch với công suất builting loại không thể thiếu:

uint64_t offset = 113ul*365ul*24ul*60ul*60ul*1000ul; // 113 years give or take some leap seconds/days etc.? 

sẽ làm việc trên GCC hoặc Clang, nhưng nó sẽ chỉ đơn giản là tràn các tính toán trong MSVC2013 . Bạn cần phải kết hợp rõ ràng tính toán với 64 bit:

uint64_t offset = uint64_t(113ul)*365*24*60*60*1000; 
Các vấn đề liên quan