【问题标题】:to_Char(DATE) with timeto_Char(DATE) 与时间
【发布时间】:2018-09-12 13:34:47
【问题描述】:

我有一个数据库(Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production)。有一个表(课程),其中有一个日期列(start_dte)。我想将输出格式化为一个字符,所以我使用了:

SELECT start_dte,
   to_Char(start_dte) AS start_dte_2,
   to_Char(start_dte,'DD.MM.YYYY') AS start_dte_3,
   to_Char(start_dte,'DD.MM.YYYY HH24:MI:SS') AS start_dte_4,
   to_Char(start_dte,'DD.MM.YYYY HH12:MI:SS') AS start_dte_5,
   to_Char(start_dte,'DD.MM.YYYY HH.MI.SSXFF AM') AS start_dte_6,
   to_Char(start_dte,'DD.MM.YYYY HH24:MI:SSxFF') AS start_dte_7,
   to_Char(start_dte,'DD-MON-YYYY HH24:MI:SSxFF TZH:TZM') AS start_dte_8
FROM Course

结果:

6,7,8号给我

java.sql.SQLException: ORA-01821: 日期格式无法识别

6 与以下格式相同:

SELECT value
  FROM V$NLS_PARAMETERS
 WHERE parameter = 'NLS_TIME_FORMAT' 

7 和 8 取自 Oracle 文档,但这仅适用于时间戳。那么我错过了什么?我知道实际的数据类型应该是日期时间,但我只有对该数据库的读取权限。我真正想要的:

甚至更好:

【问题讨论】:

  • 请不要粘贴图片,使用格式化文本。
  • 日期有时间,但没有小数秒或时区,所以错误是合适的。 (尽管有一些像 NLS 设置这样的模糊引用,但没有 time 数据类型)。我不明白你到底在问什么; start_dte_4 肯定已经给了你你想要的吗?
  • @AlexPoole 不,因为它要休息 2 小时..
  • 所以你真的在问如何将日期值从一个时区调整到另一个时区?你的问题根本没有这么说。两个时区是什么时候?
  • @Alex Poole 我真的相信我不需要转换任何我想要与数据库中相同的日期/时间只是另一种格式的东西?

标签: sql oracle date time


【解决方案1】:

DATE 没有任何时区信息,因此如果要调整显示的时间,则需要指定该日期名义上代表的时区,以及要将其转换为的时区.

举个例子,如果您存储的日期表示 UTC,并且您想查看巴黎的等效本地时间,您可以通过将其转换为普通时间戳并将其传递到 the from_tz() function 来声明存储的时间是 UTC;然后specify the target timezone with at:

-- CTE for your sample data
with course (start_dte) as (
  select cast(timestamp '2018-10-17 14:00:00' as date) from dual
)
-- actual query
select from_tz(cast(start_dte as timestamp), 'UTC')
  at time zone 'Europe/Paris' as start_timestamp_tz
from course;

START_TIMESTAMP_TZ                        
------------------------------------------
2018-10-17 16:00:00.000000000 EUROPE/PARIS

由于您是通过 JDBC 查询的,因此您可能希望将其检索为它的本机数据类型,然后选择如何在本地显示它。 (但您大概可以将其作为日期查询并在 Java 中进行调整...)

如果你想在数据库端将其转换为字符串,只需使用你已经使用的格式模型:

select to_char(from_tz(cast(start_dte as timestamp), 'UTC')
  at time zone 'Europe/Paris', 'DD.MM.YYYY HH24:MI') as start_date
from course;

START_DATE      
----------------
17.10.2018 16:00

将其放入两个字段也很简单,如果您不想重复转换,可以使用 CTE 或内联视图:

select to_char(start_timestamp_tz, 'DD.MM.YYYY') as start_date,
  to_char(start_timestamp_tz, 'HH24:MI') as start_time
from (
  select from_tz(cast(start_dte as timestamp), 'UTC')
    at time zone 'Europe/Paris' as start_timestamp_tz
  from course
);


START_DATE START_TIME
---------- ----------
17.10.2018 16:00     

但听起来 Java 应该将这种转换为字符串以供显示。

【讨论】:

    【解决方案2】:

    我真正想要的:

    | START_DATE       |
    |------------------|
    | 17.10.2018 16:00 |
    

    甚至更好:

    | START_DATE | START_TIME |
    |------------|------------|
    | 17.10.2018 |      16:00 |
    

    用途:

    SELECT to_Char(start_dte,'DD.MM.YYYY') AS start_date,
           to_Char(start_dte,'HH24:MI') AS start_time
    FROM   Course
    

    如果您的数据存储在一个时区(即 UTC)的表中,并且您希望它在另一个时区,则使用:

    • CAST( date_value AS TIMESTAMP ) 将其从 DATE 数据类型转换为 TIMESTAMP 数据类型。
    • FROM_TZ( timestamp_value, timezone_string ) 在给定时区将其从 TIMESTAMP 数据类型转换为 TIMESTAMP WITH TIME ZONE 数据类型。
    • timestamp_with_timezone_value AT TIME ZONE timezone_string 将其从一个时区转换为另一个时区。

    像这样:

    SELECT TO_CHAR(
             FROM_TZ( CAST( start_dte AS TIMESTAMP ), 'UTC' ) AT TIME ZONE 'Europe/Berlin',
             'DD.MM.YYYY'
           ) AS start_date,
           TO_CHAR(
             FROM_TZ( CAST( start_dte AS TIMESTAMP ), 'UTC' ) AT TIME ZONE 'Europe/Berlin',
             'HH24:MI'
           ) AS start_time
    FROM   Course
    

    【讨论】:

      【解决方案3】:

      start_dte 是一个 DATE 值。

      DATE 既没有小数秒(即XFF)也没有时区信息(即TZH:TZM

      使用TIMESTAMP WITH TIME ZONE是不是你想得到这样的输出。

      【讨论】:

      • 我只有只读权限。我无法更改日期列
      • 那就试试CAST(start_dte AS TIMESTAMP WITH TIME ZONE)
      • 然后我得到:不支持的 JDBC 类型:-101
      猜你喜欢
      • 2014-07-09
      • 1970-01-01
      • 2021-03-02
      • 2011-11-02
      • 1970-01-01
      • 2017-02-08
      • 2013-12-15
      相关资源
      最近更新 更多