我有以下SQL查询将长号转换为日期,我无法将日期转换回长号。请让我知道你的建议。
SELECT to_date((( 1432550197431912935 - POWER(2,60)) /POWER(2,44)) + to_date('01-JAN-1970','DD-MON-YYYY')) from dual
2013年7月9日
select TO_CHAR(((TO_DATE ('09-JUL-2013','DD-MON-YYYY') -to_date('01-JAN-1970','DD-MON-YYYY')) * POWER(2,44) ) + POWER(2,60)) from dual
输出
1432549301782839296
长值不一样。
答案 0 :(得分:6)
您在转换中失去了太多精确度,无法以其他方式返回。通过使用时间戳而不是日期,您可以更接近。
首先,您的初始查询完全丢失了时间组件:
select to_char(date '1970-01-01'
+ (1432550197431912935 - power(2, 60))/power(2, 44), 'YYYY-MM-DD HH24:MI:SS')
from dual;
2013-07-09 01:13:19
......但即便如此,转回的方式已经失去了太多:
select ((to_date('2013-07-09 01:13:19','YYYY-MM-DD HH24:MI:SS')
- date '1970-01-01') * power(2, 44)) + power(2, 60) from dual;
1432550197477589405
这比你得到的更接近1432549301782839296,但还有很长的路要走。
部分问题是DATE
的精确度,仅为第二个。如果你使用TIMESTAMP
代替你可以相当接近;你可以看到所拥有的价值非常精确:
select timestamp '1970-01-01 00:00:00'
+ numtodsinterval((1432550197431912935 - power(2, 60))/power(2, 44), 'DAY')
from dual;
2013-07-09 01:13:18.775670462
通过时间戳算法给出间隔结果,将其转换回来很复杂,然后您必须先操作以返回到数字,首先作为原始天数:
select extract(day from int_val)
+ extract(hour from int_val) / 24
+ extract(minute from int_val) / (24 * 60)
+ extract(second from int_val) / (24 * 60 * 60)
from (
select to_timestamp('2013-07-09 01.13.18.775670462', 'YYYY-MM-DD HH24:MI:SS.FF9')
- timestamp '1970-01-01 00:00:00' as int_val from dual);
15895.0509117554451620370370370370370371
......然后用你的力量操控:
select ((extract(day from int_val)
+ extract(hour from int_val) / 24
+ extract(minute from int_val) / (24 * 60)
+ extract(second from int_val) / (24 * 60 * 60))
* power(2, 44)) + power(2, 60)
as x
from (
select to_timestamp('2013-07-09 01.13.18.775670462', 'YYYY-MM-DD HH24:MI:SS.FF9')
- timestamp '1970-01-01 00:00:00' as int_val from dual);
1432550197431912935.09988554676148148148
这非常接近。你可以将它截断或舍入到最接近的整数。
只是看看你的数字和每种方式的权力操纵都表明它似乎符合Oracle可以应对的精确度:
select (1432550197431912935 - power(2, 60)) / power(2, 44)
from dual;
15895.050911755445156359201064333319664
select (15895.050911755445156359201064333319664 * power(2, 44)) + power(2, 60)
from dual;
1432550197431912935.000...
即使有时间戳,你也会失去一些,因为第一个值超过了9位数的小数秒限制。代表小数秒的部分 - 一旦你占了15895小时等 - 是一天.0000089776673785814232865555418862
,即.77567046150943497195839881896768
秒;时间戳将舍入为.775670462
。所以它永远不会是完美的。
这也让人想知道原始数字是如何产生的;它似乎不太可能实际上代表一个极端精确的时间,因为它低于yoctoseconds。如果精确度不高,那就不太清楚了。实际上它是基于2的幂被操纵的人工制品,但它无论如何都看起来不是很有用。使用Unix风格的纪元日期更为常见,无论如何,如果必须将其存储为数字,则计算自您使用的纪元日期以来的秒数或有时毫秒数。这个设计很有趣。
答案 1 :(得分:0)
尝试使用以下查询:
select TO_CHAR(((TO_DATE ('09-JUL-2013','DD-MON-YYYY') -to_date('01-JAN-1970','DD-MON-YYYY')) + POWER(2,60) ) * POWER(2,44)) from dual