简体   繁体   中英

C++ and Sqlite3: How to store date/time with milliseconds precision

I´m building a C++ application that will be running in Ubuntu and will use Sqlite3 as a database.

One of my goals is to have a C++ class containing time/date fields and store then on database.

In the past I´ve used time_t as the variable type on my class and stored them as INTEGER type on Sqlite3, like:

C++ Class:

class MyClass {

        time_t dateTimeInfo;
}

Sqlite3:

CREATE TABLE MYCLASS (....., INTEGER DATETIMEINFO, ...);

That approach allows me to SELECT times with different comparasion operatiors ( >, >=, < , <=, == ) with no problems at all, as I´m dealing with simple number. At the user level the time_t is converted to ISO 8601 std::string´s so that I can have a human readable interface.

This works very well except that it does not support millisecods . In my current project I need to support them, so I need to make changes to this.

As far I had studies I undestand I need to use std::chrono::time_point as the class type, as follows:

C++ Class:

class MyClass {

        std::chrono::time_point dateTimeInfo;
}

But I really don´t know what data type to use in Sqlite3 and if it will work the same way time_t used to...

Sqlite3:

CREATE TABLE MYCLASS (....., ???? DATETIMEINFO, ...);

My questions:

a) Is std::chrono::time_point the correct option here ?

b) What is the Sqlite3 type equivalent ? Still an INTEGER ?

c) Is this the recommended approach (no boost please, C++11) ?

Thanks for helping.

You can store the ISO 8601 string formatted times as TEXT directly. For instance, you can make the following table:

CREATE TABLE tbl(name TEXT, ts TEXT);

and insert ISO 8601 formatted strings with millisecond values as a text string:

INSERT INTO tbl VALUES ('first', '2015-07-06T10:59:46.1234Z');
INSERT INTO tbl VALUES ('second', '2015-07-06T10:59:47.5678Z');
INSERT INTO tbl VALUES ('third', '2015-07-06T10:59:48.9012Z');

At this point you can query them using comparison operators:

SELECT * FROM tbl WHERE ts <= '2015-07-06T10:59:46.1233Z';
// Returns nothing
SELECT * FROM tbl WHERE ts <= '2015-07-06T10:59:46.1234Z';
// Returns the first record
SELECT * FROM tbl WHERE ts > '2015-07-06T10:59:46.1234Z';
// Returns the last two records

As an added bonus, you get ISO 8601 formats on the way out when you interface with this database, which is what you're doing on the client side anyway.

This method makes use of the fact that within a timezone, the lexicographic ordering of the strings produces a semantically correct ordering of datetimes. If your usage scenario involves multiple timezones, using a single timezone, such as UTC time, for storage within the database helps preserve this ordering property.

Yes, std::chrono is a very good approach (C++ internally). You can convert time points from/to milliseconds using std::chrono like this:

using namespace std::chrono;

typedef time_point<system_clock, milliseconds> time_points_millis;

time_points_millis tp = system_clock::now();

// An at least 43 bit signed integral type
auto epoch = tp.time_since_epoch();

In this case you should use an 64-bit integral type to store it with SQLite because the data can exceed 32 bits.

Comment: I don't really know much about SQLite, yet, but I found this for 64-bit types: official docs .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM