作者:Przemyslaw Piotrowski
Oracle 和 Python 的日期处理介绍
2007 年 9 月发布
从 Python 2.4 版开始,cx_Oracle 自身可以处理 DATE 和 TIMESTAMP 数据类型,将这些列的值映射到 Python 的 datetime 模块的 datetime 对象中。因为 datetime 对象支持原位的运算操作,这可以带来某些优势。内置的时区支持和若干专用模块使 Python 成为一台实时机器。感谢 cx_Oracle 的映射机制,Python 和 Oracle 间的日期/时间数据类型转换对开发人员是完全透明的。
Python 开发人员可能一开始会觉得 Oracle 的日期运算有点奇怪,但只需几点提示,该算法就会变得清楚且合理。本系列的这部分内容将帮助您从 Oracle 和 Python 两个角度来深入理解日期运算。二者均对日期/时间数据类型的处理提供丰富的支持,因此选择哪个由编程人员决定。如果您倾向于将应用程序逻辑放在数据库中,或者喜欢将日期/时间操作封装在应用程序自身内部,Oracle 和 Python 的无缝集成会为您带来最大的灵活性,同时编程工作量却很少。
Oracle
Oracle 的特色在于为时区和日期运算提供顶级的支持。用于处理时间和日期的基本的 Oracle 数据类型包括:DATE — 日期和时间信息,包括世纪、年、月、日、小时、分和秒。这种类型的列支持的值范围在公元前 4712 年 1 月 1 日到公元 9999 年 12 月 31 日之间。
TIMESTAMP — DATE 数据类型的粒度精确到秒。TIMESTAMP 字段包含 DATE 中的全部信息,另外还包括指定精度的秒的小数(最多为 9 位)。默认精度为 6 位。
TIMESTAMP WITH TIME ZONE — 除 TIMESTAMP 列中包含的信息外,此变体还包括时区偏移量,它是当地时间和 UTC(全球统一时间)时间之间的差值。精度属性与上面相同。
TIMESTAMP WITH LOCAL TIME ZONE — 与 TIMESTAMP WITH TIME ZONE 相对,此类型的值中不包含时区偏移量,而是由用户的当地会话时区确定该值。
日期时间由大量字段组成,数量由数据类型的粒度和变体决定。可以使用 EXTRACT 语句通过 SQL 查询将这些字段提取出来。要了解有关数据类型中的可用字段和时间间隔的详细信息,请参考Oracle 数据库 SQL 语言参考 的。我们来了解一下工作原理:SQL> SELECT EXTRACT(YEAR FROM hire_date) FROM employees ORDER BY 1;
EXTRACT(YEARFROMHIRE_DATE)
--------------------------
1987
1987
?
2000
107 rows selected.
利用此方法和 Oracle 的日期运算,您也可以得到两个日期之间的时间间隔:SQL> SELECT hire_date, SYSDATE, EXTRACT(YEAR FROM (SYSDATE-hire_date) YEAR TO MONTH) "Years"
2 FROM employees WHERE ROWNUM <= 5;
HIRE_DATE SYSDATE Years
------------------ ------------------ ----------
17-JUN-87 23-FEB-07 19
21-SEP-89 23-FEB-07 17
13-JAN-93 23-FEB-07 14
03-JAN-90 23-FEB-07 17
21-MAY-91 23-FEB-07 15
5 rows selected.日期操作涉及的另一数据类型是 INTERVAL,它表示一段时间。在编写本文时,Python 不支持将 INTERVAL 数据类型作为查询的一部分返回。唯一的方法是使用 EXTRACT 从时间间隔中提取出所需的信息。尽管如此,包含返回 TIMESTAMP 类型的时间间隔的查询仍然运转良好。
INTERVAL 类型有两个变体:INTERVAL YEAR TO MONTH — 存储年和月的数量信息。年的精度可以手动指定。默认值是 (INTERVAL YEAR(2) TO MONTH)。
Error — 这里提到的除 Warning 外的所有异常的基类。
INTERVAL DAY TO SECOND — 在要求更高的精度时,此类型将天、小时、分和秒的信息存储为一段时间。天和秒的精度都可以显式指定,范围为 0 到 9。默认值是 INTERVAL DAY(2) TO SECOND(6)。
SYSDATE+1 等于明天
现在看一下 Oracle 如何解决日期运算。在处理 datetime 列时,Oracle 认为 1 是指 1 天。这一方法确实非常直观。如果您想使用更小的单位