MySQL 中日期是如何编码/存储的?
我必须从 C++ 上的应用程序的数据库中获取的原始字节中解析日期。我发现MySQL中的日期是4个字节,最后两个分别是月份和日期。但是前两个字节奇怪地编码了年份,因此如果日期是2002-08-30,则内容将为210,15,8,31。如果日期是1996-12-22,则日期将存储为204 、15、12、22。 显然,第一个字节不能大于255,所以我检查了2047年——它是255、15和2048——它是128、16。
一开始我以为关键是二进制运算,但我做到了不太明白逻辑:
2047: 0111 1111 1111
255: 0000 1111 1111
15: 0000 0000 1111
2048: 1000 0000 0000
128: 0000 1000 0000
16: 0000 0001 0000
有什么想法吗?
I have to parse date from raw bytes I get from the database for my application on C++. I've found out that date in MySQL is 4 bytes and the last two are month and day respectively. But the first two bytes strangely encode the year, so if the date is 2002-08-30, the content will be 210, 15, 8, 31. If the date is 1996-12-22, the date will be stored as 204, 15, 12, 22.
Obviously, the first byte can't be bigger than 255, so I've checked year 2047 -- it's 255, 15, and 2048 -- it's 128, 16.
At first I thought that the key is binary operations, but I did not quite understand the logic:
2047: 0111 1111 1111
255: 0000 1111 1111
15: 0000 0000 1111
2048: 1000 0000 0000
128: 0000 1000 0000
16: 0000 0001 0000
Any idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(5)
哪个版本???
DATETIME
过去以压缩十进制(8 个字节)编码。但是,当添加秒小数部分时,格式会更改为类似
- 长度指示(1 字节)
INT UNSIGNED
的秒数 - 自 1970 年以来(4 字节)- 小数秒(0-3 字节)
DATE
的存储方式与 MEDIUMINT UNSIGNED
(3 个字节)一样,为自 0000-00-00(或类似的时间)以来的天数。
你是如何获得“原始字节”的?没有任何功能可以让你这样做。 Select HEX(some-date) 首先转换为字符串(如“2022-03-22”),然后取其十六进制。这将为您提供 323032322D30332D3232
。
关于代码请参考答案。
关于文档内容检查以下文字:
getBytes文档链接到ColumnMetaData
文档 URL。
ColumnMetaData文档链接到protobuf编码url。
protobuf 编码 url / Protocol Buffers 文档 文档说:
基础 128 变体
可变宽度整数或变体是连线的核心
格式。它们允许在任何地方使用无符号 64 位整数进行编码
1 到 10 个字节之间,较小的值使用较少的字节。varint 中的每个字节都有一个连续位,指示是否
它后面的字节是 varint 的一部分。 这是最重要的
字节的有效位 (MSB)(有时也称为符号
少量)。低7位是有效负载;生成结果整数
通过将其组成字节的 7 位有效负载附加在一起。例如,这里是数字 1,编码为
01
– 它是一个
字节,因此未设置 MSB:<前><代码>0000 0001
^ 最高位这里是 150,编码为
9601
– 这有点复杂:<前><代码>10010110 00000001
^ 最高位 ^ 最高位你怎么知道这是150?首先你从
每个字节,因为这只是告诉我们是否已经到达
数字的末尾(如您所见,它设置在第一个字节中,如下所示)
varint 中多于一个字节)。然后我们连接7位
有效负载,并将其解释为小尾数、64 位无符号
整数:10010110 00000001 // 原始输入。 0010110 0000001 // 删除连续位。 0000001 0010110 // 放入小端顺序。 10010110 // 连接。 128 + 16 + 4 + 2 = 150 // 解释为整数。
因为在 protoscope 中,varints 对于协议缓冲区非常重要
语法中,我们将它们称为普通整数。 150 与9601
相同。
varint 中的每个字节都有一个连续位,指示其后面的字节是否是 varint 的一部分。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我们遇到了同样的问题,并开发了以下 C++20 辅助方法,用于与 mysqlx (MySQL Connector/C++ 8.0 X DevAPI) 一起进行生产,以正确读取 DATE、DATETIME 和 TIMESTAMP 字段:
然后可以按如下方式使用:
getBytes 文档链接到
ColumnMetaData 文档 url。
ColumnMetaData文档链接到protobuf编码url。
protobuf 编码 url / Protocol Buffers 文档 文档说:
We had the same issue and developed the following C++20 helper methods for production use with mysqlx (MySQL Connector/C++ 8.0 X DevAPI) to properly read DATE, DATETIME and TIMESTAMP fields:
Which can then be used as follows:
getBytes document links to
ColumnMetaData
document url.ColumnMetaData document links to protobuf encoding url.
protobuf encoding url / Protocol Buffers Documentation Documentation say :