0

我在数据库中有一个日期存储为 varchar 中的长值,例如:1230748200000。我需要使用 oracle 查询从中获取年份。我该如何在 oracle 中进行操作?有没有办法可以将它转换为日期,以便我可以得到年份?问题是我不能使用 to_char(SYSTIMESTAMP,'yyyy') 或 to_Date 因为我没有时间戳或日期格式的日期......而不是将它作为 long varchar

谢谢你。

编辑:您能否为以下情况提供解决方案。我的表中有 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)); 

哪个日期返回为 Fri Jan 01 00:03:18 IST2010 为什么这里有区别?

4

3 回答 3

2

这里查看更多信息

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

时区等可能存在问题,因为我相信纪元时间将以 UTC 表示,但这超出了我的理解范围。

此外,您的值看起来是 13 位而不是 10 位,因此您可能只需要添加一些额外的零,即除以 86400000 而不是 86400。

编辑:正如我上面所说....可能存在时区问题。看起来Java代码正在使用1970-01-01(应该是UTC)添加偏移量并将其转换为本地时间。您还需要对数据库查询执行此操作。

我对 Oracle 如何处理时区有点不清楚,但经过一些试验,我想出了以下示例

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。虽然这一切都是通过实验才发现的,所以你的里程可能会有所不同。

于 2010-11-30T11:50:39.353 回答
1

我们希望将存储在数据库中的 long 值转换为中央时区中的 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 的毫秒值。

于 2013-12-11T13:34:18.133 回答
1

@MikeyByCrikey 发布了一个很好的起点,但在将字符串值转换为日期之前,您需要回答几个问题:

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

B. 在 Oracle 中将字符串转换为数字相当容易。我只使用 TO_NUMBER 函数,如下所示:

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

  nMilliseconds := TO_NUMBER(strMillisecs);

C. 一旦你到达了这一点('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'));

希望这是有用的。

分享和享受。

于 2010-11-30T12:32:37.120 回答