24

我在许多不同的时区(和时间段)中使用不同的数据库,通常会引起问题的一件事是日期/时间定义。

出于这个原因,由于日期是对起始值的引用,为了跟踪它是如何计算的,我尝试存储基准日期;即:该特定计算机/数据库支持的最短日期;

如果我看得很清楚,这取决于 RDBMS 和类型的特定存储。在 SQL Server 中,我发现了几种计算这个“基准日期”的方法;

SELECT CONVERT(DATETIME, 0) 

或者

SELECT DATEADD(MONTH, 0, 0 ) 

甚至是这样的演员:

DECLARE @300 BINARY(8) 
SET @300 = 0x00000000 + CAST(300 AS BINARY(4))
set @dt=(SELECT CAST(@300 AS DATETIME) AS BASEDATE)
print CAST(@dt AS NVARCHAR(100))

(其中@dt 是日期时间变量)

我的问题是,在 PostgreSQL 中是否有类似的计算基准日期的方法,即:支持的最小日期值并基于所有计算?

datetype的描述中,我可以看到支持的最小日期是公元前 4713 年,但是有没有办法像在 SQL Server 中那样以编程方式获取这个值(例如作为格式化的日期字符串)?

4

2 回答 2

21

该手册将这些值声明为:

  • 低值:公元前 4713 年
  • 高价值:294276 AD

正如克里斯指出的那样,需要注意的-infinity是,这也得到了支持。

请参阅手册同一页后面的注释;只有当您使用整数时间戳时,以上才是正确的,这是所有模糊的最新 PostgreSQL 版本中的默认值。如果有疑虑:

SHOW integer_datetimes;

会告诉你。如果您改用浮点日期时间,则会获得更大的范围和更少的(非线性)精度。任何以编程方式计算最小值的尝试都必须应对该限制。

PostgreSQL 不只是让您将零转换为时间戳以获得可能的最小时间戳,如果您使用浮点日期时间,这也没有多大意义。您可以使用朱利安日期转换功能,但这会给您纪元而不是最短时间

postgres=> select to_timestamp(0);
      to_timestamp      
------------------------
 1970-01-01 08:00:00+08
(1 row)

因为它接受负值。你会认为给它负 maxint 会起作用,但结果令人惊讶,我想知道我们是否有一个环绕式错误潜伏在这里:

postgres=> select to_timestamp(-922337203685477);
          to_timestamp           
---------------------------------
 294247-01-10 12:00:54.775808+08
(1 row)

postgres=> select to_timestamp(-92233720368547);
          to_timestamp           
---------------------------------
 294247-01-10 12:00:54.775808+08
(1 row)

postgres=> select to_timestamp(-9223372036854);
         to_timestamp         
------------------------------
 294247-01-10 12:00:55.552+08
(1 row)

postgres=> select to_timestamp(-922337203685);
ERROR:  timestamp out of range
postgres=> select to_timestamp(-92233720368);
          to_timestamp           
---------------------------------
 0954-03-26 09:50:36+07:43:24 BC
(1 row)

postgres=> select to_timestamp(-9223372036);
         to_timestamp         
------------------------------
 1677-09-21 07:56:08+07:43:24
(1 row)

(也许与 to_timestamp 需要双倍的事实有关,即使这些天时间戳存储为整数?)。

我认为将时间戳范围设置为您不会出错的任何时间戳可能是最明智的。毕竟,有效时间戳的范围是不连续的:

postgres=> SELECT TIMESTAMP '2000-02-29';
      timestamp      
---------------------
 2000-02-29 00:00:00
(1 row)

postgres=> SELECT TIMESTAMP '2001-02-29';
ERROR:  date/time field value out of range: "2001-02-29"
LINE 1: SELECT TIMESTAMP '2001-02-29';

所以你不能假设仅仅因为一个值在两个有效的时间戳之间,它就是它自己有效的。

于 2013-12-03T04:38:27.653 回答
12

最早的时间戳是“-infinity”。这是一个特殊的价值。另一边是“无限”,它晚于任何特定的时间戳。

我不知道以编程方式获取此信息的方法。我会像使用 NULL 一样使用硬编码的值。这意味着您必须在客户端处理无穷大。

于 2013-12-03T04:15:49.507 回答