Cast or extract timestamptz from v1 uuid in postgresql

北城以北 提交于 2019-12-10 02:26:39

问题


I'm trying to extract the timestamp from a V1 uuid, naively wished this worked:

select '3efe0a20-f1b3-11e3-bb44-14109fec739e'::uuid::timestamp;

Here is a quick example showing how to extract the time in go, but I'm hoping postgresql has something built-in rather than creating a one-off pl/pgSql function. http://play.golang.org/p/XRCooLgfaG


回答1:


I've tested this with uuid's from my database and it seems to work very well, even without the unsigned bigints

CREATE FUNCTION uuid_timestamp(id uuid) RETURNS timestamptz AS $$
  select TIMESTAMP WITH TIME ZONE 'epoch' +
      (((('x' || lpad(split_part(id::text, '-', 1), 16, '0'))::bit(64)::bigint) +
      (('x' || lpad(split_part(id::text, '-', 2), 16, '0'))::bit(64)::bigint << 32) +
      ((('x' || lpad(split_part(id::text, '-', 3), 16, '0'))::bit(64)::bigint&4095) << 48) - 122192928000000000) / 10000000 ) * INTERVAL '1 second';    
$$ LANGUAGE SQL
  IMMUTABLE
  RETURNS NULL ON NULL INPUT;

a V1 uuid I created in the 2099 future!

select uuid_timestamp('6d248400-65b7-1243-a57a-14109fec739e');
uuid_timestamp     
------------------------
 2099-08-01 11:30:00-07
(1 row)



回答2:


Here is a rough pl/pgsql implementation which cast (timestamp, clock_seq, macaddr) into a version 1 uuid.

-- Build UUIDv1 via RFC 4122. 
-- clock_seq is a random 14bit unsigned int with range [0,16384)
CREATE OR REPLACE FUNCTION form_uuid_v1(ts TIMESTAMPTZ, clock_seq INTEGER, mac MACADDR)
  RETURNS UUID AS $$
DECLARE
  t       BIT(60) := (extract(EPOCH FROM ts) * 10000000 + 122192928000000000) :: BIGINT :: BIT(60);
  uuid_hi BIT(64) := substring(t FROM 29 FOR 32) || substring(t FROM 13 FOR 16) || b'0001' ||
                     substring(t FROM 1 FOR 12);
BEGIN
  RETURN lpad(to_hex(uuid_hi :: BIGINT) :: TEXT, 16, '0') ||
         (to_hex((b'10' || clock_seq :: BIT(14)) :: BIT(16) :: INTEGER)) :: TEXT ||
         replace(mac :: TEXT, ':', '');
END
$$ LANGUAGE plpgsql;

-- Usage
select form_uuid_v1(now(), 666, '44:88:AA:DD:BB:88');


来源:https://stackoverflow.com/questions/24178485/cast-or-extract-timestamptz-from-v1-uuid-in-postgresql

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!