Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Oracle 11g中将多个日期varchar2转换为日期格式_Oracle_Date_Datetime_Oracle11g - Fatal编程技术网

在Oracle 11g中将多个日期varchar2转换为日期格式

在Oracle 11g中将多个日期varchar2转换为日期格式,oracle,date,datetime,oracle11g,Oracle,Date,Datetime,Oracle11g,我在尝试将多个日期转换为一种定义的格式时遇到问题。我们正在从另一个数据库源接收多个日期,因此在它到达我们的数据库源之前,我无法控制格式 以下是所有格式: YYYYMMDD YYYY-MM-DD HH:MM:SS 年月日 年月日 节略日月日HH:MM:SS时区YYYY'Thu Feb 02 20:49:59 MSK 2012' 完整书写日,月日,年时:月:日上午/下午 我的要求是将它们全部设置为标准的MM/DD/YYYY格式或null。有什么想法吗 谢谢。我建议使用带有类似regexp_条件的ca

我在尝试将多个日期转换为一种定义的格式时遇到问题。我们正在从另一个数据库源接收多个日期,因此在它到达我们的数据库源之前,我无法控制格式

以下是所有格式:

YYYYMMDD

YYYY-MM-DD HH:MM:SS

年月日

年月日

节略日月日HH:MM:SS时区YYYY'Thu Feb 02 20:49:59 MSK 2012'

完整书写日,月日,年时:月:日上午/下午

我的要求是将它们全部设置为标准的MM/DD/YYYY格式或null。有什么想法吗


谢谢。

我建议使用带有类似regexp_条件的case语句,在then条款中使用适当的日期掩码来检测可能的格式和返回日期,例如:

with tz as (
SELECT distinct tzabbrev
     , first_value(min(tzname)) over (partition by tzabbrev order by count(*) desc) tzname
  FROM v$timezone_names 
 group by tzabbrev
     , TZ_OFFSET(tzname)
), dta as (
select yt.install_date
     , regexp_replace(yt.install_date,tzabbrev,tzname,1,1,'i') install_date2
  from your_table yt
  left join tz
    on regexp_like(install_date, tz.TZABBREV,'i')
)
select install_date, install_date2
     , to_timestamp_tz( install_date2
              , case 
                  when regexp_like(install_date2,'^[A-Z]{3,} [A-Z]{3,} [0-9]{1,2} [0-9]{1,2}(:[0-9]{2}){1,2} [[:print:]]{5,} [0-9]{2,4}','i') then 'DY MON DD HH24:MI:SS TZR YYYY'
                  when regexp_like(install_date2,'^[A-Z]{4,},? [A-Z]{3,},? [0-9]{1,2},? [0-9]{2,4}','i') then 'DAY MONTH DD YYYY'
                  when regexp_like(install_date2,'^[A-Z]{3},? [A-Z]{3,},? [0-9]{1,2},? [0-9]{2,4}','i') then 'DY MONTH DD YYYY'
                  when regexp_like(install_date2,'^[0-9]{1,2}[-/][0-9]{1,2}[-/]([0-9]{2}){1,2}') then 'MM-DD-RRRR'
                  when regexp_like(install_date2,'^[0-9]{1,2}[-/ ][A-Z]{3,}[-/ ]([0-9]{2}){1,2}','i') then 'DD-MON-RRRR'
                  when regexp_like(install_date2,'^[A-Z]{3,}[-/ ][0-9]{1,2},?[-/ ]([0-9]{2}){1,2}','i') then 'MON-DD-RRRR'
                  when regexp_like(install_date2,'^(19|20)[0-9]{6}') then 'RRRRMMDD'
                  when regexp_like(install_date2,'^[23][0-9]{5}') then 'DDMMRR'
                  when regexp_like(install_date2,'^[0-9]{6}') then 'MMDDRR'
                  when regexp_like(install_date2,'^[01][0-9]{7}') then 'MMDDRRRR'
                  when regexp_like(install_date2,'^[23][0-9]{7}') then 'DDMMRRRR'
                  ELSE NULL
                end
              ||case
                  when regexp_like(install_date2, '[0-9]{1,2}(:[0-9]{2}){1,2}$') then ' HH24:MI:SS'
                  when regexp_like(install_date2, '[0-9]{1,2}(:[0-9]{2}){1,2} ?(am|pm)$','i') then ' HH:MI:SS AM'
                  else null
                end
              )
              Install_Time_Stamp
  from dta;

我对时区缩写有问题,因此我添加了一个步骤,首先用时区区域替换它们。

我建议使用带有类似regexp_条件的case语句,使用then子句中的适当日期掩码检测可能的格式和返回日期,例如:

with tz as (
SELECT distinct tzabbrev
     , first_value(min(tzname)) over (partition by tzabbrev order by count(*) desc) tzname
  FROM v$timezone_names 
 group by tzabbrev
     , TZ_OFFSET(tzname)
), dta as (
select yt.install_date
     , regexp_replace(yt.install_date,tzabbrev,tzname,1,1,'i') install_date2
  from your_table yt
  left join tz
    on regexp_like(install_date, tz.TZABBREV,'i')
)
select install_date, install_date2
     , to_timestamp_tz( install_date2
              , case 
                  when regexp_like(install_date2,'^[A-Z]{3,} [A-Z]{3,} [0-9]{1,2} [0-9]{1,2}(:[0-9]{2}){1,2} [[:print:]]{5,} [0-9]{2,4}','i') then 'DY MON DD HH24:MI:SS TZR YYYY'
                  when regexp_like(install_date2,'^[A-Z]{4,},? [A-Z]{3,},? [0-9]{1,2},? [0-9]{2,4}','i') then 'DAY MONTH DD YYYY'
                  when regexp_like(install_date2,'^[A-Z]{3},? [A-Z]{3,},? [0-9]{1,2},? [0-9]{2,4}','i') then 'DY MONTH DD YYYY'
                  when regexp_like(install_date2,'^[0-9]{1,2}[-/][0-9]{1,2}[-/]([0-9]{2}){1,2}') then 'MM-DD-RRRR'
                  when regexp_like(install_date2,'^[0-9]{1,2}[-/ ][A-Z]{3,}[-/ ]([0-9]{2}){1,2}','i') then 'DD-MON-RRRR'
                  when regexp_like(install_date2,'^[A-Z]{3,}[-/ ][0-9]{1,2},?[-/ ]([0-9]{2}){1,2}','i') then 'MON-DD-RRRR'
                  when regexp_like(install_date2,'^(19|20)[0-9]{6}') then 'RRRRMMDD'
                  when regexp_like(install_date2,'^[23][0-9]{5}') then 'DDMMRR'
                  when regexp_like(install_date2,'^[0-9]{6}') then 'MMDDRR'
                  when regexp_like(install_date2,'^[01][0-9]{7}') then 'MMDDRRRR'
                  when regexp_like(install_date2,'^[23][0-9]{7}') then 'DDMMRRRR'
                  ELSE NULL
                end
              ||case
                  when regexp_like(install_date2, '[0-9]{1,2}(:[0-9]{2}){1,2}$') then ' HH24:MI:SS'
                  when regexp_like(install_date2, '[0-9]{1,2}(:[0-9]{2}){1,2} ?(am|pm)$','i') then ' HH:MI:SS AM'
                  else null
                end
              )
              Install_Time_Stamp
  from dta;

我对时区缩写有问题,因此我添加了一个步骤,首先用时区区域替换它们。

您可以定义一个转换函数,基本上按顺序处理每种格式:

create or replace function translate_date(i_date_string VARCHAR2) return date as
begin
-- you may optimize to not to go in all blocks based on the string format
-- order the blocks on the expected frequency
 begin
   return to_date(i_date_string,'yyyymmdd');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end;  
 begin
   return to_date(i_date_string,'yyyy/mm/dd');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end; 
 begin
   return to_date(i_date_string,'yyyy-mm-dd');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end; 
 begin
   return to_date(i_date_string,'yyyy-mm-dd hh24:mi:ss');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end; 
 begin
 -- transform to local timestamp and than to date
   return cast(cast(to_timestamp_tz(i_date_string,'dy month dd hh24:mi:ss tzr yyyy') as TIMESTAMP WITH LOCAL TIME ZONE) as date);
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end; 
 begin
   return to_date(i_date_string,'dy, month dd, yyyy hh:mi:ss am');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end;  
 return NULL;
end;
/
例如,示例数据

 TSTMP                                                                                              
 ------------------------
 20150101                                                                                             
 2015-01-01 23:59:59                                                                                  
 2015/01/01                                                                                           
 2015-01-01                                                                                           
 Thu Feb 02 20:49:59 Europe/Moscow 2012                                                               
 Thu, Feb 02, 2012 10:49:59 AM                                                                        
 Thu, Feb 02, 2012 10:49:59 PM  
你得到

TSTMP                                       RESULT_DATE       
------------------------------------------  -------------------
20150101                                    01.01.2015 00:00:00 
2015-01-01 23:59:59                         01.01.2015 23:59:59 
2015/01/01                                  01.01.2015 00:00:00 
2015-01-01                                  01.01.2015 00:00:00 
Thu Feb 02 20:49:59 Europe/Moscow 2012      02.02.2012 17:49:59 
Thu, Feb 02, 2012 10:49:59 AM               02.02.2012 10:49:59 
Thu, Feb 02, 2012 10:49:59 PM               02.02.2012 22:49:59 

请注意,我跳过了时区缩写MSK的案例,请参阅@Sentinel答案中可能的解决方案,但请检查这可能有歧义。

您可以定义一个转换函数,基本上按顺序处理每种格式:

create or replace function translate_date(i_date_string VARCHAR2) return date as
begin
-- you may optimize to not to go in all blocks based on the string format
-- order the blocks on the expected frequency
 begin
   return to_date(i_date_string,'yyyymmdd');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end;  
 begin
   return to_date(i_date_string,'yyyy/mm/dd');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end; 
 begin
   return to_date(i_date_string,'yyyy-mm-dd');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end; 
 begin
   return to_date(i_date_string,'yyyy-mm-dd hh24:mi:ss');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end; 
 begin
 -- transform to local timestamp and than to date
   return cast(cast(to_timestamp_tz(i_date_string,'dy month dd hh24:mi:ss tzr yyyy') as TIMESTAMP WITH LOCAL TIME ZONE) as date);
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end; 
 begin
   return to_date(i_date_string,'dy, month dd, yyyy hh:mi:ss am');
 EXCEPTION
   WHEN OTHERS  THEN NULL;
 end;  
 return NULL;
end;
/
例如,示例数据

 TSTMP                                                                                              
 ------------------------
 20150101                                                                                             
 2015-01-01 23:59:59                                                                                  
 2015/01/01                                                                                           
 2015-01-01                                                                                           
 Thu Feb 02 20:49:59 Europe/Moscow 2012                                                               
 Thu, Feb 02, 2012 10:49:59 AM                                                                        
 Thu, Feb 02, 2012 10:49:59 PM  
你得到

TSTMP                                       RESULT_DATE       
------------------------------------------  -------------------
20150101                                    01.01.2015 00:00:00 
2015-01-01 23:59:59                         01.01.2015 23:59:59 
2015/01/01                                  01.01.2015 00:00:00 
2015-01-01                                  01.01.2015 00:00:00 
Thu Feb 02 20:49:59 Europe/Moscow 2012      02.02.2012 17:49:59 
Thu, Feb 02, 2012 10:49:59 AM               02.02.2012 10:49:59 
Thu, Feb 02, 2012 10:49:59 PM               02.02.2012 22:49:59 

请注意,我跳过了时区缩写MSK的案例,请参阅@Sentinel答案中的可能解决方案,但请检查这可能是不明确的。

该函数可以简化一点,因为它可以容忍微小偏差不同的分隔符、缺少分隔符、缺少时间分量、2/4位年份。例如,截止日期:str,“rrrr-mm-dd hh24:mi:ss”将涵盖

2020/09/18 01.02
2020.09.18 01
20200918010203
2020-0901
202009-01
20/09/18
To_timestamp_tz还将允许丢失毫秒和时区,包括丢失tz元素TZM和TZD。
因此,我们基本上只需要考虑主要的变化,如hh24/hh、mm/mon、元素顺序、ISO 8601 2020-01-01T01:02:03中的T分隔符、TZ指示符UTC偏移量TZH:TZM/地区名称TZR和星期日DY。

该函数可以稍微简化,因为迄今为止,它可以容忍不同分隔符、缺少分隔符、,缺少时间组件,2/4位年份。例如,截止日期:str,“rrrr-mm-dd hh24:mi:ss”将涵盖

2020/09/18 01.02
2020.09.18 01
20200918010203
2020-0901
202009-01
20/09/18
To_timestamp_tz还将允许丢失毫秒和时区,包括丢失tz元素TZM和TZD。
因此,我们基本上只需要考虑主要的变化,如hh24/hh、mm/mon、元素顺序、ISO 8601 2020-01-01T01:02:03中的T分隔符、TZ指示符UTC偏移量TZH:TZM/地区名称TZR和星期几DY。

我知道您得到的字符串以多种格式表示日期。您的目标是将这些字符串转换为没有格式的日期吗?或者将输入字符串转换为也以特定格式表示日期的输出字符串?字符串中是否有多个日期?或具有不同格式日期的多个字符串?将这些输入字符串转换为在日期列中以MM/DD/YYYY格式表示日期的输出字符串。源列是一个VARCHAR240,目标字段是一个日期字段。是否有有用的信息可以告诉您行将采用哪种格式,或者您需要猜测?另外,您希望如何处理时区信息?例如,您希望在“Thu Feb 02 20:49:59 MSK 2012”中插入什么内容?2012年2月2日?或者它是否需要先转换为特定的时区(例如UTC)?我知道您会得到以多种格式表示日期的字符串。您的目标是将这些字符串转换为没有格式的日期吗?或者将输入字符串转换为也以特定格式表示日期的输出字符串?字符串中是否有多个日期?或具有不同格式日期的多个字符串?将这些输入字符串转换为在日期列中以MM/DD/YYYY格式表示日期的输出字符串。源列是一个VARCHAR240,目标字段是一个日期字段。是否有有用的信息可以告诉您行将采用哪种格式,或者您需要猜测?另外,您希望如何处理时区信息?例如,您希望在“Thu Feb 02 20:49:59 MSK 2012”中插入什么内容?2012年2月2日?还是需要先将其转换为特定的时区(例如UTC)?一旦获得时间戳,您就可以更改时区、截断时间分量、将其格式化为字符串等。非常感谢您的回复!这正是我需要它做的。我只需要添加一些regexp_,就像在这种情况下一样
s因为我发现在install_date列中填充了[[todaysDate]]和'now'的值。哈哈,我已经用改进的时区区域查找更新了上述查询。现在,它获取与给定时区缩写相关联的最常见时区偏移量的第一个区域名称。例如,它不返回“Europe/Chisinau”,而返回“Europe/Moscow”作为“MSK”MSK'在偏移量+03:00时出现11次,但在偏移量+04:00时仅出现两次。这仍然只是一个最佳猜测,但它避免了ORA-01857:无效时区和/或ORA-01882:未找到时区区域在未转换时遇到的错误。这要感谢Marmite Bomber对其答案的评论。一旦你得到了时间戳,你就可以更改时区、截断时间成分、将其格式化为字符串等。非常感谢你的回复!这正是我需要它做的。我只需要添加几个类似于when的regexp,因为我发现在install_date列中填充了[[todaysDate]]和'now'的值。哈哈,我已经用改进的时区区域查找更新了上述查询。现在,它获取与给定时区缩写相关联的最常见时区偏移量的第一个区域名称。例如,它不返回“Europe/Chisinau”,而返回“Europe/Moscow”作为“MSK”MSK'在偏移量+03:00时出现11次,但在偏移量+04:00时仅出现两次。这仍然只是一个最佳猜测,但它避免了ORA-01857:无效时区和/或ORA-01882:未找到时区区域在未转换时遇到的错误。这要感谢Marmite Bomber对其答案的评论。同样感谢Marmite的帮助回答。我试图实现Sentinel的解决方案,但可能会发现将转换添加到函数中更有用。应该能够选择两个回答作为答案,但无论如何,感谢您的帮助@ryan45366不客气!没问题,我也受到了@Sentinel解决方案的启发。但请查看我对缩短时区转换的评论。服用mintzname可能会导致与服用相同的其他结果maxtzname@ryan45366,我认为函数是一个更好的解决方案。更持久,更容易在查询中重用。感谢您的帮助以及Marmite的回答。我试图实现Sentinel的解决方案,但可能会发现将转换添加到函数中更有用。应该能够选择两个回答作为答案,但无论如何,感谢您的帮助@ryan45366不客气!没问题,我也受到了@Sentinel解决方案的启发。但请查看我对缩短时区转换的评论。服用mintzname可能会导致与服用相同的其他结果maxtzname@ryan45366,我认为函数是一个更好的解决方案。更持久,更容易在查询中重用。