web-dev-qa-db-fra.com

Conversion du type de données d'horodatage en horodatage Unix Oracle

J'ai un type de données d'horodatage dans la base de données au format 24-JuL-11 10.45.00.000000000 AM et je veux le convertir en un horodatage Unix, comment puis-je l'obtenir?

7
deepti

Cette question est à peu près l'inverse de Convertir Unixtime en Datetime SQL (Oracle)

Comme le dit Justin Cave:

Il n'y a pas de fonctions intégrées. Mais c'est relativement facile d'en écrire un. Depuis un timestamp Unix est le nombre de secondes depuis le 1er janvier 1970

Étant donné que le fait de supprimer deux dates l'une de l'autre entraîne le nombre de jours entre elles, vous pouvez effectuer les opérations suivantes:

create or replace function date_to_unix_ts( PDate in date ) return number is

   l_unix_ts number;

begin

   l_unix_ts := ( PDate - date '1970-01-01' ) * 60 * 60 * 24;
   return l_unix_ts;

end;

Comme en secondes depuis 1970, le nombre de fractions de secondes est sans importance. Vous pouvez toujours l'appeler avec un type de données d'horodatage si ...

SQL> select date_to_unix_ts(systimestamp) from dual;

DATE_TO_UNIX_TS(SYSTIMESTAMP)
-----------------------------
                   1345801660

En réponse à votre commentaire, je suis désolé mais je ne vois pas ce comportement:

SQL> with the_dates as (
  2    select to_date('08-mar-12 01:00:00 am', 'dd-mon-yy hh:mi:ss am') as dt
  3      from dual
  4     union all
  5    select to_date('08-mar-12', 'dd-mon-yy')
  6      from dual )
  7  select date_to_unix_ts(dt)
  8    from the_dates
  9         ;

DATE_TO_UNIX_TS(DT)
-------------------
         1331168400
         1331164800

SQL>

Il y a une différence de 3 600 secondes, soit 1 heure.

17
Ben

Je me rends compte qu'une réponse a déjà été acceptée, mais je pense qu'il convient de préciser que la fonction dans cette réponse ne prend pas en compte le décalage du décalage de fuseau horaire indiqué. Un horodatage Unix approprié doit être calculé à GMT (+0). La fonction to_date d'Oracle suppose que la date indiquée est dans le fuseau horaire local, sauf indication contraire. Ce problème est exacerbé par le fait que l'heure avancée est une réalité. Je suis venu ce problème avec la fonction suivante:

create or replace
  function unix_time_from_date
      (
        in_date   in date,
        in_src_tz in varchar2 default 'America/New_York'
      )
    return integer
  as
    ut      integer       := 0;
    tz      varchar2(8)   := '';
    tz_date timestamp with time zone;
    tz_stmt varchar2(255);
  begin
    /**
     * This function is used to convert an Oracle DATE (local timezone) to a Unix timestamp (UTC).
     *
     * @author James Sumners
     * @date 01 February 2012
     *
     * @param in_date An Oracle DATE to convert. It is assumed that this date will be in the local timezone.
     * @param in_src_tz Indicates the time zone of the in_date parameter.
     *
     * @return integer
     */

    -- Get the current timezone abbreviation (stupid DST)
    tz_stmt := 'select systimestamp at time zone ''' || in_src_tz || ''' from dual';
    execute immediate tz_stmt into tz_date;
    select
      extract(timezone_abbr from tz_date)
    into tz
    from dual;

    -- Get the Unix timestamp
    select
      (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (86400)
    into ut
    from dual;

    return ut;
end unix_time_from_date;

J'ai quelques fonctions complémentaires, unix_time et unix_time_to_date, disponibles à l'adresse http://jrfom.com/2012/02/10/Oracle-and-unix-timestamps-revisited/ . Je ne peux pas croire qu'Oracle ait réussi jusqu'à 11g sans les mettre en œuvre.

11
James Sumners

J'utilise la méthode suivante, qui diffère un peu des autres réponses en ce qu'elle utilise la fonction sessiontimezone() pour obtenir correctement la date

    select
    ( 
      cast((FROM_TZ(CAST(in_date as timestamp), sessiontimezone) at time zone 'GMT') as date) -- in_date cast do GMT
      - 
      TO_DATE('01.01.1970','dd.mm.yyyy') -- minus unix start date
    )
    * 86400000 -- times miliseconds in day
    from dual;
1
dpedro

pour date:

   FUNCTION date_to_unix (p_date  date,in_src_tz in varchar2 default 'Europe/Kiev') return number is
begin
    return  round((cast((FROM_TZ(CAST(p_date as timestamp), in_src_tz) at time zone 'GMT') as date)-TO_DATE('01.01.1970','dd.mm.yyyy'))*(24*60*60));
end;

pour l'horodatage:

FUNCTION timestamp_to_unix (p_time  timestamp,in_src_tz in varchar2 default 'Europe/Kiev') return number is
    begin
        return  round((cast((FROM_TZ(p_time, in_src_tz) at time zone 'GMT') as date)-TO_DATE('01.01.1970','dd.mm.yyyy'))*(24*60*60));
    end;
1
Andre Kirpitch

J'utilise ces fonctions pour la conversion entre l'heure Oracle et l'heure Unix. Ils considèrent votre fuseau horaire actuel. Vous devez également ajouter le mot clé DETERMINISTIC, par exemple si vous souhaitez utiliser cette fonction dans un index basé sur une fonction. La conversion entre DATE et TIMESTAMP doit être effectuée implicitement par Oracle.

FUNCTION Timestamp2UnixTime(theTimestamp IN TIMESTAMP, timezone IN VARCHAR2 DEFAULT SESSIONTIMEZONE) RETURN NUMBER DETERMINISTIC IS
    timestampUTC TIMESTAMP;
    theInterval INTERVAL DAY(9) TO SECOND;
    epoche NUMBER;
BEGIN
    timestampUTC := FROM_TZ(theTimestamp, timezone) AT TIME ZONE 'UTC';
    theInterval := TO_DSINTERVAL(timestampUTC - TIMESTAMP '1970-01-01 00:00:00');
    epoche := EXTRACT(DAY FROM theInterval)*24*60*60 
        + EXTRACT(HOUR FROM theInterval)*60*60 
        + EXTRACT(MINUTE FROM theInterval)*60 
        + EXTRACT(SECOND FROM theInterval);
    RETURN ROUND(1000*epoche);
END Timestamp2UnixTime;



FUNCTION UnixTime2Timestamp(UnixTime IN NUMBER) RETURN TIMESTAMP DETERMINISTIC IS
BEGIN
    RETURN (TIMESTAMP '1970-01-01 00:00:00 UTC' + UnixTime/1000 * INTERVAL '1' SECOND) AT LOCAL;
END UnixTime2Timestamp;
0
SELECT (SYSDATE - TO_DATE('01-01-1970 00:00:00', 'DD-MM-YYYY HH24:MI:SS')) * 24 * 60 * 60 * 1000 FROM DUAL
0
Piotr R

C'est ce que je suis venu avec:

select    substr(extract(day from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 24 * 60 * 60 + 
          extract(hour from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 60 * 60 + 
          extract(minute from (n.origstamp - timestamp '1970-01-01 00:00:00')) * 60 + 
          trunc(extract(second from (n.origstamp - timestamp '1970-01-01 00:00:00')),0),0,15) TimeStamp 
          from tablename;

FWIW

0
rogerdpack