Help us shape the future of Go! Take the 2026 Go Developer Survey

br

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 26, 2026 License: MIT Imports: 11 Imported by: 0

README

Arandu

Arandu BR

The Brazilian values an Arandu application takes from a form and prints on a page: the CPF, the CNPJ (numeric and alphanumeric), the CEP, the telephone numbers, the documents with check digits (NIS, CNS, CNH, RENAVAM, título de eleitor, certidão, the state registration), the vehicle plate, an amount in reais, a date, and the federative unit — and a CPF or a CNPJ with part of it hidden.

It is a library. It registers no route, owns no table and decides no authorization, so there is nothing to construct and no aru migrate to run. An application imports it, calls it, and hands its validation rules to the Factory with one call, factory.Use(br.Rules()), where it is wired in bootstrap/app.go.

Install

go get github.com/hyz-is/arandu-br
import br "github.com/hyz-is/arandu-br"

The module requires Hesape and nothing else. arandu.mod.toml declares no capability: no network, no filesystem, no process, no migration.

Validate a form

The rules are a validation.Provider, br.Rules(), that the application hands to the Factory it builds, once, where it is wired. Nothing is registered before that call:

validators := validation.NewFactory(validation.FromTranslation(tr))
validators.Use(br.Rules())

var StoreCustomer = validation.MustCompile(validation.Rules{
	"cpf":      []any{"required", br.RuleCPF},
	"cnpj":     "nullable|" + br.RuleCNPJ,
	"document": "required|" + br.RuleCPFOrCNPJ,
	"postcode": "required|" + br.RuleCEPFormat,
	"phone":    "required|" + br.RuleMobile,
	"state":    "required|" + br.RuleStateRegistration + ":SP",
}, validation.WithModuleRules())

err := validators.Check(StoreCustomer) // at boot: names any rule nothing declares

Use declares every rule and alias, each as a validation.RuleDef with its pt-BR sentence, and a validation.<rule> line in the application's translations is read before that sentence. br.Defs() returns the declarations. A rule set compiled in a package-level variable runs before the Factory exists, so it is compiled with validation.WithModuleRules() and resolved by the Factory; a request type that declares Rules() needs neither.

The names are those of geekcom/validator-docs and laravellegends/pt-br-validator, so a rule set written for either reads the same, and the string form works: "required|cpf".

rule constant accepts
cpf br.RuleCPF a CPF, 00000000000 or 000.000.000-00
cnpj br.RuleCNPJ a CNPJ, numeric or alphanumeric, 00000000000000 or 00.000.000/0000-00
cpf_ou_cnpj (cpf_or_cnpj, cpf_cnpj) br.RuleCPFOrCNPJ either of the two
cep br.RuleCEP a CEP, 00000000 or 00000-000, not below 01000-000
formato_cpf, formato_cnpj, formato_cpf_ou_cnpj (formato_cpf_cnpj), formato_cep br.RuleCPFFormat, br.RuleCNPJFormat, br.RuleCPFOrCNPJFormat, br.RuleCEPFormat the punctuated shape alone, whatever the digits: 000.000.000-00, 00.000.000/0000-00, 00000-000 or 00.000-000
celular br.RuleLocalMobile a mobile number without the area code, 91234-5678 or 912345678
celular_com_ddd br.RuleMobile (11) 91234-5678, (11)91234-5678 or 11912345678, with a real area code
celular_com_codigo br.RuleMobileWithCountry +55(11)91234-5678, +55 (11) 91234-5678 or +5511912345678
celular_com_codigo_sem_mascara br.RuleMobileWithCountryBare +5511912345678 or +55 11 912345678
telefone, telefone_com_ddd, telefone_com_codigo br.RuleLocalLandline, br.RuleLandline, br.RuleLandlineWithCountry a landline number, 3000-0000, (11) 3000-0000, +55(11)3000-0000
telefone_ou_celular br.RuleAnyPhone a mobile or a landline number, with or without the area code: 91234-5678, 3456-7890, (11) 91234-5678, (11) 3456-7890, bare or punctuated
ddd br.RuleAreaCode one of the 67 area codes Anatel assigns
placa br.RulePlate any plate Brazil issued, the Mercosul one included, ABC-1234, ABC1D23
formato_placa_de_veiculo br.RulePlateFormat three letters, a hyphen or none, a digit, a digit or a letter, two digits
renavam br.RuleRenavam nine to eleven digits with the RENAVAM check digit
cnh br.RuleCNH the eleven digits of the register number, with the Denatran check digits
titulo_eleitor br.RuleVoterTitle the digits of a título de eleitor, five to thirteen, with its state and check digits
nis, pis br.RuleNIS, br.RulePIS 000.00000.00-0 or the eleven digits, with the check digit
formato_nis, formato_pis br.RuleNISFormat, br.RulePISFormat 000.00000.00-0, whatever the digits
cns br.RuleCNS the fifteen digits of the Cartão Nacional de Saúde, definitive or provisional
certidao, formato_certidao br.RuleCivilCertificate, br.RuleCivilCertificateFormat the thirty-two digits of a birth, marriage or death certificate, and their nine groups
uf br.RuleUF one of the 27 codes, in capitals
inscricao_estadual:UF br.RuleStateRegistration the state registration number of the unit, inscricao_estadual:SP
passaporte br.RulePassport two letters and six digits
data, horario br.RuleDate, br.RuleTimeOfDay 31/12/2026, a day the month has; 15:04 or 15:04:05
brl (moeda) br.RuleBRL an amount in reais, as ParseBRL reads it

Which telephone rule: a field of a mobile number with the area code takes celular_com_ddd; a field with a dynamic mask, mobile or landline, with or without the area code, takes telefone_ou_celular (Laravel's rules add up, so celular_com_ddd|telefone_com_ddd refuses everything); a field of a landline number takes telefone_com_ddd or telefone.

Each rule checks what the matching Parse function checks, and only a string: a CPF sent as a JSON number has already lost its leading zeros. A blank value is left to required or nullable. A rule written with an argument it does not take does not compile (cpf:strict; the eight names registered at import refuse every value instead), and inscricao_estadual takes exactly one, the code of a unit, in either case, and does not compile with another.

A failure reads as the PHP packages' sentences do, in Portuguese, with the attribute: O campo documento não é um CPF válido. An application names its own sentence under validation.cpf, validation.cnpj, validation.formato_cep and so on in its translations, which hesape/validation reads before the default; br.Messages("pt-BR") returns every default, by rule name, for an application that loads them into its language files.

Where it is narrower than the PHP packages

Both packages remove every character that is not a digit before checking. This package takes a value bare or in its one conventional punctuation, so a form never stores what the person did not type; trim or re-punctuate in the request if the form should forgive it. Beyond that, a value the PHP rules accept and these refuse:

rule refused here why
cpf, cnpj, nis, cns, titulo_eleitor and the rest 094 050 986 59, 094.050.986-59 only the bare or the one punctuated spelling
celular, celular_com_ddd 9800-1936, (31)9999-5555 an eight-digit number is not a mobile number since 2016; it is a telefone
celular_com_codigo, telefone_com_codigo +1(31)99999-5555, +66(31)9999-5555 the number is checked against Brazil's plan, so the code is +55
cns a definitive card that begins with 0 or 3 to 6 laravellegends computes it; a definitive card begins with 1 or 2
nis, pis a number shorter than eleven digits geekcom pads it with zeros; a leading zero is a digit
renavam 1970.73212, 00000000000 only digits; a repetition has no owner
inscricao_estadual 8 2__6-7*9.3/41, 00000000000 for MT only dots, hyphens and slashes between digits; a repetition has no owner
cnh — laravellegends' arithmetic lacks the Denatran's correction and refuses 1 valid number in 40; the correct one is used
placa — AAA12A3 passes placa (geekcom) and not formato_placa_de_veiculo (laravellegends)

Examples the PHP packages test with are rewritten as data in tests/Unit/rule_examples_test.go, and the ones refused here carry the reason.

The import-time registration is deprecated

Until v0.5.0 the package registered cpf, cnpj, cpf_or_cnpj, cep, celular and brl when it was imported. It still does, now with cpf_ou_cnpj and celular_com_ddd beside them, so a rule set that names them keeps compiling without a Factory. Use leaves those eight names to it. That registration goes in a later release; call factory.Use(br.Rules()). br.Install(factory) is that call under its old name, and is deprecated too.

celular means the number without the area code now, as in the PHP packages; what it was is celular_com_ddd. UPGRADE.md says what to search for.

Take a value in

cpf, err := br.ParseCPF(in.String("cpf"))    // eleven digits, bare
cnpj, err := br.ParseCNPJ(in.String("cnpj")) // fourteen characters, bare, letters in capitals
cep, err := br.ParseCEP(in.String("postcode"))

Each Parse function returns the bare spelling, which is the one to store, or ErrInvalidCPF, ErrInvalidCNPJ or ErrInvalidCEP. ValidCPF, ValidCNPJ and ValidCEP answer the same question with a bool.

What is accepted is deliberately narrow: the value bare, or in its one conventional punctuation, and nothing else. No other separator, no separator out of place, no whitespace around it — a form that trimmed or re-punctuated input would accept a value the person did not type.

  • CPF — the two check digits the Receita Federal computes. The eleven repetitions of one digit compute too and belong to nobody, so they are refused by name.
  • CNPJ — the alphanumeric scheme: twelve digits or capital letters, each worth its ASCII code minus 48, then two numeric check digits. The numeric CNPJ is the all-digit case and is checked by the same computation. A lower-case letter is read as its capital. Fourteen repetitions of one character are refused.
  • CEP — eight digits, and not below 01000-000, where the Correios ranges begin. There is no check digit, so a CEP that passes may still address nothing.

None of them says whether a document was issued, is regular or exists: that is a question for the Receita Federal or the Correios, and this package makes no call.

CPFCheckDigits and CNPJCheckDigits compute the check digits of a base, which is what a seeder or a factory needs to write a valid document without borrowing somebody's.

A CPF and a CNPJ are text, from the form to the column. A document read as a number has lost its leading zeros (00000000191 becomes 191), and the alphanumeric CNPJ cannot be a number at all. Declare the column text (or varchar), never an integer, and take the value with in.String. For text that already left the form, NormalizeCPF keeps the digits of a string and NormalizeCNPJ keeps the digits and the letters, in capitals, so a stored 12.abc.345/01de-35 compares with 12ABC34501DE35; neither validates, and ParseCPF and ParseCNPJ are what take a value in.

The other values follow the same shape, a Parse function that returns the bare spelling or an Err… and a Valid function beside it:

value function returns an error
mobile number with area code ParseMobile 11 digits ErrInvalidMobile
mobile number without it, or with +55 ParseLocalMobile, ParseMobileWithCountry 9 digits, 55 and 11 digits ErrInvalidMobile
landline ParseLandline, ParseLocalLandline, ParseLandlineWithCountry 10, 8, 55 and 10 digits ErrInvalidLandline
any telephone number ParseAnyPhone 8, 9, 10 or 11 digits ErrInvalidPhone
area code ParseAreaCode 2 digits ErrInvalidAreaCode
NIS, PIS ParseNIS 11 digits ErrInvalidNIS
Cartão Nacional de Saúde ParseCNS 15 digits ErrInvalidCNS
CNH ParseCNH 11 digits ErrInvalidCNH
RENAVAM ParseRenavam 11 digits, the zeros of an older number put back ErrInvalidRenavam
título de eleitor ParseVoterTitle its digits ErrInvalidVoterTitle
certidão ParseCivilCertificate 32 digits ErrInvalidCivilCertificate
vehicle plate ParsePlate in capitals, no hyphen ErrInvalidPlate
passport ParsePassport in capitals ErrInvalidPassport
inscrição estadual ParseStateRegistration(uf, s) its digits ErrInvalidStateRegistration
day, time of day ParseDate, ParseTimeOfDay time.Time at midnight UTC, time.Duration since midnight ErrInvalidDate, ErrInvalidTimeOfDay

NIS, CNS and Landline punctuate a stored value like CPF, and FormatPhone picks the mask of a telephone number by its digits (8, 9, 10 or 11). NormalizePhone keeps the digits of text that already left the form.

An amount in reais
cents, err := br.ParseBRL(in.String("budget")) // int64 centavos, or ErrInvalidBRL

ParseBRL reads an amount as a person types it, and as an HTML number input submits it:

typed centavos
R$ 1.234,56, R$1.234,56, 1.234,56, 1234,56 123456
1.500 150000 — a dot followed by three digits groups thousands
1234.56, 1,5, 1.5 123456, 150, 150 — a dot followed by one or two digits is the decimal point
R$ 47, 0 4700, 0

Whitespace around the amount and after R$ is ignored. A sign, another currency, a space or a dot elsewhere among the digits, a group of other than three digits, a third decimal and an amount past the largest int64 are refused. Zero is an amount; a form that needs a positive one says so itself. A number input that takes centavos carries step="0.01", which keeps a third decimal — 1.500 meaning one and a half — out of what it submits.

Print a value

br.CPF("11122233344")      // "111.222.333-44", check digits or not
br.CNPJ("12abc34501de35")  // "12.ABC.345/01DE-35"
br.CEP("70040010")         // "70040-010"
br.BRL(123456)             // "R$ 1.234,56"
br.BRL(-99)                // "-R$ 0,99"
br.Date(t.In(saoPaulo))    // "31/12/2026"
br.DateTime(t.In(saoPaulo)) // "31/12/2026 15:04"

br.FormatBRL(123456, br.BRLFormat{WithoutGrouping: true}) // "R$ 1234,56"
br.FormatBRL(4700, br.BRLFormat{WithoutZeroCents: true})  // "R$ 47"
br.FormatBRL(19950, br.BRLFormat{WithoutZeroCents: true}) // "R$ 199,50"
br.FormatBRL(123456, br.BRLFormat{WithoutSymbol: true, WithoutGrouping: true}) // "1234,56", for a form field

br.BRLDecimal("1234.5678") // "R$ 1.234,5678", every digit kept

CPF, CNPJ and CEP punctuate a value of the right shape and return anything else unchanged: they format and do not validate, so a page that prints a stored value shows what is stored.

BRL takes centavos as an int64 — an amount that has to add up is held as an integer — and writes every one, the most negative included. It writes the same string as number.CurrencyFromCents(cents, "BRL") with the process-wide locale set to pt-BR, and depends on no process-wide setting.

FormatBRL is BRL departing from it in what its BRLFormat names, and the zero BRLFormat is BRL itself. Every amount it prints, ParseBRL reads back -- WithoutSymbol is how a form field is filled with an amount it hands back.

BRLDecimal writes an amount finer than a centavo -- a price per unit of usage, the exact total a charge was rounded from -- held as decimal text, the way math/big and a decimal column write it: the digits of the reais, then a dot and every digit of the fraction. Nothing is rounded, and a value that is not a decimal is returned unchanged.

Date writes the day t holds in its own location, and DateTime the day and the time of day, 31/12/2026 15:04. A time read from the database is usually in UTC, where a late evening in Brasília is already the next day, so convert it with t.In(location) first.

Hide part of a document

br.RedactCPF("12345678900", br.KeepCPFMiddle)      // "***.456.789-**"
br.RedactCPF("123.456.789-00", br.KeepCPFLastFive) // "***.***.789-00"
br.RedactCPF("12345678900", "•••.###.###-••")      // "•••.456.789-••"
br.RedactCNPJ("12ABC34501DE35", br.KeepCNPJEnds)   // "12.***.***/****-35"

A Redaction is spelled like the document: # shows the character in that position and every other character is written as it stands, the separators included. It has the length of the punctuated spelling or of the bare one, and the output takes that spelling.

redaction pattern prints
br.KeepCPFMiddle ***.###.###-** as the Portal da Transparência publishes a CPF
br.KeepCPFMiddleBare ***######** as the Receita Federal's open CNPJ data publishes a partner's CPF
br.KeepCPFCheckDigits ***.***.***-## only the two check digits, which identify nobody
br.KeepCPFLastFive ***.***.###-## what a profile page shows its owner
br.KeepCNPJEnds ##.***.***/****-## the first two and the last two characters

RedactCPF and RedactCNPJ read the value as ParseCPF and ParseCNPJ do, bare or punctuated, and do not check the check digits. Anything else — and a redaction of neither length — gives "", never the value: a redaction that fell back to its input would print what it exists to hide.

The federative units

br.UF is the closed set of the twenty-seven units, shaped like an enum aru make:enum writes:

br.UFSP.String()  // "SP"
br.UFSP.Label()   // "São Paulo"
uf, err := br.ParseUF(in.String("uf")) // exact code, in capitals, or ErrInvalidUF

br.UFValues() lists them in the alphabetical order of their names. The type satisfies enum.Enum, so the rest of the collection reads it without a second list:

enum.Options(br.UFValues()...)        // the options of a select
validation.EnumOf(br.UFValues()...)   // the rule

As a column, Value and Scan refuse a code outside the set.

What this package does not do

reached for why not
New, a Module, a line in k.Register there is nothing to register: no route, no table, no policy
a lookup at the Receita Federal or the Correios a validator that calls out is a validator that fails when the network does, and the manifest declares network = false
accepting 123.456.789 09, 01000-000 or full-width digits the caller would store a value the person did not type
a float64 amount BRL takes centavos; a float has already rounded
reading the process locale the same call would print differently depending on what another part of the application set

Layout

cpf.go, cnpj.go, cep.go   parsing, check digits and punctuation
mobile.go                 the mobile number
shape.go                  the masks they share
redact.go                 RedactCPF, RedactCNPJ and the Redaction type
rules.go, catalog.go      Rules, Defs, Install and the rule names
phone.go                  the landline, the area code and the other spellings of a number
nis.go, cns.go, cnh.go    the documents with check digits
renavam.go, voter.go
certificate.go
plate.go                  the vehicle plate and the passport
stateregistration.go      the state registration number of the 27 units
normalize.go              NormalizeCPF and NormalizeCNPJ
masked.go                 the checks of the formato_ rules
money.go, date.go         BRL, FormatBRL, BRLDecimal, ParseBRL, Date, DateTime, ParseDate, ParseTimeOfDay
uf.go                     the UF enum

Tests

GOWORK=off go test -race ./...

Every valid document in the suite is generated from a fixed seed by an oracle written apart from the package, from the Receita Federal's weight tables; none is copied from anywhere. The parsers are fuzzed against that oracle:

GOWORK=off go test -run='^$' -fuzz='^FuzzParseCNPJ$' -fuzztime=30s ./tests/Unit

Licence

MIT. See LICENSE.md. Copyright Paulo R. Lima.

Documentation

Overview

Package br validates and formats the Brazilian values an application takes from a form and prints on a page: the CPF, the CNPJ, the CEP, the telephone numbers, the documents with check digits, an amount in reais, a date, and the federative unit -- and a CPF or a CNPJ with part of it hidden.

It is a library. It registers no route, owns no table and decides no authorization, so nothing about it goes in bootstrap/app.go but one call to Factory.Use: a caller imports it and calls it.

Taking a value in

ParseCPF, ParseCNPJ and ParseCEP read a value written bare or in its one conventional punctuation, and return the bare spelling to store. ValidCPF, ValidCNPJ and ValidCEP are the same question answered with a bool. The CPF and the CNPJ are checked against the check digits the Receita Federal computes; the CNPJ may be alphanumeric. A CPF and a CNPJ are text from the form to the column: a document read as a number has lost its leading zeros, and the alphanumeric CNPJ cannot be a number at all.

ParseMobile reads a mobile number the same way, and ParseLocalMobile, ParseMobileWithCountry, ParseLandline, ParseLocalLandline and ParseLandlineWithCountry the other spellings of a telephone number. ParseNIS, ParseCNS, ParseCNH, ParseRenavam, ParseVoterTitle, ParseCivilCertificate, ParsePlate, ParsePassport and ParseStateRegistration read the other documents, and ParseDate and ParseTimeOfDay read 31/12/2026 and 15:04. NormalizeCPF and NormalizeCNPJ drop the punctuation of text that already left the form. ParseBRL reads an amount in reais as a person types it, R$ 1.234,56, or as an HTML number input submits it, 1234.56, and returns centavos.

The rules

The same checks are rules of hesape/validation, under the names of the PHP packages geekcom/validator-docs and laravellegends/pt-br-validator: cpf, cnpj, cpf_ou_cnpj, cep, celular, celular_com_ddd, telefone, placa, renavam, cnh, titulo_eleitor, nis, cns, certidao, uf, inscricao_estadual:SP, data, horario, brl and the formato_ rules, which check a spelling alone. Defs lists them as validation.RuleDef values -- the name, the aliases, the check, the arguments and the pt-BR sentence with :attribute -- and Rules is the validation.Provider that declares them to the Factory the application builds, once, where it is wired:

factory.Use(br.Rules())

A rule set compiled before the Factory exists, in a package-level variable, is compiled with validation.WithModuleRules. Each rule has a constant:

rules := validation.Rules{
	"document": "required|" + br.RuleCPFOrCNPJ,
	"postcode": "required|" + br.RuleCEPFormat,
	"state":    "required|" + br.RuleStateRegistration + ":SP",
}

Importing this package still registers cpf, cnpj, cpf_or_cnpj, cpf_ou_cnpj, cep, celular, celular_com_ddd and brl, so that a rule set that names them compiles without a Factory. That registration is deprecated and goes in a later release; Rules declares the same names, and Install, which calls Factory.Use, is deprecated too.

Printing a value

CPF, CNPJ, CEP, Mobile, Landline, NIS and CNS punctuate a stored value; BRL writes centavos as reais, R$ 1.234,56, and FormatBRL writes them without the grouping, without zero centavos or without the symbol; BRLDecimal writes an exact decimal amount finer than a centavo, every digit kept; Date writes a day as 31/12/2026 and DateTime a day and a time as 31/12/2026 15:04. RedactCPF and RedactCNPJ write a document with part of it hidden, through a Redaction such as KeepCPFMiddle, ***.456.789-**. Each is a function of its arguments alone.

UF is the closed set of the twenty-seven units, in the shape hesape/enum reads: UFValues, Label for the name a form shows, and Value and Scan for a column.

The files are laid out by subject:

cpf.go, cnpj.go, cep.go  -> parsing, check digits and punctuation
mobile.go, phone.go      -> the telephone numbers and the area code
nis.go, cns.go, cnh.go,
renavam.go, voter.go,
certificate.go           -> the other documents with check digits
plate.go                 -> the vehicle plate and the passport
stateregistration.go     -> the inscricao estadual of the 27 units
normalize.go             -> NormalizeCPF and NormalizeCNPJ
shape.go, masked.go      -> the masks they share, and the formato_ checks
redact.go                -> RedactCPF, RedactCNPJ and Redaction
rules.go, catalog.go     -> Rules, Defs, Install and the rule names
money.go, date.go        -> BRL, FormatBRL, BRLDecimal, ParseBRL, Date, DateTime,
                            ParseDate and ParseTimeOfDay
uf.go                    -> the UF enum

Index

Constants

View Source
const (
	// RuleCPF is a CPF, as ParseCPF accepts it.
	RuleCPF = "cpf"
	// RuleCNPJ is a CNPJ, numeric or alphanumeric, as ParseCNPJ accepts it.
	RuleCNPJ = "cnpj"
	// RuleCPFOrCNPJ is a value either ParseCPF or ParseCNPJ accepts: the
	// document field of a form a person or a company fills in. The rule was
	// registered as cpf_or_cnpj, which is still registered as another name for
	// it.
	RuleCPFOrCNPJ = "cpf_ou_cnpj"
	// RuleCEP is a CEP, as ParseCEP accepts it.
	RuleCEP = "cep"
	// RuleMobile is a Brazilian mobile number with its area code, as
	// ParseMobile accepts it. It was registered as celular, which now means
	// the number without the area code: see RuleLocalMobile.
	RuleMobile = "celular_com_ddd"
	// RuleBRL is an amount in reais, as ParseBRL accepts it: the price or the
	// budget field of a form.
	RuleBRL = "brl"

	// RuleLocalMobile is a mobile number without the area code, as
	// ParseLocalMobile accepts it.
	RuleLocalMobile = "celular"
	// RuleMobileWithCountry is a mobile number with the country code, as
	// ParseMobileWithCountry accepts it.
	RuleMobileWithCountry = "celular_com_codigo"
	// RuleMobileWithCountryBare is a mobile number with the country code and
	// no parentheses or hyphen: +5514999999999.
	RuleMobileWithCountryBare = "celular_com_codigo_sem_mascara"
	// RuleLocalLandline is a landline number without the area code, as
	// ParseLocalLandline accepts it.
	RuleLocalLandline = "telefone"
	// RuleLandline is a landline number with its area code, as ParseLandline
	// accepts it.
	RuleLandline = "telefone_com_ddd"
	// RuleLandlineWithCountry is a landline number with the country code, as
	// ParseLandlineWithCountry accepts it.
	RuleLandlineWithCountry = "telefone_com_codigo"
	// RuleAnyPhone is a telephone number, mobile or landline, with or without
	// the area code, as ParseAnyPhone accepts it: the field whose mask changes
	// as the person types.
	RuleAnyPhone = "telefone_ou_celular"
	// RuleAreaCode is an area code, as ParseAreaCode accepts it.
	RuleAreaCode = "ddd"

	// RuleCPFFormat is a CPF written 000.000.000-00, whatever its digits.
	RuleCPFFormat = "formato_cpf"
	// RuleCNPJFormat is a CNPJ written 00.000.000/0000-00, whatever its
	// characters.
	RuleCNPJFormat = "formato_cnpj"
	// RuleCPFOrCNPJFormat is a value written as either of the two.
	RuleCPFOrCNPJFormat = "formato_cpf_ou_cnpj"
	// RuleCEPFormat is a CEP written 00000-000 or 00.000-000.
	RuleCEPFormat = "formato_cep"

	// RulePlate is a vehicle plate, as ParsePlate accepts it.
	RulePlate = "placa"
	// RulePlateFormat is a plate written with three letters, an optional
	// hyphen, a digit, a digit or a letter, and two digits.
	RulePlateFormat = "formato_placa_de_veiculo"
	// RuleRenavam is a RENAVAM, as ParseRenavam accepts it.
	RuleRenavam = "renavam"
	// RuleCNH is a CNH register number, as ParseCNH accepts it.
	RuleCNH = "cnh"
	// RuleVoterTitle is a título de eleitor, as ParseVoterTitle accepts it.
	RuleVoterTitle = "titulo_eleitor"
	// RuleNIS is a NIS, as ParseNIS accepts it.
	RuleNIS = "nis"
	// RulePIS is a PIS: the same number as the NIS, under the other name.
	RulePIS = "pis"
	// RuleNISFormat is a NIS written 000.00000.00-0.
	RuleNISFormat = "formato_nis"
	// RulePISFormat is a PIS written 000.00000.00-0.
	RulePISFormat = "formato_pis"
	// RuleCNS is a Cartão Nacional de Saúde number, as ParseCNS accepts it.
	RuleCNS = "cns"
	// RuleCivilCertificate is the number of a birth, marriage or death
	// certificate, as ParseCivilCertificate accepts it.
	RuleCivilCertificate = "certidao"
	// RuleCivilCertificateFormat is a certificate number written in its nine
	// groups.
	RuleCivilCertificateFormat = "formato_certidao"
	// RuleUF is the code of a federative unit, as ParseUF accepts it.
	RuleUF = "uf"
	// RulePassport is a Brazilian passport number, as ParsePassport accepts
	// it.
	RulePassport = "passaporte"
	// RuleStateRegistration is an inscrição estadual of the unit named as the
	// argument, inscricao_estadual:SP, as ParseStateRegistration accepts it.
	RuleStateRegistration = "inscricao_estadual"
	// RuleDate is a day written 31/12/2026, as ParseDate accepts it.
	RuleDate = "data"
	// RuleTimeOfDay is a time written 15:04 or 15:04:05, as ParseTimeOfDay
	// accepts it.
	RuleTimeOfDay = "horario"
	// RuleMoney is an amount in reais under the name the PHP packages' users
	// look for: another name for RuleBRL.
	RuleMoney = "moeda"
)

The names of the rules this package declares, for a rule string:

rules := validation.Rules{
	"document": "required|" + br.RuleCPFOrCNPJ,
	"postcode": []any{"required", br.RuleCEPFormat},
	"phone":    "required|" + br.RuleMobile,
}

They are the names of the PHP packages geekcom/validator-docs and laravellegends/pt-br-validator, so a rule set written for one of them reads the same here. Defs lists them with what each accepts and what it says when it refuses, and Rules is the module that declares them to a Factory:

factory := validation.NewFactory(validation.FromTranslation(tr)).Use(br.Rules())

A rule set compiled in a package-level variable may name them if it is compiled with validation.WithModuleRules: the Factory resolves it when it is used, and Factory.Check fails at boot naming any rule no module declared. The names the earlier releases registered when this package was imported -- cpf, cnpj, cpf_or_cnpj, cep, celular and brl, with cpf_ou_cnpj and celular_com_ddd beside them -- are still registered that way, which is deprecated, and Rules leaves them to that registration.

Each rule accepts only a string -- a document sent as a JSON number has already lost its leading zeros -- and a blank value is left to required or nullable. A rule that takes no argument does not compile when it is written with one: cpf:strict is a typo, and a boot failure reports it.

Variables

View Source
var ErrInvalidAreaCode = errors.New("br: not a valid area code")

ErrInvalidAreaCode is what ParseAreaCode returns for a value that is not an area code (DDD) Anatel assigns.

View Source
var ErrInvalidBRL = errors.New("br: not a valid amount in reais")

ErrInvalidBRL is what ParseBRL returns for a value that is not an amount in reais.

View Source
var ErrInvalidCEP = errors.New("br: not a valid CEP")

ErrInvalidCEP is what ParseCEP returns for a value that is not a CEP.

View Source
var ErrInvalidCNH = errors.New("br: not a valid CNH")

ErrInvalidCNH is what ParseCNH returns for a value that is not a CNH.

View Source
var ErrInvalidCNPJ = errors.New("br: not a valid CNPJ")

ErrInvalidCNPJ is what ParseCNPJ and CNPJCheckDigits return for a value that is not a CNPJ.

View Source
var ErrInvalidCNS = errors.New("br: not a valid CNS")

ErrInvalidCNS is what ParseCNS returns for a value that is not a CNS.

View Source
var ErrInvalidCPF = errors.New("br: not a valid CPF")

ErrInvalidCPF is what ParseCPF and CPFCheckDigits return for a value that is not a CPF. It says nothing about which part was wrong, because the person who typed the value is the only one who can tell a typo from a wrong number.

View Source
var ErrInvalidCivilCertificate = errors.New("br: not a valid civil registry certificate number")

ErrInvalidCivilCertificate is what ParseCivilCertificate returns for a value that is not the number of a civil registry certificate.

View Source
var ErrInvalidDate = errors.New("br: not a valid date")

ErrInvalidDate is what ParseDate returns for a value that is not a calendar day written as 31/12/2026.

View Source
var ErrInvalidLandline = errors.New("br: not a valid landline number")

ErrInvalidLandline is what the Landline parsers return for a value that is not a Brazilian landline number.

View Source
var ErrInvalidMobile = errors.New("br: not a valid mobile number")

ErrInvalidMobile is what ParseMobile returns for a value that is not a Brazilian mobile number.

View Source
var ErrInvalidNIS = errors.New("br: not a valid NIS")

ErrInvalidNIS is what ParseNIS returns for a value that is not a NIS.

View Source
var ErrInvalidPassport = errors.New("br: not a valid passport number")

ErrInvalidPassport is what ParsePassport returns for a value that is not a Brazilian passport number.

View Source
var ErrInvalidPhone = errors.New("br: not a valid telephone number")

ErrInvalidPhone is what ParseAnyPhone returns for a value that is not a Brazilian telephone number of either kind.

View Source
var ErrInvalidPlate = errors.New("br: not a valid vehicle plate")

ErrInvalidPlate is what ParsePlate returns for a value that is not a vehicle plate.

View Source
var ErrInvalidRenavam = errors.New("br: not a valid RENAVAM")

ErrInvalidRenavam is what ParseRenavam returns for a value that is not a RENAVAM.

View Source
var ErrInvalidStateRegistration = errors.New("br: not a valid state registration number")

ErrInvalidStateRegistration is what ParseStateRegistration returns for a value that is not a state registration number of the unit it was asked about.

View Source
var ErrInvalidTimeOfDay = errors.New("br: not a valid time of day")

ErrInvalidTimeOfDay is what ParseTimeOfDay returns for a value that is not a time of day.

View Source
var ErrInvalidUF = errors.New("br: not a UF")

ErrInvalidUF is what ParseUF, Value and Scan return for a code outside the set.

View Source
var ErrInvalidVoterTitle = errors.New("br: not a valid voter registration number")

ErrInvalidVoterTitle is what ParseVoterTitle returns for a value that is not a título de eleitor.

Functions

func BRL

func BRL(cents int64) string

BRL writes an amount of reais held as a count of centavos, the way a Brazilian page prints money: R$ 1.234,56.

A dot separates each three digits of the reais, a comma stands before the two digits of the centavos, and the symbol leads with a space after it. A negative amount leads with the sign, before the symbol -- -R$ 1.234,56 -- because a sign written after the symbol reads as part of the amount. Zero is R$ 0,00, and every int64 is written, its most negative value included.

The amount is an integer because an amount that has to add up is held as one; no float64 appears on the way from it to the page. The result depends on nothing but the argument: hesape/number writes the same string from CurrencyFromCents(cents, "BRL") only while the process-wide locale is pt-BR, and a library cannot set that locale without setting it for everything else the application formats.

BRL is FormatBRL with the zero BRLFormat.

func BRLDecimal added in v0.4.0

func BRLDecimal(amount string) string

BRLDecimal writes an exact amount of reais held as decimal text -- the digits of the reais, then a dot and as many digits of a fraction of a real as the amount has, the way math/big and a decimal column write one -- with the symbol, the grouping and the comma of BRL, and every digit of the fraction kept: 1234.5678 is R$ 1.234,5678, -0.000001 is -R$ 0,000001 and 47 is R$ 47.

It is for an amount finer than a centavo -- a price per unit of usage, the exact total a charge was rounded from -- that a page must show to the last digit it was computed to. Nothing is rounded and no float64 appears on the way: the digits that arrive are the digits written.

The amount is an optional minus sign, one ASCII digit or more, and optionally a dot followed by one digit or more. Anything else is returned unchanged: it formats, and does not validate.

func CEP

func CEP(s string) string

CEP writes a CEP punctuated, as 00000-000.

It takes the eight digits bare or already punctuated, and returns anything else unchanged: it formats, and does not validate. Validate with ParseCEP where the value is taken in.

func CNPJ

func CNPJ(s string) string

CNPJ writes a CNPJ punctuated, as 00.000.000/0000-00, with its letters in capitals.

It takes the fourteen characters bare or already punctuated, and returns anything else unchanged: it formats, and does not validate. Validate with ParseCNPJ where the value is taken in.

func CNPJCheckDigits

func CNPJCheckDigits(base string) (string, error)

CNPJCheckDigits returns the two check digits of a CNPJ whose first twelve characters are base, and ErrInvalidCNPJ when base is not twelve digits or letters. A lower-case letter is read as its capital.

Each character is worth its ASCII code minus 48 -- a digit its own value, A seventeen, Z forty-two. A check digit is the sum of the characters before it, weighted from the right by 2 to 9 and again from 2, taken modulo eleven: a remainder below two gives zero, and any other gives eleven minus it.

func CNS added in v0.5.0

func CNS(s string) string

CNS writes a CNS punctuated, as 000 0000 0000 0000.

It takes the fifteen digits bare or already punctuated, and returns anything else unchanged: it formats, and does not validate. Validate with ParseCNS where the value is taken in.

func CPF

func CPF(s string) string

CPF writes a CPF punctuated, as 000.000.000-00.

It takes the eleven digits bare or already punctuated, and returns anything else unchanged: it formats, and does not validate, so a page that prints a stored value shows what is stored rather than an empty cell. Validate with ParseCPF where the value is taken in.

func CPFCheckDigits

func CPFCheckDigits(base string) (string, error)

CPFCheckDigits returns the two check digits of a CPF whose first nine digits are base, and ErrInvalidCPF when base is not nine digits.

Each check digit is the sum of the digits before it, weighted from 10 (or 11) down to 2, times ten, modulo eleven -- with ten written as zero. It is what a seeder or a factory needs to write a CPF that passes, without borrowing one that belongs to somebody.

func Date

func Date(t time.Time) string

Date writes the calendar day of t as a Brazilian page prints it: 31/12/2026, day, month and four-digit year.

The day is the one t holds in its own location. An instant read from a database is usually in UTC, where a late evening in Brasília is already the next day, so convert it first -- br.Date(t.In(location)) -- with the location the reader lives in.

func DateTime added in v0.4.0

func DateTime(t time.Time) string

DateTime writes the calendar day and the time of day of t as a Brazilian page prints them: 31/12/2026 15:04, the day as Date writes it, a space, and the hours and minutes on a twenty-four hour clock.

Like Date it reads t in its own location, so an instant from a database is converted first -- br.DateTime(t.In(location)) -- with the location the reader lives in, and a page that keeps UTC says so beside it.

func Defs added in v0.6.0

func Defs() []validation.RuleDef

Defs lists the rules this package declares, each as the RuleDef that hesape/validation takes: its name, its aliases, its check, the arguments it takes and its pt-BR sentence. It returns a new slice every time; the application changes nothing by editing it. Rules is the module that declares them.

Where the two PHP packages the names come from disagree on what a rule accepts, the rule here accepts what the Parse function of its document accepts, which is the narrow reading: the value bare or in its one conventional punctuation, and nothing else.

func FormatBRL added in v0.3.0

func FormatBRL(cents int64, f BRLFormat) string

FormatBRL writes an amount of reais held as a count of centavos, as BRL does, departing from it in what f says: R$ 1234,56 without the grouping, R$ 47 without the zero centavos, 1.234,56 without the symbol. The sign and the comma are BRL's, and every int64 is written.

func FormatPhone added in v0.7.0

func FormatPhone(digits string) string

FormatPhone writes the digits of a telephone number punctuated by their count: 8 as 0000-0000, 9 as 00000-0000, 10 as (00) 0000-0000 and 11 as (00) 00000-0000. Any other length, and a value that is not all digits, is returned unchanged: it formats, and does not validate.

func Install deprecated added in v0.5.0

func Install(f *validation.Factory)

Install declares the rules of Rules on a Factory, and does nothing for a nil one.

Deprecated: use factory.Use(br.Rules()), which is the same declaration through the call hesape/validation provides for a module.

func Landline added in v0.5.0

func Landline(s string) string

Landline writes a landline number with its area code punctuated, as (00) 0000-0000.

It takes the ten digits bare or already punctuated, and returns anything else unchanged: it formats, and does not validate. Validate with ParseLandline where the value is taken in.

func Messages added in v0.5.0

func Messages(locale string) map[string]string

Messages lists the sentence of every rule in locale, by the name a rule string writes -- aliases included -- which is the key under validation. An application that keeps its sentences in language files can load them from it, and the lines it defines itself take precedence over these.

func Mobile added in v0.2.0

func Mobile(s string) string

Mobile writes a mobile number punctuated, as (00) 00000-0000.

It takes the eleven digits bare or already punctuated, and returns anything else unchanged: it formats, and does not validate. Validate with ParseMobile where the value is taken in.

func NIS added in v0.5.0

func NIS(s string) string

NIS writes a NIS punctuated, as 000.00000.00-0.

It takes the eleven digits bare or already punctuated, and returns anything else unchanged: it formats, and does not validate. Validate with ParseNIS where the value is taken in.

func NormalizeCNPJ added in v0.5.0

func NormalizeCNPJ(s string) string

NormalizeCNPJ returns the digits and the letters of s, the letters in capitals, and drops every other character: the dots, the slash, the hyphen and the spaces. A CNPJ may carry letters in its first twelve positions, so keeping only the digits would turn one into another number.

It does not validate and does not check the length; taking a value in is ParseCNPJ. The result is text, as the document is: a CNPJ read as a number loses its leading zeros and cannot hold a letter.

func NormalizeCPF added in v0.5.0

func NormalizeCPF(s string) string

NormalizeCPF returns the digits of s and drops every other character: the dots, the hyphen, the spaces a person or a spreadsheet put around them.

It is for text that already left the form -- a column, a file, a pasted list -- and has to be compared with the stored spelling. It does not validate, does not check the length and does not restore a zero a number lost, because a CPF is text: keep it as text from the form to the column. Taking a value in is ParseCPF, which refuses what NormalizeCPF would have forgiven.

func NormalizePhone added in v0.7.0

func NormalizePhone(s string) string

NormalizePhone returns the digits of s and drops every other character: the parentheses, the hyphen, the spaces and a plus sign.

It is for text that already left the form, to compare with the stored spelling. It does not validate and does not check the length; taking a value in is ParseAnyPhone.

func ParseAnyPhone added in v0.7.0

func ParseAnyPhone(s string) (string, error)

ParseAnyPhone returns the digits of a Brazilian telephone number, mobile or landline, with or without the area code, and ErrInvalidPhone for anything else. It is for the field whose mask changes as the person types.

The value is the digits bare or in their usual punctuation, by length:

8 digits   a landline without the area code, 0000-0000, the first digit 2 to 9
9 digits   a mobile number without it, 00000-0000, the first digit 9
10 digits  a landline with it, (00) 0000-0000 or (00)0000-0000
11 digits  a mobile number with it, (00) 00000-0000 or (00)00000-0000

The area code is one Anatel assigns. A ten-digit number whose third digit is 9 is refused, because it is the eleven-digit mobile number missing a digit and not a landline. The country code is not read: ParseMobileWithCountry and ParseLandlineWithCountry are for that. A repetition of one digit is refused. The digits come back bare, which is the spelling to store.

func ParseAreaCode added in v0.5.0

func ParseAreaCode(s string) (string, error)

ParseAreaCode returns the two digits of an area code (DDD) written bare, and ErrInvalidAreaCode for anything else, including a code Anatel does not assign. It accepts nothing around the digits: not a leading zero, not parentheses.

func ParseBRL added in v0.3.0

func ParseBRL(s string) (int64, error)

ParseBRL reads an amount in reais as a person types it into a form, and returns it as a count of centavos, or ErrInvalidBRL.

The amount may be led by the symbol, R$, with or without a space after it, and whitespace around the whole is ignored. The reais are digits, bare (1234) or grouped by dots in threes (1.234); a comma then gives one or two digits of centavos (1.234,56, and 1.234,5 for fifty centavos). An amount with no comma may instead give its centavos after a single dot, when that dot is followed by one or two digits and nothing else (1234.56): that is how an HTML number input submits a value, and no grouping of thousands leaves fewer than three digits after a dot. A dot followed by three digits always groups thousands, so 1.500 is fifteen hundred reais -- a number input that should take centavos says step="0.01", which keeps a third decimal out of it.

Everything else is refused: a sign, another currency or a lower-case r$, a space or a dot inside the digits other than as above, a group of other than three digits, a third digit of centavos, a comma with nothing after it, a digit outside ASCII, and an amount past the largest int64. Zero is an amount; a form that needs a positive one says so itself.

func ParseCEP

func ParseCEP(s string) (string, error)

ParseCEP returns the eight digits of a CEP, written bare (00000000) or punctuated (00000-000), and ErrInvalidCEP for anything else or for a code below 01000-000, where no range begins.

A CEP carries no check digit, so a code that passes may still address nothing: only a lookup in the Correios base can say it exists.

The digits come back bare, which is the spelling to store.

func ParseCNH added in v0.5.0

func ParseCNH(s string) (string, error)

ParseCNH returns the eleven digits of a Carteira Nacional de Habilitação register number, written bare, and ErrInvalidCNH for anything else.

The last two digits are the check digits the Denatran computes: the first is the sum of the nine digits before it, weighted from 9 down to 1, modulo eleven, with ten written as zero; the second is the sum of the same nine weighted from 1 up to 9, modulo eleven, less 2 when the first came from a ten, brought back above zero by adding eleven, with ten again written as zero. Eleven repetitions of one digit are refused. The number is not punctuated, and a leading zero is part of it.

It does not say whether the licence was issued or is in force: only the Detran can.

func ParseCNPJ

func ParseCNPJ(s string) (string, error)

ParseCNPJ returns the fourteen characters of a CNPJ, written bare (00000000000000) or punctuated (00.000.000/0000-00), and ErrInvalidCNPJ for anything else.

The first twelve positions may hold letters as well as digits: that is the alphanumeric CNPJ the Receita Federal issues, and the numeric CNPJ is the case of it whose twelve positions are all digits, checked by the same computation. The last two positions are the check digits, and are always digits. A letter typed in lower case is read as the capital it stands for, and comes back as one.

It refuses fourteen repetitions of one character, which no CNPJ is. It does not say whether the CNPJ was issued or is active: only the Receita Federal can.

The characters come back bare, which is the spelling to store.

func ParseCNS added in v0.5.0

func ParseCNS(s string) (string, error)

ParseCNS returns the fifteen digits of a Cartão Nacional de Saúde, written bare (000000000000000) or punctuated (000 0000 0000 0000), and ErrInvalidCNS for anything else.

A definitive card begins with 1 or 2 and carries 00 and then 0 or 1 in the positions that follow the NIS it was issued from; a provisional one begins with 7, 8 or 9. Either way the digits weighted from 15 down to 1 add up to a multiple of eleven. It does not say whether the card was issued: only the Ministério da Saúde can.

The digits come back bare, which is the spelling to store.

func ParseCPF

func ParseCPF(s string) (string, error)

ParseCPF returns the eleven digits of a CPF, written bare (00000000000) or punctuated (000.000.000-00), and ErrInvalidCPF for anything else.

It checks the shape and the two check digits the Receita Federal computes, and refuses the eleven repetitions of one digit, whose check digits compute but which belong to nobody. It does not say whether the CPF was issued or is regular: only the Receita Federal can.

The digits come back bare, which is the spelling to store: a column that holds both spellings cannot be searched for either.

func ParseCivilCertificate added in v0.5.0

func ParseCivilCertificate(s string) (string, error)

ParseCivilCertificate returns the thirty-two digits of the number of a birth, marriage or death certificate, written bare or in its nine groups, and ErrInvalidCivilCertificate for anything else.

The groups are told apart by a dot or a space, with a hyphen or a space before the last: 000000.00.00.0000.0.00000.000.0000000-00 and 000000 00 00 0000 0 00000 000 0000000 00. The last two digits are check digits: each is the sum of the digits before it, weighted from 2 upwards for the first and from 1 upwards for the second, to 10 and then from 0, modulo eleven, with ten written as one. Thirty-two repetitions of one digit are refused: their check digits compute and the number belongs to nobody. It does not say whether the certificate exists: only the registry can.

The digits come back bare, which is the spelling to store.

func ParseDate added in v0.5.0

func ParseDate(s string) (time.Time, error)

ParseDate reads a calendar day written as a Brazilian page prints it, 31/12/2026 -- two digits of the day, two of the month and four of the year -- and returns midnight of that day in UTC. It returns ErrInvalidDate for anything else, including a day the month does not have: 29/02/2027, 31/04/2026, and the year 0000.

A date has no time zone, so what it returns is the day and nothing else; compare its Year, Month and Day, or put the day in a location with time.Date.

func ParseLandline added in v0.5.0

func ParseLandline(s string) (string, error)

ParseLandline returns the ten digits of a landline number with its area code, written bare (1130000000) or punctuated ((11) 3000-0000, or (11)3000-0000 without the space after the area code), and ErrInvalidLandline for anything else.

The area code is one Anatel assigns. It checks the shape and the first digit of the number, and does not say whether the line exists: only the operator can.

func ParseLandlineWithCountry added in v0.5.0

func ParseLandlineWithCountry(s string) (string, error)

ParseLandlineWithCountry returns the twelve digits of a Brazilian landline number written with its country code -- 55, the area code and the eight digits -- and ErrInvalidLandline for anything else. It reads the spellings ParseMobileWithCountry reads.

func ParseLocalLandline added in v0.5.0

func ParseLocalLandline(s string) (string, error)

ParseLocalLandline returns the eight digits of a landline number written without the area code, bare (30000000) or punctuated (3000-0000), and ErrInvalidLandline for anything else. The first digit is not 0 or 1.

func ParseLocalMobile added in v0.5.0

func ParseLocalMobile(s string) (string, error)

ParseLocalMobile returns the nine digits of a mobile number written without the area code, bare (900000000) or punctuated (90000-0000), and ErrInvalidMobile for anything else.

The number starts with 9 -- every mobile number has since 2016, and an eight-digit number is a landline, so ParseLocalLandline reads it -- and it refuses the nine followed by eight zeros, which a form fills when somebody types nothing.

func ParseMobile added in v0.2.0

func ParseMobile(s string) (string, error)

ParseMobile returns the eleven digits of a Brazilian mobile number, written bare (00000000000) or punctuated ((00) 00000-0000, or (00)00000-0000 without the space after the area code, as it is often typed), and ErrInvalidMobile for anything else.

It checks the shape, that the area code is one Anatel assigns, that the number starts with 9 (every mobile number since 2016), and refuses the nine followed by eight zeros, which a form fills when somebody types nothing. It does not say whether the line exists: only the operator can.

The digits come back bare, which is the spelling to store.

func ParseMobileWithCountry added in v0.5.0

func ParseMobileWithCountry(s string) (string, error)

ParseMobileWithCountry returns the thirteen digits of a Brazilian mobile number written with its country code -- 55, the area code and the nine digits -- and ErrInvalidMobile for anything else.

It reads +55 (00) 00000-0000, with the optional spaces after the country code and after the parenthesis, and +5500000000000, with the optional spaces after the country code and after the area code. The code has to be Brazil's: the area code and the number are checked against Brazil's plan, which no other country's number follows. The area code is one Anatel assigns, as in ParseMobile.

func ParseNIS added in v0.5.0

func ParseNIS(s string) (string, error)

ParseNIS returns the eleven digits of a NIS -- the number the PIS, the PASEP, the NIT and the Cadastro Único all use -- written bare (00000000000) or punctuated (000.00000.00-0), and ErrInvalidNIS for anything else.

It checks the shape and the check digit, and refuses eleven repetitions of one digit. A number with fewer than eleven digits is refused, not padded: a leading zero is a digit of the number, and the person who left it out typed another number.

The digits come back bare, which is the spelling to store.

func ParsePassport added in v0.5.0

func ParsePassport(s string) (string, error)

ParsePassport returns a Brazilian passport number in capitals, and ErrInvalidPassport for anything else. The number is two letters, in either case, and six digits. It checks the shape: the passport carries no check digit this package knows.

func ParsePlate added in v0.5.0

func ParsePlate(s string) (string, error)

ParsePlate returns a vehicle plate in capitals and without punctuation, and ErrInvalidPlate for anything else.

It reads every shape in plateShapes, a letter in either case, and the hyphen after the three letters that the plate of 1990 to 2018 is written with -- ABC-1234, and ABC-1D23 too -- which does not come back. It checks the shape and nothing else: only the Detran knows whether a plate was issued.

func ParseRenavam added in v0.5.0

func ParseRenavam(s string) (string, error)

ParseRenavam returns the eleven digits of a Registro Nacional de Veículos Automotores number, written bare, and ErrInvalidRenavam for anything else.

The number issued before 2013 has nine digits and the ones between that and the eleven have ten; both are read as the eleven they were always meant to be, with the zeros in front, and come back as those eleven. The last digit is the check digit: the ten before it weighted by 3, 2, 9, 8, 7, 6, 5, 4, 3 and 2, the sum taken modulo eleven, eleven minus the remainder, and zero when that is ten or more. A number of one digit repeated is refused. It does not say whether the vehicle exists: only the Detran can.

func ParseStateRegistration added in v0.5.0

func ParseStateRegistration(uf UF, s string) (string, error)

ParseStateRegistration returns the digits of an inscrição estadual written for the unit uf, and ErrInvalidStateRegistration for anything else, including a uf that is not one of the twenty-seven.

Every unit issues its own number, with its own length, its own prefix and its own check digits, so the unit is part of the question: the same digits can be valid in one and not in another. The number is read with its digits alone or with dots, hyphens and slashes between them, the way each unit prints it; any other character, or a separator that starts, ends or doubles, is refused. A repetition of one digit is refused.

The value "ISENTO" a company without a registration writes in its place is not a number and is not accepted: a form that takes it names it beside the rule. It does not say whether the registration is active: only the unit's treasury can.

The digits come back bare, which is the spelling to store.

func ParseTimeOfDay added in v0.5.0

func ParseTimeOfDay(s string) (time.Duration, error)

ParseTimeOfDay reads a time of day written 15:04 or 15:04:05, on a twenty-four hour clock, and returns how long after midnight it is. It returns ErrInvalidTimeOfDay for anything else: hours above 23, minutes or seconds above 59, a missing zero, or a time with a meridiem.

func ParseVoterTitle added in v0.5.0

func ParseVoterTitle(s string) (string, error)

ParseVoterTitle returns the digits of a título de eleitor, written bare or, for the common twelve digits, punctuated (0000 0000 0000), and ErrInvalidVoterTitle for anything else.

The number is a sequence, then two digits for the state that issued it -- 01 to 28, São Paulo to the title issued abroad -- and two check digits. It reads from five to thirteen digits, because the sequence of the older titles is shorter and a few are longer. The first check digit weighs the sequence from 9 down to 2 and over again from the right; the second weighs the state and the first check digit the same way; each is the sum modulo eleven, with ten written as zero and, for São Paulo and Minas Gerais, a zero written as one. A number of one digit repeated is refused. It does not say whether the voter is registered: only the Justiça Eleitoral can.

func RedactCNPJ added in v0.3.0

func RedactCNPJ(s string, r Redaction) string

RedactCNPJ writes a CNPJ with the positions r hides replaced, as r spells it.

It takes the fourteen characters bare or punctuated, as ParseCNPJ reads them, a lower-case letter shown as its capital, and does not check the check digits. For anything else, or a redaction of neither length, it returns "".

func RedactCPF added in v0.3.0

func RedactCPF(s string, r Redaction) string

RedactCPF writes a CPF with the positions r hides replaced, as r spells it.

It takes the eleven digits bare or punctuated, as ParseCPF reads them, and does not check the check digits: a page that hides a stored value hides it whether or not it was ever valid. For anything else -- a value of another shape, or a redaction of neither length -- it returns "", and never the value it was given: a redaction that fell back to its input would print the document it exists to hide.

func Rules added in v0.5.0

func Rules() validation.Provider

Rules is the module of the rules in Defs, for validation.Factory.Use:

factory := validation.NewFactory(validation.FromTranslation(tr))
factory.Use(br.Rules())

It declares every rule and alias of Defs in the factory's registry, with the pt-BR sentence and the filler of the :uf placeholder, and nothing else: nothing is registered before the application calls Use. A name already in the process-wide catalogue, which is what the deprecated registration at import leaves, or already declared in the registry, is skipped, so Use may be called on a factory that Install already served.

func ValidAnyPhone added in v0.7.0

func ValidAnyPhone(s string) bool

ValidAnyPhone reports whether ParseAnyPhone accepts s.

func ValidAreaCode added in v0.5.0

func ValidAreaCode(s string) bool

ValidAreaCode reports whether ParseAreaCode accepts s.

func ValidBRL added in v0.3.0

func ValidBRL(s string) bool

ValidBRL reports whether ParseBRL accepts s.

func ValidCEP

func ValidCEP(s string) bool

ValidCEP reports whether ParseCEP accepts s.

func ValidCNH added in v0.5.0

func ValidCNH(s string) bool

ValidCNH reports whether ParseCNH accepts s.

func ValidCNPJ

func ValidCNPJ(s string) bool

ValidCNPJ reports whether ParseCNPJ accepts s.

func ValidCNS added in v0.5.0

func ValidCNS(s string) bool

ValidCNS reports whether ParseCNS accepts s.

func ValidCPF

func ValidCPF(s string) bool

ValidCPF reports whether ParseCPF accepts s.

func ValidCivilCertificate added in v0.5.0

func ValidCivilCertificate(s string) bool

ValidCivilCertificate reports whether ParseCivilCertificate accepts s.

func ValidDate added in v0.5.0

func ValidDate(s string) bool

ValidDate reports whether ParseDate accepts s.

func ValidLandline added in v0.5.0

func ValidLandline(s string) bool

ValidLandline reports whether ParseLandline accepts s.

func ValidLandlineWithCountry added in v0.5.0

func ValidLandlineWithCountry(s string) bool

ValidLandlineWithCountry reports whether ParseLandlineWithCountry accepts s.

func ValidLocalLandline added in v0.5.0

func ValidLocalLandline(s string) bool

ValidLocalLandline reports whether ParseLocalLandline accepts s.

func ValidLocalMobile added in v0.5.0

func ValidLocalMobile(s string) bool

ValidLocalMobile reports whether ParseLocalMobile accepts s.

func ValidMobile added in v0.2.0

func ValidMobile(s string) bool

ValidMobile reports whether ParseMobile accepts s.

func ValidMobileWithCountry added in v0.5.0

func ValidMobileWithCountry(s string) bool

ValidMobileWithCountry reports whether ParseMobileWithCountry accepts s.

func ValidNIS added in v0.5.0

func ValidNIS(s string) bool

ValidNIS reports whether ParseNIS accepts s.

func ValidPassport added in v0.5.0

func ValidPassport(s string) bool

ValidPassport reports whether ParsePassport accepts s.

func ValidPlate added in v0.5.0

func ValidPlate(s string) bool

ValidPlate reports whether ParsePlate accepts s.

func ValidRenavam added in v0.5.0

func ValidRenavam(s string) bool

ValidRenavam reports whether ParseRenavam accepts s.

func ValidStateRegistration added in v0.5.0

func ValidStateRegistration(uf UF, s string) bool

ValidStateRegistration reports whether ParseStateRegistration accepts s for uf.

func ValidTimeOfDay added in v0.5.0

func ValidTimeOfDay(s string) bool

ValidTimeOfDay reports whether ParseTimeOfDay accepts s.

func ValidVoterTitle added in v0.5.0

func ValidVoterTitle(s string) bool

ValidVoterTitle reports whether ParseVoterTitle accepts s.

Types

type BRLFormat added in v0.3.0

type BRLFormat struct {
	// WithoutGrouping writes the reais with no dot between their thousands:
	// R$ 1234,56.
	WithoutGrouping bool
	// WithoutZeroCents leaves the centavos off an amount of whole reais, the
	// way a price list writes one: R$ 47, and still R$ 199,50.
	WithoutZeroCents bool
	// WithoutSymbol leaves the R$ and the space after it off, the way a form
	// field holds an amount it hands back to the person: 1.234,56, and
	// -1.234,56 for a negative one. ParseBRL reads it back.
	WithoutSymbol bool
}

BRLFormat is how FormatBRL departs from BRL. Its zero value departs in nothing, so each field names what it leaves out.

type Redaction added in v0.3.0

type Redaction string

A Redaction is how a page writes a document with part of it hidden, spelled the way the document is spelled: '#' shows the character in that position, and every other character is written as it stands.

"***.###.###-**"  the fourth to the ninth digits of a CPF, punctuated
"***######**"     the same digits, bare
"•••.###.###-••"  the same digits, hidden behind bullets

A Redaction has the length, in characters, of either spelling of the document: the punctuated one (14 for a CPF, 18 for a CNPJ) or the bare one (11 and 14). Where the punctuated spelling holds a separator, the redaction writes its own character there, so it chooses the punctuation as well as the hiding. The length alone says which spelling a redaction is, so one written for a document of another kind is read as whichever of the two it measures, or refused.

The named redactions are the ones Brazilian sources publish and pages print. A redaction written as a literal is just as good: any string of one of the two lengths is one.

const (
	// KeepCPFMiddle shows the fourth to the ninth digits of a CPF, punctuated:
	// ***.456.789-**. It is how the Portal da Transparência publishes the CPF
	// of a public agent.
	KeepCPFMiddle Redaction = "***.###.###-**"
	// KeepCPFMiddleBare shows the same six digits with no punctuation:
	// ***456789**. It is how the Receita Federal's open CNPJ data publishes the
	// CPF of a partner.
	KeepCPFMiddleBare Redaction = "***######**"
	// KeepCPFCheckDigits shows only the two check digits of a CPF, which
	// identify nobody: ***.***.***-00.
	KeepCPFCheckDigits Redaction = "***.***.***-##"
	// KeepCPFLastFive shows the last five digits of a CPF, as a profile page
	// reminds its owner which CPF it holds: ***.***.789-00.
	KeepCPFLastFive Redaction = "***.***.###-##"
	// KeepCNPJEnds shows the first two and the last two characters of a CNPJ:
	// 12.***.***/****-35.
	KeepCNPJEnds Redaction = "##.***.***/****-##"
)

The redactions a page usually needs. Each is a constant of the type, so a call reads br.RedactCPF(cpf, br.KeepCPFMiddle).

type UF

type UF string

UF is one of the twenty-seven federative units of Brazil -- the twenty-six states and the Federal District -- stored as its two-letter code.

It is a closed set in the shape a generated enum has: constants that are the only valid values, Valid to ask, Label for what a form shows, and a Value/Scan pair that refuses a code outside the set on the way to and from a column. So hesape/enum reads it like any other: enum.Options(br.UFValues()...) fills a select, and validation.EnumOf(br.UFValues()...) is the rule.

const (
	UFAC UF = "AC"
	UFAL UF = "AL"
	UFAP UF = "AP"
	UFAM UF = "AM"
	UFBA UF = "BA"
	UFCE UF = "CE"
	UFDF UF = "DF"
	UFES UF = "ES"
	UFGO UF = "GO"
	UFMA UF = "MA"
	UFMT UF = "MT"
	UFMS UF = "MS"
	UFMG UF = "MG"
	UFPA UF = "PA"
	UFPB UF = "PB"
	UFPR UF = "PR"
	UFPE UF = "PE"
	UFPI UF = "PI"
	UFRJ UF = "RJ"
	UFRN UF = "RN"
	UFRS UF = "RS"
	UFRO UF = "RO"
	UFRR UF = "RR"
	UFSC UF = "SC"
	UFSP UF = "SP"
	UFSE UF = "SE"
	UFTO UF = "TO"
)

The units, in the alphabetical order of their names, which is the order a list of them is read in. Stored exactly as written: the code is what the Correios, the Receita Federal and IBGE all print.

func ParseUF

func ParseUF(s string) (UF, error)

ParseUF turns request input into a UF, or wraps ErrInvalidUF.

It reads the code exactly as the set spells it, in capitals: the value a select sends back is the one Options gave it, and a value that differs from every option did not come from the form.

func UFValues

func UFValues() []UF

UFValues lists the twenty-seven units in declaration order.

It is what fills a select and what a rule is built from, so the set is written once, here, and every list of units derives from it.

func (UF) Label

func (v UF) Label() string

Label is the name of the unit, which is what a form shows: São Paulo for SP. It is empty for a code outside the set.

It is separate from String on purpose. The code is a contract with every column and every message that holds it; the name is a contract with nobody, and changing how one is spelled must not be able to change a row.

func (*UF) Scan

func (v *UF) Scan(src any) error

Scan implements sql.Scanner. A code the set does not hold is an error at the row that has it, rather than a value that behaves like a unit three layers up.

func (UF) String

func (v UF) String() string

String is the code, so fmt and a view print it unchanged.

func (UF) Valid

func (v UF) Valid() bool

Valid reports whether v is one of the units.

func (UF) Value

func (v UF) Value() (driver.Value, error)

Value implements driver.Valuer. It refuses a code outside the set, which is what keeps a zero-valued struct from putting an empty string in the column.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL