文章目录
第四章 数据类型(三)
日期、时间、PosixTime 和时间戳数据类型
可以定义日期、时间和时间戳数据类型,并通过标准 SQL 日期和时间函数相互转换日期和时间戳。例如,可以使用 CURRENT_DATE
或 CURRENT_TIMESTAMP
作为使用该数据类型定义的字段的输入,或者使用 DATEADD
、DATEDIFF
、DATENAME
或 DATEPART
来操作使用该数据类型存储的日期值。
数据类型类 %Library.Date
、%Library.Time
、%Library.PosixTime
、%Library.TimeStamp
和 %MV.Date
对于 SqlCategory
的处理方式如下:
-
%Library.Date
类以及逻辑值为+$HOROLOG
($HOROLOG
的日期部分)的任何用户定义数据类型类都应使用DATE
作为SqlCategory
。默认情况下,DATE
和对应的%Library.Date
数据类型只接受正整数,0
代表1840-12-31
。要支持早于1840-12-31
的日期,必须在表中定义数据类型为%Library.Date(MINVAL=-nnn)
的日期字段,其中MINVAL
是从1840-12-31
倒数的负天数最大为 -672045 (0001-01-01)
。%Library.Date
可以将日期值存储为-672045
到2980013
范围内的无符号或负整数。日期值可以按如下方式输入:
- 逻辑模式接受
+HOROLOG
整数值,例如65619
(2020 年 8 月 28 日)。 - 显示模式使用
DisplayToLogical()
转换方法。它接受当前语言环境的显示格式的日期,例如“8/28/2020”
。它还接受逻辑日期值(+HOROLOG
整数值)。 - ODBC 模式使用
ODBCToLogical()
转换方法。它接受 ODBC 标准格式的日期,例如“2020–08–28”
。它还接受逻辑日期值(+HOROLOG
整数值)。
-
%Library.Time
类和任何逻辑值为$PIECE($HOROLOG,”,”,2)
($HOROLOG
的时间部分)的用户定义数据类型类都应使用TIME
作为SqlCategory
。%Library.Time
将时间值存储为0
到86399
范围内的无符号整数(自午夜以来的秒数)。时间值可以按如下方式输入:
- 逻辑模式接受
$PIECE($HOROLOG,”,”,2)
整数值,例如84444 (23:27:24)
。 - 显示模式使用
DisplayToLogical()
转换方法。它接受当前语言环境的显示格式的时间,例如“23:27:24”
。 - ODBC 模式使用
ODBCToLogical()
转换方法。它接受 ODBC 标准格式的时间,例如“23:27:24”
。它还接受逻辑时间值(0
到86399
范围内的整数)。
TIME
支持小数秒,因此此数据类型也可用于 HH:MI:SS.FF
到用户指定的精度 (F) 小数位数,最多为 9
。要支持小数秒,请设置 PRECISION
范围。例如,TIME(0) (%Time(PRECISION=0))
舍入到最接近的秒数;TIME(2) (%Time(PRECISION=2))
将(或零填充)四舍五入到精度的两位小数。
如果提供的数据还指定了精度(例如,CURRENT_TIME(3)
),则存储的小数位数如下:
- 如果
TIME
未指定精度,而数据指定了精度,则使用数据的精度。 - 如果
TIME
未指定精度且数据未指定精度,则使用系统范围配置的时间精度。 - 如果
TIME
指定精度而数据未指定精度,则使用系统范围配置的时间精度作为数据精度。 - 如果
TIME
指定了精度并且数据精度小于TIME
精度,则使用数据精度。 - 如果
TIME
指定了精度并且数据精度大于TIME
精度,则使用TIME
精度。
SQL 元数据将时间精度的小数位报告为“scale”
;它使用“precision
精度”一词来表示数据的总长度。使用 TIME
数据类型的字段报告精度和比例元数据如下:TIME(0)
(%Time(PRECISION=0))
的元数据精度为 8 (nn:nn:nn)
,比例为 0
。TIME(2 ) (%Time(PRECISION=2)) 的元数据精度为 11 (nn:nn:nn.ff)
,比例为 2
。TIME (%Time 或 %Time(PPRECISION="")
采用其小数秒精度来自提供的数据,因此元数据精度为 18
和未定义的比例。
-
%Library.PosixTime
类和任何具有编码的有符号64
位整数逻辑值的用户定义数据类型类都应使用 POSIXTIME 作为SqlCategory
。%PosixTime
是从1970–01–01 00:00:00
以来的秒数(和小数秒)计算的编码时间戳。该日期之后的时间戳由正%PosixTime
值表示,该日期之前的时间戳由负 %PosixTime 值表示。%PosixTime
支持最多6
位精度的小数秒。%PosixTime
支持的最早日期为0001-01-01 00:00:00
,其逻辑值为-6979664624441081856
。支持的最后日期为9999-12-31
23:59:59.999999
,其逻辑值为1406323805406846975
。
因为 %PosixTime
值始终由编码的 64
位整数表示,所以它始终可以明确地区分于 %Date
或 %TimeStamp
值。例如,1970–01–01 00:00:00
的 %PosixTime
值为 1152921504606846976
,2017–01–01 00:00:00
的 %PosixTime
值为 1154404733406846976
,1969–12–01
的 %PosixTime
值00:00:00
是 -6917531706041081856
。
%PosixTime
比 %TimeStamp
更可取,因为它比 %TimeStamp
数据类型占用更少的磁盘空间和内存,并且提供比 %TimeStamp
更好的性能。
可以使用 ODBC 显示模式集成 %PosixTime
和 %TimeStamp
值:
-
%PosixTime
和%TimeStamp
数据类型的逻辑模式值完全不同:%PosixTime
是有符号整数,%TimeStamp
是包含 ODBC 格式时间戳的字符串。 - 显示方式:
%PosixTime
显示使用当前locale
时间和日期格式参数(例如02/22/2018 08:14:11
);%TimeStamp
显示为 ODBC 格式的时间戳。 - ODBC 模式:
%PosixTime
和%TimeStamp
都显示为 ODBC 格式的时间戳。精度的小数位数可能不同。
可以使用 TO_POSIXTIME
函数或 TOPOSIXTIME()
方法将 %TimeStamp
值转换为 %PosixTime
。可以使用 IsValid()
方法来确定数值是否为有效的 %PosixTime
值。
-
%Library.TimeStamp
类和任何具有YYYY-MM-DD HH:MI:SS.FF
逻辑值的用户定义数据类型类都应使用TIMESTAMP
作为SqlCategory
。请注意,%Library.TimeStamp
的最大精度来自系统平台的精度,最多为9
位小数秒,而%Library.PosixTime
的最大精度为6
位。因此,在某些平台上,%Library.TimeStamp
可能比%Library.PosixTime
更精确。%Library.TimeStamp
规范化会自动将精度超过9
位的输入值截断为9
位小数秒。 -
%Library.DateTime
是%Library.TimeStamp
的子类。它定义了一个名为DATEFORMAT
的类型参数,它覆盖了DisplayToLogical()
和OdbcToLogical()
方法来处理 TSQL 应用程序习惯的不精确的日期时间输入。 -
%MV.Date
类,或任何具有$HOROLOG-46385
逻辑日期值的用户定义数据类型类,应使用MVDATE
作为SqlCategory
。 - 不适合上述任何逻辑值的用户定义日期数据类型应将数据类型的
SqlCategory
定义为DATE
,并在数据类型类中提供LogicalToDate()
方法以将用户定义的逻辑日期值转换为%Library.Date
逻辑值和DateToLogical()
方法,用于将%Library.Date
逻辑值转换为用户定义的逻辑日期值。 - 不适合上述任何逻辑值的用户定义时间数据类型应将数据类型的
SqlCategory
定义为TIME
,并在数据类型类中提供LogicalToTime()
方法以将用户定义的逻辑时间值转换为%Library.Time
逻辑值和TimeToLogical()
方法,用于将%Library.Time
逻辑值转换为用户定义的逻辑时间值。 - 不适合上述任何逻辑值的用户定义时间戳数据类型应将数据类型的
SqlCategory
定义为TIMESTAMP
,并在数据类型类中提供LogicalToTimeStamp()
方法以将用户定义的逻辑时间戳值转换为%Library.TimeStamp
逻辑值和TimeStampToLogical()
方法,用于将%Library.TimeStamp
逻辑值转换为用户定义的逻辑时间戳值。
可以使用 =
, <>,
>
, <
运算符将 POSIXTIME
与 DATE
或 TIMESTAMP
值进行比较。
在将 FMTIMESTAMP
类别值与 DATE
类别值进行比较时, IRIS 在将其与 DATE
进行比较之前不会从 FMTIMESTAMP
值中去除时间。这与比较 TIMESTAMP
与 DATE
值以及比较 TIMESTAMP
与 MVDATE
值的行为相同。它还与其他 SQL 供应商比较时间戳和日期的方式兼容。这意味着当使用 SQL 相等 (=) 运算符进行比较时,FMTIMESTAMP 320110202.12
和 DATE 62124
的比较相等。应用程序必须将 FMTIMESTAMP
值转换为 DATE
或 FMDATE
值以仅比较值的日期部分。
1840 年 12 月 31 日之前的日期
日期通常由 DATE
数据类型或 TIMESTAMP
数据类型表示。
DATE
数据类型以 $HOROLOG
格式存储日期,作为从 1840 年 12 月 31 日的任意开始日期算起的正整数天数。默认情况下,日期只能由正整数 (MINVAL=0
) 表示,它对应于到 1840 年 12 月 31 日。但是,可以更改 %Library.Date MINVAL
类型参数以启用存储 1840 年 12 月 31 日之前的日期。通过将 MINVAL
设置为负数,可以存储 12 月 31 日之前的日期, 1840
为负整数。最早允许的 MINVAL
值为 -672045
。这对应于第 1 年 (CE) 的 1 月 1 日。 DATE
数据类型不能表示 BCE(也称为 BC)日期。
TIMESTAMP
数据类型默认为 1840–12–31 00:00:00
作为最早允许的时间戳。但是,可以更改 MINVAL 参数以定义可以存储 1840 年 12 月 31 日之前的日期的字段或属性。例如,MyTS %Library.TimeStamp(MINVAL='1492-01-01 00:00:00')
。最早允许的 MINVAL
值是 0001–01–01 00:00:00
。这对应于第 1 年 (CE) 的 1 月 1 日。 %TimeStamp
数据类型不能表示 BCE(也称为 BC)日期。
注意:请注意,这些日期计算并未考虑公历改革(1582 年 10 月 15 日颁布,但直到 1752 年才在英国及其殖民地采用)引起的日期变化。
可以重新定义语言环境的最短日期,如下所示:
s oldMinDate = ##class(%SYS.NLS.Format).GetFormatItem("DATEMINIMUM")
if oldMinDate = 0 {
d ##class(%SYS.NLS.Format).SetFormatItem("DATEMINIMUM",-672045)
s newMinDate = ##class(%SYS.NLS.Format).GetFormatItem("DATEMINIMUM")
w "Changed earliest date to ",newMinDate
} else {
w "Earliest date was already reset to ",oldMinDate
}
上面的示例将语言环境的 MINVAL
设置为允许的最早日期 (1/1/01
)。
注意:IRIS 不支持使用带有负逻辑 DATE 值的儒略日期(%Library.Date
值,MINVAL<0
)。因此,这些 MINVAL<0
值与 TO_CHAR
函数返回的儒略日期格式不兼容。