#database #arrow
# Time
- **定义**
```fbs
table Time {
unit: TimeUnit = MILLISECOND;
bitWidth: int = 32;
}
```
- **含义**
- 自午夜开始流逝的时间(**一天内**,最大值小于24小时)
- 例如单位为秒的话,合法的值区间为 $\large [0,\ 864000=24 \times 60 \times 60)$;
- 如果单位为毫秒的话,最多到 86400000
<br>
- **支持两种 bitWidth**
- **32位**:此时,单位 (unit) 可以是 SECOND 和 MILLISECOND
- **64位**:此时,单位可以是 MIRCOSECOND 和 NANOSECOND
<br>
--------
<br>
## Timestamp
- **定义**
```fbs
table Timestamp {
unit: TimeUnit;
timezone: string;
}
```
- **含义**
- Timestamp 的值存储为一个 64 位有符号整型,代表从某个 fixed epoch 作为起点所经历的时间, 单位为:seconds、milliseconds、microseconds 或者 nanoseconds
- 可以指定时区,时区格式为 timezone database(如 "America/New_York")或者 offset形式("+07:30")
- 不支持闰秒
<br>
- **带有时区的 Timestamp**
- 如果一个 Timestamp column 的 timezone 非空,它的 epoch 就是 **UTC** 1970-01-01 00:00:00,**忽略** Timestamp 自己的时区(这个时区**只代表了如何展示**)
- 因此,带有时区的 Timestamps 之间可以直接按值进行比较,因为它们共享一个相同的参考点(Unix epoch)
<br>
- **不带时区的 Timestamp**
- 它的 epoch 是 1970-01-01 00:00:00,但是 timezone 是**未知**的
- 因此,不带时区的 timestamp values 无法解释为物理时间点,只能作为 **wall clock time**
- 例如值为 0 的无时区 timestamp,对应一个未知时区的 "January 1st 1970, 00h00 "
- 无时区的 timestamp values **不能**比较和排序,它们可能有着不同的参考点。
<br>
- **更改时区**
- 如果 Timestamp类型定义里带有时区,则更改时区只需要操作元数据,不用改动 timestamp 的值。
- 如果没有时区,将它更改为一个非空时区,就需要考虑目标语义。
- 一种可能是将原始值解释为相对于目标时区,然后再调整为相对 UTC epoch。
<br>
- **外部库如何编码数据**
- **instant**:代表时间上的物理点,没有相对时区。可以使用 UTC 时区的 Timestamp 进行编码
- **zoned date-time**:代表时间上的物理点加上时区。编码使用相同时区的 Timestamp 类型,value要相对于 UTC epoch
- **offset date-time**:如 "+03:00",类似 zoned date-time
<br>
- **naive datetime**:
- 一些库也称为 local date-time,表示一个 wall clock time + 一个 calendar date,
- **没有表明**如何映射到物理时间点。需要小心处理,因为缺少这些信息,加上夏令时可能使一些值存在歧义或者不存在。
- 可以存储为一个 struct(含有 Date + Time 字段)
- 也可以编码为无时区的 Timestamp 类型,value 计算需要假设 date time 是 UTC 的。
> 如 “January 1st 1970, 00h00” 编码为 Timestamp 时 value 为 0.
-----------------
# Date
- **定义**
```fbs
enum DateUnit: short {
DAY,
MILLISECOND
}
table Date {
unit: DateUnit = MILLISECOND;
}
```
- **含义**
- 表示自 UNIX epoch (1970-01-01) 开始流逝的时间
- 两个单位:
- **Milliseconds**:值存储为 64位整型,表示自 UNIX epoch 之后过了多少毫秒,值可以被 86400000 **整除**
- **Days**:值存储为 32位整型,表示自 UNIX epoch 之后过了多少天
---------
## Decimal
- **定义**
```fbs
table Decimal {
/// Total number of decimal digits
precision: int;
/// Number of digits after the decimal point "."
scale: int;
bitWidth: int = 128;
}
```
- **含义**
存储精确的数值数据:
- **precision**:代表总的数字位数(十进制)
- **scale**:表示小数点后的位数
- 底层存储为 128位 / 256 位整型
> 如 `DECIMAL(5,2)`, 可以存储范围为 $-999.99$ 到 $999.99$ 的数字
- **Arrow使用**
- 从十进制字符串解析:`arrow_cast::parse::parse_decimal()`
- 从 i128 中还原为字符串:`arrow::datatypes::Decimal128Type::format_decimal()`
- 128类型最多支持到38位(precision),小于 2^127 的位数