Oracle TO_DATE не сохраняет формат - PullRequest
1 голос
/ 08 января 2010

Так как это кажется скорее вопросом синтаксиса, мой поиск не дал никаких полезных результатов.

Я пытаюсь сделать запрос, который получает европейские данные из американской базы данных, используя время по Гринвичу. Мне нужно узнать европейское время, но не могу заставить его работать правильно.

Давайте скажем "myDateField" = '01 -01-2010 '

SELECT TO_CHAR(myDateField + (60 / 1440), 'Mon" "DD", "YYYY')

Производит именно то, что я хочу, но мне нужно, чтобы остаться на свидание.
Производит: ' 01.01.2010 '

SELECT TO_DATE(TO_CHAR(myDateField + (60 / 1440)), 'Mon" "DD", "YYYY')

Появляется ошибка "Недопустимый месяц".
Производит: Ошибка

SELECT TO_DATE(TO_CHAR(myDateField + (60 / 1440), 'Mon" "DD", "YYYY'), 'Mon" "DD", "YYYY')

Работает, но форматирование потеряно.
Производит: ' 01-01-2010 '

Как я могу отформатировать это так, чтобы я мог получить результат, который дает первое утверждение, но также сохранить его как дату? Или вообще есть лучший метод?

EDIT:
Так же, как пример этого конкретного запроса, работающего при других обстоятельствах ... Это тот же запрос, но вместо преобразования в европейское время он конвертируется в другой часовой пояс в Северной Америке.

SELECT TO_DATE(TO_CHAR(NEW_TIME(myDateField, 'GMT', 'MDT')), 'Mon" "DD", "YYYY')

Производит именно то, что я хочу, сохраняя данные как дату.
Производит: ' 01.01.2010 '

В итоге:

Есть ли способ взять «myDateField + (60/1440)» или использовать ключевое слово «FROM_TZ», и заставить результат использовать формат «Mon» «DD», «YYYY», сохраняя при этом его тип даты

Ответы [ 3 ]

4 голосов
/ 08 января 2010

Я думаю, важно понимать, что желаемое форматирование вступает в силу как часть преобразования типов DATE в CHAR. Таким образом, ваше требование «установить формат, но сохранить его как дату» не имеет смысла - не в Oracle это не так.

Если вы просто хотите добавить некоторый интервал времени к дате и сохранить его в качестве даты, это все, что нужно:

myDateCol + (60 / 1440) -- add one hour to the date

и если вы хотите отформатировать его в европейском стиле, он становится

TO_CHAR(myDateCol + (60 / 1440), 'MON DD, YYYY')

но, конечно, тогда это будет строка, удобочитаемое представление фактического значения даты. А из-за формата на самом деле не хватает информации о времени.

Конечно, вы можете преобразовать эту дату обратно в:

TO_DATE(TO_CHAR(myDateCol + (60 / 1440), 'MON DD, YYYY'), 'MON DD, YYYY')

но серьезно - нет никакого смысла - потому что часть времени отсутствует в строке, эта дата будет фактически иметь 00:00:00 как время. Итак, вы только что потеряли информацию.

Это становится ясно, когда вы делаете такие вещи:

TO_CHAR(myDateCol + (60 / 1440), 'MON DD, YYYY HH24:MI:SS')

сравните это тоже:

TO_CHAR(
  TO_DATE(
    TO_CHAR(myDateCol + (60 / 1440), 'MON DD, YYYY HH24:MI:SS')
  , 'MON DD, YYYY'
  )
, 'MON DD, YYYY HH24:MI:SS'
)

(последнее выражение показывает, как вы урезали поля времени)

3 голосов
/ 08 января 2010

Дата - это просто дата - она ​​не имеет встроенного формата строки. Он имеет формат по умолчанию, то есть, когда вы запрашиваете дату в какой-либо программе или библиотеке, которая извлекает ее в виде строки, есть настройка по умолчанию, как она будет отформатирована.

Один из подходов - просто запросить дату и отформатировать ее в вашей клиентской программе. Например, в Java вы можете использовать класс DateFormat.

Но вы также можете попробовать ALTER SESSION SET NLS_DATE_FORMAT = 'Mon dd, yyyy'

и это может сработать.

Редактировать: Ваш второй запрос вернул мне ошибку not a valid month. Вы выполнили это после того, как следовали моему ALTER SESSION предложению?

2 голосов
/ 08 января 2010

Новый ответ, поскольку первый вызвал путаницу с датой и символом, а не часовыми поясами.

Вы спросили, есть ли лучший способ. Я думаю, что есть: использовать поддержку часового пояса оракула.

см .: http://download.oracle.com/docs/cd/B19306_01/server.102/b14225/ch4datetime.htm#i1006333

Пример запроса для преобразования даты и времени в другой часовой пояс:

SELECT FROM_TZ(
         CAST(TO_DATE('1999-12-01 11:00:00','YYYY-MM-DD HH:MI:SS') AS TIMESTAMP)
       , 'America/New_York'
       )
       AT TIME ZONE 'America/Los_Angeles' "West Coast Time"
FROM DUAL;

Использование этих функций гарантирует, что математика верна. После этого вы можете, конечно, отформатировать его так, как хотите, например:

SELECT TO_CHAR(
         FROM_TZ(
           CAST(TO_DATE('1999-12-01 11:00:00','YYYY-MM-DD HH:MI:SS') AS TIMESTAMP)
         , 'America/New_York'
         )
         AT TIME ZONE 'America/Los_Angeles' 
       , 'MON DD, YYYY') "West Coast Time"
FROM DUAL;

... но, как я указал в первом ответе, результатом здесь будет символ CHAR, а не дата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...