2010-11-30 28 views
0

我有一个数据库中的日期存储区作为varchar中的长整型值,例如:1230748200000. 我需要通过oracle查询从其中获得年份。我怎么能在Oracle中做到这一点?有没有一种方法可以将日期转换为日期以便我可以获得年份?问题是我不能使用to_char(SYSTIMESTAMP,'yyyy')或to_Date,因为我没有时间戳或日期格式的日期...而是让它只要varchar从存储在oracle数据库中的long var char毫秒值获取日期数据库

谢谢。

编辑: 你可以请给出一个解决方案,以下情况。我有1262284398000在我的表保存为VAR char.so正如我所说的,我需要让我今年使用下面的SQL这回一年,2009年

select 
to_char(
to_date('01-JAN-1970','DD-MM-YYYY HH24:MI SS') + (1262284398000/(1000*60 * 60 * 24)) ,'YYYY') 
from dual ; 

但在Java代码相同的值返回日期截止到2010年使年是不同的,

Calendar c = Calendar.getInstance(); 
    c.setTimeInMillis(1262284398000l); 
    System.out.println(c.getTime()); 
    System.out.println(c.get(Calendar.YEAR)); 

哪个日期返回作为星期五01月01 00:03:18 IST2010为什么这里的区别?

+0

关于Java和Oracle结果之间的区别:我不知道,也没有安装Java以便能够使用它。 Java碰巧报告2000年2月29日是无效日期吗?只是好奇。 – 2010-11-30 19:38:45

回答

2

有进一步信息

select epoch_time, extract(year from epoch_time) as year 
from (
    select date '1970-01-01' + 1291116794/86400 as epoch_time 
    from dual 
) 

看看here周围可能有不同时区等问题,因为我相信划时代的时间将在UTC但我是无法理解。

此外,它看起来像你的价值是13个位数,而不是10,所以你也许只需要通过86400000添加一些额外的零,即鸿沟,而不是86400。

编辑:正如我前面所说.. ..可能有时区问题。它看起来像Java代码采取1970-01-01(在UTC,因为它应该是)添加偏移量并将其转换为当地时间。您还需要在数据库查询中执行此操作。

我有点不清楚甲骨文如何处理时区,但有点实验后,我想出了下面的例子

alter session set time_zone = 'Asia/Calcutta'; 
select 
    sessiontimezone, 
    to_char(to_date('01-JAN-1970','DD-MM-YYYY HH24:MI SS') + 
    (1262284398000/(1000*60 * 60 * 24)) ,'YYYY'), 
    extract(year from cast(timestamp '1970-01-01 00:00:00 +00:00' at local + 
    numtodsinterval(1262284398000/1000, ' SECOND') as timestamp with time zone)), 
    to_char(timestamp '1970-01-01 00:00:00 +00:00' at local + 
    numtodsinterval(1262284398000/1000, ' SECOND'), 'YYYY'), 
    extract(year from cast(timestamp '1970-01-01 00:00:00 +00:00' at local + 
    numtodsinterval(1262284398000/1000, ' SECOND') as timestamp with local time 
    zone)) 
from dual; 

在上面的例子中,前两列(SESSIONTIMEZONE后)应是2009年,最后两个应该是2010年。虽然这一切都只是通过实验发现,所以你的里程可能会有所不同。

1

@MikeyByCrikey贴一个很好的起点,但也有您需要回答之前,您可以将字符串值转换为日期一对夫妇的问题:

A.什么日期由“0”来表示?也就是说,这个毫秒计数值从哪里开始?在@ Mikey的例子中,使用了1970年1月1日的Unix“开始”日期(也称为'epoch date'),但是在帖子中没有足够的信息来知道'0'日期实际上是什么。其他系统使用不同的时代日期。例如,在运行VMS操作系统的系统上,时间日期是1858年11月17日(正好是Julian日2,400,000); Windows(32位和64位版本)使用01年1月1日 - 1601年(公元400年格里历日历周期中的第一年,当该OS设计时是当前日历周期);和其他计算机系统使用不同的'0'日期。

B.在Oracle中将字符串转换为数字相当容易。我只是用TO_NUMBER功能,如:

strMillisecs VARCHAR2(100) := '1230748200000'; 
    nMilliseconds NUMBER; 

    nMilliseconds := TO_NUMBER(strMillisecs); 

。一旦你得到了这一点(“0”日期是已知的,并将该字符串转换为数字),全年可提取如下:

dtEpoch_date   DATE := TO_DATE('01-JAN-1970', 'DD-MON-YYYY'); -- for example 
    strMillisecs   VARCHAR2(100) := '1230748200000'; 
    nMilliseconds  NUMBER; 
    dtTarget_date  DATE; 
    nYear    NUMBER; 
    nMillisecs_in_a_day NUMBER := 86400000; 

    nMilliseconds := TO_NUMBER(strMillisecs); 

    -- Note: there are 

    dtTarget_date := dtEpoch_date + (nMilliseconds/nMillisecs_in_a_day); 

    -- FINALLY! 

    nYear := TO_NUMBER(TO_CHAR(dtTarget_date, 'YYYY')); 

希望这是有用的。

分享和享受。

+0

感谢鲍勃的答案..你可以看看编辑的问题,我描述了我即将到来的最新问题 – Harshana 2010-11-30 14:06:54

1

我们希望将存储在数据库中的长整型值转换为中央时区中的TIMESTAMP值。

这工作。

select FROM_TZ(
    TO_TIMESTAMP('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + 
    NUMTODSINTERVAL(1386655200000/1000,'SECOND'), 
    'UTC') at time zone 'America/Chicago' 
from dual 

其中1386655200000是中央时区中2013年12月10日的java.util.Date的毫秒值。