文章
· 六月 9, 2022 阅读大约需 6 分钟

第四章 数据类型(三)

第四章 数据类型(三)

日期、时间、PosixTime 和时间戳数据类型

可以定义日期、时间和时间戳数据类型,并通过标准 SQL 日期和时间函数相互转换日期和时间戳。例如,可以使用 CURRENT_DATECURRENT_TIMESTAMP 作为使用该数据类型定义的字段的输入,或者使用 DATEADDDATEDIFFDATENAMEDATEPART 来操作使用该数据类型存储的日期值。

数据类型类 %Library.Date%Library.Time%Library.PosixTime%Library.TimeStamp%MV.Date 对于 SqlCategory 的处理方式如下:

  1. %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 可以将日期值存储为 -6720452980013 范围内的无符号或负整数。日期值可以按如下方式输入:
  • 逻辑模式接受 +HOROLOG 整数值,例如 65619(2020 年 8 月 28 日)。
  • 显示模式使用 DisplayToLogical() 转换方法。它接受当前语言环境的显示格式的日期,例如“8/28/2020”。它还接受逻辑日期值(+HOROLOG 整数值)。
  • ODBC 模式使用 ODBCToLogical() 转换方法。它接受 ODBC 标准格式的日期,例如“2020–08–28”。它还接受逻辑日期值(+HOROLOG整数值)。
  1. %Library.Time 类和任何逻辑值为 $PIECE($HOROLOG,”,”,2)$HOROLOG 的时间部分)的用户定义数据类型类都应使用 TIME 作为 SqlCategory%Library.Time 将时间值存储为 086399 范围内的无符号整数(自午夜以来的秒数)。时间值可以按如下方式输入:
  • 逻辑模式接受$PIECE($HOROLOG,”,”,2) 整数值,例如 84444 (23:27:24)
  • 显示模式使用 DisplayToLogical() 转换方法。它接受当前语言环境的显示格式的时间,例如“23:27:24”
  • ODBC 模式使用 ODBCToLogical() 转换方法。它接受 ODBC 标准格式的时间,例如“23:27:24”。它还接受逻辑时间值(086399 范围内的整数)。

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),比例为 2TIME (%Time 或 %Time(PPRECISION="") 采用其小数秒精度来自提供的数据,因此元数据精度为 18 和未定义的比例。

  1. %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 值为 11529215046068469762017–01–01 00:00:00%PosixTime 值为 11544047334068469761969–12–01%PosixTime00: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 值。

  1. %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 位小数秒。
  2. %Library.DateTime%Library.TimeStamp 的子类。它定义了一个名为 DATEFORMAT 的类型参数,它覆盖了 DisplayToLogical()OdbcToLogical() 方法来处理 TSQL 应用程序习惯的不精确的日期时间输入。
  3. %MV.Date 类,或任何具有 $HOROLOG-46385 逻辑日期值的用户定义数据类型类,应使用 MVDATE 作为 SqlCategory
  4. 不适合上述任何逻辑值的用户定义日期数据类型应将数据类型的 SqlCategory 定义为 DATE,并在数据类型类中提供 LogicalToDate() 方法以将用户定义的逻辑日期值转换为%Library.Date 逻辑值和 DateToLogical() 方法,用于将 %Library.Date 逻辑值转换为用户定义的逻辑日期值。
  5. 不适合上述任何逻辑值的用户定义时间数据类型应将数据类型的 SqlCategory 定义为 TIME,并在数据类型类中提供 LogicalToTime() 方法以将用户定义的逻辑时间值转换为%Library.Time逻辑值和 TimeToLogical() 方法,用于将 %Library.Time 逻辑值转换为用户定义的逻辑时间值。
  6. 不适合上述任何逻辑值的用户定义时间戳数据类型应将数据类型的 SqlCategory 定义为 TIMESTAMP,并在数据类型类中提供 LogicalToTimeStamp() 方法以将用户定义的逻辑时间戳值转换为%Library.TimeStamp 逻辑值和 TimeStampToLogical() 方法,用于将 %Library.TimeStamp 逻辑值转换为用户定义的逻辑时间戳值。

可以使用 =, <>, >, < 运算符将 POSIXTIMEDATETIMESTAMP 值进行比较。

在将 FMTIMESTAMP 类别值与 DATE 类别值进行比较时, IRIS 在将其与 DATE 进行比较之前不会从 FMTIMESTAMP 值中去除时间。这与比较 TIMESTAMPDATE 值以及比较 TIMESTAMPMVDATE 值的行为相同。它还与其他 SQL 供应商比较时间戳和日期的方式兼容。这意味着当使用 SQL 相等 (=) 运算符进行比较时,FMTIMESTAMP 320110202.12DATE 62124 的比较相等。应用程序必须将 FMTIMESTAMP 值转换为 DATEFMDATE 值以仅比较值的日期部分。

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 函数返回的儒略日期格式不兼容。

讨论 (0)1
登录或注册以继续