Получить дату из значения длинных переменных в миллисекундах, хранящегося в базе данных Oracle - PullRequest
0 голосов
/ 30 ноября 2010

У меня дата хранится в базе данных как длинное значение в varchar, например: 1230748200000. Мне нужно получить год от него с помощью запроса оракула .. как я могу сделать это в оракуле? Есть ли способ, которым я могу скрыть это в Дата, чтобы я мог получить год? Проблема в том, что я не могу использовать to_char (SYSTIMESTAMP, 'yyyy') или to_Date, потому что у меня нет даты в формате Timestamp или Date ... вместо этого она имеет длинный varchar

Спасибо.

Edit: Можете ли вы дать решение для следующего сценария. У меня есть 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 00:03:18 IST2010 Почему здесь разница, пожалуйста?

Ответы [ 3 ]

2 голосов
/ 30 ноября 2010

Посмотрите здесь для получения дополнительной информации

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. Хотя это все только что было найдено в результате экспериментов, поэтому ваш пробег может отличаться.

1 голос
/ 11 декабря 2013

Мы хотели преобразовать длинные значения, хранящиеся в базе данных, в значения 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 - это миллисекундное значение java.util.Date от 10 декабря 2013 г. в центральном часовом поясе.

1 голос
/ 30 ноября 2010

@ MikeyByCrikey опубликовал хорошую отправную точку, но есть несколько вопросов, на которые нужно ответить, прежде чем вы сможете преобразовать строковое значение в дату:

A.Какая дата обозначена '0'?То есть, откуда начинается значение отсчета в миллисекундах?В примере @ Mikey используется «начальная» дата Unix (также называемая «датой эпохи») 01 января 1970 года, но в вашем сообщении недостаточно информации, чтобы узнать, что на самом деле является датой «0».Другие системы используют разные даты эпохи.Например, в системах, работающих под управлением операционной системы VMS, датой начала является 17 ноября 1858 года (случается, что это юлианский день 2 400 000);Windows (32- и 64-разрядные версии) использует 01-янв-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'));

Надеюсь, это полезно.

Делись и наслаждайся.

...