C++ 和 Sqlite3:如何以毫秒精度存储 date/time
C++ and Sqlite3: How to store date/time with milliseconds precision
我正在构建一个 C++ 应用程序,它将在 Ubuntu 中 运行 并将使用 Sqlite3 作为数据库。
我的目标之一是拥有一个包含 time/date 字段的 C++ class 然后存储在数据库中。
过去我在 class 上使用 time_t
作为变量类型,并在 Sqlite3 上将它们存储为 INTEGER
类型,例如:
C++ Class:
class MyClass {
time_t dateTimeInfo;
}
Sqlite3:
CREATE TABLE MYCLASS (....., INTEGER DATETIMEINFO, ...);
这种方法让我可以 SELECT
次使用不同的比较运算符 (>, >=, < , <=, ==
) 而完全没有问题,因为我处理的是简单的数字。在用户级别 time_t
被转换为 ISO 8601 std::string´s
这样我就可以拥有一个人类可读的界面。
除了它不支持毫秒外,它工作得很好。在我目前的项目中,我需要支持他们,所以我需要对此进行更改。
据我了解,我需要使用 std::chrono::time_point
作为 class 类型,如下所示:
C++ Class:
class MyClass {
std::chrono::time_point dateTimeInfo;
}
但我真的不知道在 Sqlite3 中使用什么数据类型以及它是否会像 time_t
以前那样工作...
Sqlite3:
CREATE TABLE MYCLASS (....., ???? DATETIMEINFO, ...);
我的问题:
a) std::chrono::time_point
是正确的选项吗?
b) 等效的 Sqlite3 类型是什么?还是 INTEGER
?
c) 这是推荐的方法吗(请不要 boost
,C++11)?
感谢您的帮助。
是的,std::chrono
是一个很好的方法(C++ 内部)。您可以使用 std::chrono
转换时间点 from/to 毫秒,如下所示:
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();
在这种情况下,您应该使用 64 位整数类型将其与 SQLite 一起存储,因为数据可以超过 32 位。
评论:我对 SQLite 还不是很了解,但是我发现它适用于 64 位类型:official docs.
您可以将 ISO 8601 字符串格式的时间直接存储为 TEXT
。例如,您可以进行以下 table:
CREATE TABLE tbl(name TEXT, ts TEXT);
并插入 ISO 8601 格式的字符串 和毫秒值 作为文本字符串:
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');
此时您可以使用比较运算符查询它们:
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
作为额外的好处,当您与此数据库交互时,您将获得 ISO 8601 格式,无论如何,这就是您在客户端所做的。
此方法利用了这样一个事实,即在时区内,字符串的字典顺序会产生语义上正确的日期时间顺序。如果您的使用场景涉及多个时区,使用单个时区(例如 UTC 时间)存储在数据库中有助于保持这种顺序 属性.
我正在构建一个 C++ 应用程序,它将在 Ubuntu 中 运行 并将使用 Sqlite3 作为数据库。
我的目标之一是拥有一个包含 time/date 字段的 C++ class 然后存储在数据库中。
过去我在 class 上使用 time_t
作为变量类型,并在 Sqlite3 上将它们存储为 INTEGER
类型,例如:
C++ Class:
class MyClass {
time_t dateTimeInfo;
}
Sqlite3:
CREATE TABLE MYCLASS (....., INTEGER DATETIMEINFO, ...);
这种方法让我可以 SELECT
次使用不同的比较运算符 (>, >=, < , <=, ==
) 而完全没有问题,因为我处理的是简单的数字。在用户级别 time_t
被转换为 ISO 8601 std::string´s
这样我就可以拥有一个人类可读的界面。
除了它不支持毫秒外,它工作得很好。在我目前的项目中,我需要支持他们,所以我需要对此进行更改。
据我了解,我需要使用 std::chrono::time_point
作为 class 类型,如下所示:
C++ Class:
class MyClass {
std::chrono::time_point dateTimeInfo;
}
但我真的不知道在 Sqlite3 中使用什么数据类型以及它是否会像 time_t
以前那样工作...
Sqlite3:
CREATE TABLE MYCLASS (....., ???? DATETIMEINFO, ...);
我的问题:
a) std::chrono::time_point
是正确的选项吗?
b) 等效的 Sqlite3 类型是什么?还是 INTEGER
?
c) 这是推荐的方法吗(请不要 boost
,C++11)?
感谢您的帮助。
是的,std::chrono
是一个很好的方法(C++ 内部)。您可以使用 std::chrono
转换时间点 from/to 毫秒,如下所示:
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();
在这种情况下,您应该使用 64 位整数类型将其与 SQLite 一起存储,因为数据可以超过 32 位。
评论:我对 SQLite 还不是很了解,但是我发现它适用于 64 位类型:official docs.
您可以将 ISO 8601 字符串格式的时间直接存储为 TEXT
。例如,您可以进行以下 table:
CREATE TABLE tbl(name TEXT, ts TEXT);
并插入 ISO 8601 格式的字符串 和毫秒值 作为文本字符串:
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');
此时您可以使用比较运算符查询它们:
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
作为额外的好处,当您与此数据库交互时,您将获得 ISO 8601 格式,无论如何,这就是您在客户端所做的。
此方法利用了这样一个事实,即在时区内,字符串的字典顺序会产生语义上正确的日期时间顺序。如果您的使用场景涉及多个时区,使用单个时区(例如 UTC 时间)存储在数据库中有助于保持这种顺序 属性.