<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><category>pcsoft.br.windev</category><copyright>Copyright 2026, PC SOFT</copyright><lastBuildDate>12 Apr 2026 15:11:30 Z</lastBuildDate><pubDate>12 Apr 2026 15:11:30 Z</pubDate><description>PROCEDURE Get_uuidV7()&#13;
&#13;
b6,b7,b8,b9					are 8-byte int&#13;
b10,b11,b12,b13,b14,b15		are 8-byte int&#13;
sHex						is string&#13;
sUUID						is string&#13;
&#13;
// ── 1. TIMESTAMP em milissegundos ─────────────────────────────────────────&#13;
nTsMs						is 8-byte int	= Round(Val(DateSys() + TimeSys()) * 1000)&#13;
&#13;
// ── 2. DECOMPOR EM 6 BYTES (shift = divisão inteira, mask = MOD) ──────────&#13;
Abs							is 8-byte int	= (nTsMs / 1099511627776) modulo 256	// bits 47..40  (2^40)&#13;
b1							is 8-byte int	= (nTsMs / 4294967296)    modulo 256	// bits 39..32  (2^32)&#13;
b2							is 8-byte int	= (nTsMs / 16777216)      modulo 256	// bits 31..24  (2^24)&#13;
b3							is 8-byte int	= (nTsMs / 65536)         modulo 256	// bits 23..16  (2^16)&#13;
b4							is 8-byte int	= (nTsMs / 256)           modulo 256	// bits 15..8   (2^8)&#13;
b5							is 8-byte int	=  nTsMs                  modulo 256	// bits 7..0&#13;
&#13;
// ── 3. ALEATORIEDADE ──────────────────────────────────────────────────────&#13;
nRandA						is 8-byte int	= Random(0, 4095)						// 12 bits — rand_a&#13;
nW1							is 8-byte int	= Random(0, 65535)						// 16 bits — rand_b chunk 1&#13;
nW2							is 8-byte int	= Random(0, 65535)						// 16 bits — rand_b chunk 2&#13;
nW3							is 8-byte int	= Random(0, 65535)						// 16 bits — rand_b chunk 3&#13;
nW4							is 8-byte int	= Random(0, 65535)						// 16 bits — rand_b chunk 4&#13;
&#13;
// ── 4. MONTAR BYTES VERSION + VARIANT ────────────────────────────────────&#13;
// Byte 6 : 0111 xxxx  → 0x70 + nibble alto de rand_a&#13;
//          bits não se sobrepõem → soma pura&#13;
b6		= 0x70 + ((nRandA / 256) modulo 16)&#13;
b7		= nRandA modulo 256&#13;
&#13;
// Byte 8 : 10xx xxxx  → 0x80 + 6 bits altos de nW1&#13;
b8		= 0x80 + ((nW1 / 256) modulo 64)&#13;
b9		= nW1 modulo 256&#13;
&#13;
// Bytes 10–15 : rand_b puro&#13;
b10		= (nW2 / 256) modulo 256&#13;
b11		=  nW2 modulo 256&#13;
b12		= (nW3 / 256) modulo 256&#13;
b13		=  nW3 modulo 256&#13;
b14		= (nW4 / 256) modulo 256&#13;
b15		=  nW4 modulo 256&#13;
&#13;
// ── 5. CONVERTER PARA HEX ────────────────────────────────────────────────&#13;
sHex	= prv_Hex2("b0")  + prv_Hex2(b1)  + prv_Hex2(b2)  + prv_Hex2(b3)  +&#13;
prv_Hex2(b4)  + prv_Hex2(b5)  + prv_Hex2(b6)  + prv_Hex2(b7)  +&#13;
prv_Hex2(b8)  + prv_Hex2(b9)  + prv_Hex2(b10) + prv_Hex2(b11) +&#13;
prv_Hex2(b12) + prv_Hex2(b13) + prv_Hex2(b14) + prv_Hex2(b15)&#13;
&#13;
sHex	= Lower(sHex)&#13;
&#13;
// ── 6. INSERIR HÍFENS — padrão 8-4-4-4-12 ───────────────────────────────&#13;
sUUID	= Left(sHex, 8)        + "-" +&#13;
Middle(sHex,  9, 4)  + "-" +&#13;
Middle(sHex, 13, 4)  + "-" +&#13;
Middle(sHex, 17, 4)  + "-" +Right(sHex, 12)&#13;
&#13;
&#13;
RESULT sUUID&#13;
&#13;
	INTERNAL PROCEDURE prv_Hex2(nByte is 8-byte int) : string&#13;
&#13;
		s is string = NumToHex(nByte)&#13;
&#13;
		IF Length(s) &lt; 2 THEN&#13;
			s = "0" + s&#13;
		END&#13;
&#13;
		RESULT s&#13;
&#13;
	END&#13;
&#13;
	INTERNAL PROCEDURE NumToHex(nByte is 8-byte int)&#13;
&#13;
		sTab is string = "0123456789abcdef"&#13;
		nHi  is 8-byte int    = (nByte / 16) + 1   // nibble alto → posição 1..16&#13;
		nLo  is 8-byte int    = (nByte modulo 16) + 1  // nibble baixo → posição 1..16&#13;
&#13;
		RESULT Middle(sTab, nHi, 1) + Middle(sTab, nLo, 1)&#13;
&#13;
	END&#13;
&#13;
&#13;
&#13;
&#13;
&#13;
&#13;
&#13;
// Explicação &#13;
&#13;
## Explicação do código UUID v7 para um júnior&#13;
&#13;
---&#13;
&#13;
### O que é um UUID v7?&#13;
&#13;
É um identificador único universal de **128 bits** (32 caracteres hex + 4 hífens). A versão 7 é especial porque começa com o **horário atual**, então registros mais novos sempre ficam em ordem crescente no banco — ótimo para performance em índices.&#13;
&#13;
```&#13;
01965fe8-3a10-7xxx-yxxx-xxxxxxxxxxxx&#13;
|___________|       |    |__________|&#13;
  timestamp        ver     aleatório&#13;
```&#13;
&#13;
---&#13;
&#13;
### Bloco 1 — Capturar o tempo atual em milissegundos&#13;
&#13;
```wlanguage&#13;
nTsMs is 8-byte int = Round(Val(DateSys() + TimeSys()) * 1000)&#13;
```&#13;
&#13;
| Passo | O que faz |&#13;
|---|---|&#13;
| `DateSys()` | Retorna data atual como string `"20240412"` |&#13;
| `TimeSys()` | Retorna hora atual como string `"143022"` |&#13;
| `DateSys() + TimeSys()` | Concatena → `"20240412143022"` |&#13;
| `Val(...)` | Converte string para número |&#13;
| `* 1000` | Transforma segundos → milissegundos |&#13;
| `Round(...)` | Remove decimais |&#13;
&#13;
&gt; O resultado é um número enorme, tipo `1713000000000`. Isso é a "idade" do universo em milissegundos desde 1970. 😄&#13;
&#13;
---&#13;
&#13;
### Bloco 2 — Fatiar o timestamp em 6 bytes&#13;
&#13;
Um byte comporta valores de **0 a 255**. O timestamp tem 48 bits = 6 bytes. Precisamos fatiá-lo:&#13;
&#13;
```wlanguage&#13;
b0 = (nTsMs / 1099511627776) modulo 256   // byte mais significativo&#13;
b1 = (nTsMs / 4294967296)    modulo 256&#13;
b2 = (nTsMs / 16777216)      modulo 256&#13;
b3 = (nTsMs / 65536)         modulo 256&#13;
b4 = (nTsMs / 256)           modulo 256&#13;
b5 =  nTsMs                  modulo 256   // byte menos significativo&#13;
```&#13;
&#13;
**Analogia:** imagine o número `1234`. Para extrair cada dígito:&#13;
- Centena: `1234 / 100 = 12`, depois `12 modulo 10 = 2` ✅&#13;
- Dezena: `1234 / 10 = 123`, depois `123 modulo 10 = 3` ✅&#13;
&#13;
Aqui fazemos a mesma coisa, mas com base 256 (1 byte) em vez de base 10.&#13;
&#13;
Os divisores são potências de 2:&#13;
&#13;
```&#13;
1099511627776 = 2^40&#13;
4294967296    = 2^32&#13;
16777216      = 2^24&#13;
65536         = 2^16&#13;
256           = 2^8&#13;
```&#13;
&#13;
---&#13;
&#13;
### Bloco 3 — Gerar aleatoriedade&#13;
&#13;
```wlanguage&#13;
nRandA = Random(0, 4095)    // 12 bits  → 2^12 = 4096 possibilidades&#13;
nW1    = Random(0, 65535)   // 16 bits  → 2^16 = 65536 possibilidades&#13;
nW2    = Random(0, 65535)&#13;
nW3    = Random(0, 65535)&#13;
nW4    = Random(0, 65535)&#13;
```&#13;
&#13;
Dois UUIDs gerados **no mesmo milissegundo** serão diferentes por causa desta parte aleatória.&#13;
&#13;
---&#13;
&#13;
### Bloco 4 — Aplicar version e variant (regra do RFC 9562)&#13;
&#13;
O padrão exige que bytes específicos carreguem bits fixos para identificar "isso é um UUID v7":&#13;
&#13;
```wlanguage&#13;
// Byte 6: deve começar com 0111 em binário = 0x70 = 112 decimal&#13;
b6 = 112 + ((nRandA / 256) modulo 16)&#13;
```&#13;
&#13;
**Por que soma e não OR?** Porque `112` ocupa os 4 bits altos e `modulo 16` garante que o valor cabe nos 4 bits baixos — eles **nunca se sobrepõem**, então soma = OR neste caso.&#13;
&#13;
```&#13;
112  em binário = 0111 0000&#13;
modulo 16 max   = 0000 1111&#13;
                  ---------&#13;
soma            = 0111 xxxx  ✅ versão 7 gravada&#13;
```&#13;
&#13;
```wlanguage&#13;
// Byte 8: deve começar com 10 em binário = 0x80 = 128 decimal&#13;
b8 = 128 + ((nW1 / 256) modulo 64)&#13;
```&#13;
&#13;
```&#13;
128  em binário = 1000 0000&#13;
modulo 64 max   = 00xx xxxx&#13;
                  ---------&#13;
soma            = 10xx xxxx  ✅ variant RFC gravado&#13;
```&#13;
&#13;
---&#13;
&#13;
### Bloco 5 — Converter cada byte para 2 caracteres hex&#13;
&#13;
```wlanguage&#13;
INTERNAL PROCEDURE NumToHex(nByte is 8-byte int)&#13;
    sTab is string = "0123456789abcdef"&#13;
    nHi  = (nByte / 16) + 1    // nibble alto&#13;
    nLo  = (nByte modulo 16) + 1  // nibble baixo&#13;
    RESULT Middle(sTab, nHi, 1) + Middle(sTab, nLo, 1)&#13;
END&#13;
```&#13;
&#13;
**Analogia direta:** converter `255` para `"ff"`:&#13;
```&#13;
255 / 16 = 15  → posição 16 na tabela → "f"&#13;
255 mod 16 = 15 → posição 16 na tabela → "f"&#13;
resultado = "ff" ✅&#13;
```&#13;
&#13;
A tabela `"0123456789abcdef"` funciona como um array onde a posição 1 = `"0"`, posição 11 = `"a"`, posição 16 = `"f"`.&#13;
&#13;
---&#13;
&#13;
### Bloco 6 — Montar a string final com hífens&#13;
&#13;
```wlanguage&#13;
sUUID = Left(sHex, 8)       + "-" +   // 8 chars  → timestamp parte 1&#13;
        Middle(sHex, 9, 4)  + "-" +   // 4 chars  → timestamp parte 2&#13;
        Middle(sHex, 13, 4) + "-" +   // 4 chars  → version + rand_a&#13;
        Middle(sHex, 17, 4) + "-" +   // 4 chars  → variant + rand_b&#13;
        Right(sHex, 12)               // 12 chars → rand_b restante&#13;
```&#13;
&#13;
`sHex` tem 32 chars → com hífens fica o formato canônico `8-4-4-4-12`.&#13;
&#13;
---&#13;
&#13;
### Dois bugs no código atual ⚠️&#13;
&#13;
```wlanguage&#13;
// BUG 1: "Abs" é palavra reservada do WinDev!&#13;
Abs is 8-byte int = (nTsMs / 1099511627776) modulo 256&#13;
// CORRETO:&#13;
b0  is 8-byte int = (nTsMs / 1099511627776) modulo 256&#13;
&#13;
// BUG 2: "b0" entre aspas → passa a STRING, não a variável!&#13;
sHex = prv_Hex2("b0") + ...&#13;
// CORRETO:&#13;
sHex = prv_Hex2(b0) + ...&#13;
```&#13;
&#13;
---&#13;
&#13;
### Resumo visual do fluxo&#13;
&#13;
```&#13;
DateSys()+TimeSys()&#13;
        │&#13;
        ▼&#13;
   nTsMs (ms)          Random()×4&#13;
        │                   │&#13;
        ▼                   ▼&#13;
  6 bytes (b0..b5)    rand_a + nW1..nW4&#13;
        │                   │&#13;
        └────────┬───────────┘&#13;
                 ▼&#13;
         16 bytes totais&#13;
         + version 0x70&#13;
         + variant 0x80&#13;
                 │&#13;
                 ▼&#13;
          32 chars hex&#13;
                 │&#13;
                 ▼&#13;
    xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx&#13;
```</description><ttl>30</ttl><generator>WEBDEV</generator><language>pt_BR</language><link>https://forum.pcsoft.fr/fr-FR/pcsoft.br.windev/5380-contribuicao-exemplo-uuid/read.awp</link><title>Contribuição Exemplo uuid V7</title><managingEditor>moderateur@pcsoft.fr (Le modérateur)</managingEditor><webMaster>webmaster@pcsoft.fr (Le Webmaster)</webMaster></channel></rss>
