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?
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.
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.
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;
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;
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;
SELECT (SYSDATE - TO_DATE('01-01-1970 00:00:00', 'DD-MM-YYYY HH24:MI:SS')) * 24 * 60 * 60 * 1000 FROM DUAL
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