Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ULID in Oracle #52

Open
Sethionic opened this issue Aug 20, 2020 · 1 comment
Open

ULID in Oracle #52

Sethionic opened this issue Aug 20, 2020 · 1 comment

Comments

@Sethionic
Copy link

Sethionic commented Aug 20, 2020

If anyone wants to implement the ULID spec in Oracle, here's a start:
Extracting timestamp from ULID in PL/SQL

    p_Ulid VARCHAR2(200) := '01EG664DVCY5NTH7WFN57PA7TM';
    FUNCTION Get_Ulid_Ts(p_In VARCHAR2) RETURN TIMESTAMP
        WITH TIME ZONE IS
        Dec_Value   NUMBER := 0;
        t_Time_Part VARCHAR2(10) := Substr(p_In, 0, 10); --First 10 characters are the timestamp
        Ret         TIMESTAMP WITH TIME ZONE := To_Timestamp_Tz('19700101 +00:00', 'yyyymmdd TZH:TZM');
        c_Base      NUMBER := 32;
        c_Base32    VARCHAR2(32) := '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; --Crockford's base32
        TYPE B32_Map_Typ IS TABLE OF NUMBER INDEX BY VARCHAR2(1);
        B32map B32_Map_Typ;
    BEGIN
        --initialize base32 map
        FOR i IN 0 .. Length(c_Base32) - 1
        LOOP
            B32map(Substr(c_Base32, i + 1, 1)) := i;
        END LOOP;
        --convert base 32 to base 10
        FOR i IN 1 .. Length(t_Time_Part)
        LOOP
            Dec_Value := Dec_Value +
                         Power(c_Base, i - 1) *
                         B32map(Substr(t_Time_Part, -i, 1));
        END LOOP;
        --add to unix timestamp sentinal
        Ret := Ret +numtodsinterval(((Dec_Value/ 1000) ),'SECOND') ;
        RETURN Ret;
    END;
BEGIN
    --ISO8601 timestamp formats
    EXECUTE IMMEDIATE q'!alter session set nls_timestamp_format = 'YYYY-MM-DD"T"HH24:MI:SS.ff3"Z"' !';
    EXECUTE IMMEDIATE q'!alter session set nls_timestamp_tz_format = 'YYYY-MM-DD"T"HH24:MI:SS.ff3 TZR' !';
    --test function
    Dbms_Output.Put_Line(Get_Ulid_Ts(p_Ulid));
    Dbms_Output.Put_Line(Get_Ulid_Ts(p_Ulid) At TIME ZONE
                         'America/New_York');
END;
/
@Sethionic
Copy link
Author

Here's the same with a reverse
https://github.com/Sethionic/oracle-ulid

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant