lib/extenso_pt.rb in extenso_pt-0.5.3 vs lib/extenso_pt.rb in extenso_pt-0.5.4
- old
+ new
@@ -1,209 +1,296 @@
# frozen_string_literal: true
require 'extenso_pt/version'
require 'bigdecimal/util'
-# @author Hernâni Rodrigues Vaz
+LC = %i[pt br].freeze
+A0020 = {
+ pt: ['', 'UM', 'DOIS', 'TRÊS', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
+ 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'CATORZE',
+ 'QUINZE', 'DEZASSEIS', 'DEZASSETE', 'DEZOITO', 'DEZANOVE'],
+ br: ['', 'UM', 'DOIS', 'TRES', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
+ 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'QUATORZE',
+ 'QUINZE', 'DEZESSEIS', 'DEZESSETE', 'DEZOITO', 'DEZENOVE']
+}.freeze
+A0100 = {
+ pt: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
+ 'SETENTA', 'OITENTA', 'NOVENTA'],
+ br: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
+ 'SETENTA', 'OITENTA', 'NOVENTA']
+}.freeze
+A1000 = {
+ pt: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
+ 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS'],
+ br: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
+ 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS']
+}.freeze
+A1E24 = {
+ pt: ['', 'MIL', ' MILHÃO', ' MIL MILHÃO', ' BILIÃO', ' MIL BILIÃO',
+ ' TRILIÃO', ' MIL TRILIÃO', '', ' MIL', ' MILHÕES', ' MIL MILHÕES',
+ ' BILIÕES', ' MIL BILIÕES', ' TRILIÕES', ' MIL TRILIÕES'],
+ br: ['', 'MIL', ' MILHÃO', ' BILHÃO', ' TRILHÃO', ' QUADRILHÃO',
+ ' QUINTILHÃO', ' SEXTILHÃO', '', ' MIL', ' MILHÕES', ' BILHÕES',
+ ' TRILHÕES', ' QUADRILHÕES', ' QUINTILHÕES', ' SEXTILHÕES']
+}.freeze
+
+# @author Hernani Rodrigues Vaz
module ExtensoPt
class Error < StandardError; end
- LC = %i[pt br].freeze
- A0020 = { pt: ['', 'UM', 'DOIS', 'TRÊS', 'QUATRO', 'CINCO', 'SEIS', 'SETE', 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'CATORZE', 'QUINZE', 'DEZASSEIS', 'DEZASSETE', 'DEZOITO', 'DEZANOVE'],
- br: ['', 'UM', 'DOIS', 'TRES', 'QUATRO', 'CINCO', 'SEIS', 'SETE', 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'QUATORZE', 'QUINZE', 'DEZESSEIS', 'DEZESSETE', 'DEZOITO', 'DEZENOVE'] }.freeze
- A0100 = { pt: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA', 'SETENTA', 'OITENTA', 'NOVENTA'],
- br: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA', 'SETENTA', 'OITENTA', 'NOVENTA'] }.freeze
- A1000 = { pt: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS', 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS'],
- br: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS', 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS'] }.freeze
- A1e24 = { pt: ['', 'MIL', ' MILHÃO', ' MIL MILHÃO', ' BILIÃO', ' MIL BILIÃO', ' TRILIÃO', ' MIL TRILIÃO', '', ' MIL', ' MILHÕES', ' MIL MILHÕES', ' BILIÕES', ' MIL BILIÕES', ' TRILIÕES', ' MIL TRILIÕES'],
- br: ['', 'MIL', ' MILHÃO', ' BILHÃO', ' TRILHÃO', ' QUADRILHÃO', ' QUINTILHÃO', ' SEXTILHÃO', '', ' MIL', ' MILHÕES', ' BILHÕES', ' TRILHÕES', ' QUADRILHÕES', ' QUINTILHÕES', ' SEXTILHÕES'] }.freeze
-
- # Produz o extenso das centenas em portugûes de portugal ou brasil.
+ # Produz o extenso das centenas em portugues de portugal ou brasil.
#
# @param [Integer] mil o valor dum grupo 3 digitos a converter
# @return [String] o extenso das centenas
def self.e900(mil)
- A1000[@@lc][(mil > 100 ? 1 : 0) + mil / 100] + (mil > 100 && mil % 100 > 0 ? ' E ' : '')
+ A1000[@lc][(mil > 100 ? 1 : 0) + mil / 100] +
+ (mil > 100 && (mil % 100).positive? ? ' E ' : '')
end
- # Produz o extenso das dezenas em portugûes de portugal ou brasil.
+ # Produz o extenso das dezenas em portugues de portugal ou brasil.
#
# @param [Integer] mil o valor dum grupo 3 digitos a converter
# @return [String] o extenso das dezenas
def self.e90(mil)
- A0100[@@lc][mil % 100 / 10] + (mil > 20 && mil % 10 > 0 ? ' E ' : '')
+ A0100[@lc][mil % 100 / 10] + (mil > 20 && (mil % 10).positive? ? ' E ' : '')
end
- # Produz o extenso das unidades em portugûes de portugal ou brasil.
+ # Produz o extenso das unidades em portugues de portugal ou brasil.
#
- # @param [Integer] mil o valor dum grupo 3 digitos a converter
+ # @param [Integer] cem o valor dum grupo 3 digitos a converter
# @return [String] o extenso das unidades
def self.e9(cem)
- A0020[@@lc][(cem < 20 ? cem : cem % 10)]
+ A0020[@lc][(cem < 20 ? cem : cem % 10)]
end
- # Produz o qualificador grupo de 3 digitos em portugûes de portugal ou brasil.
+ # Produz extenso parte fracionaria em portugues de portugal ou brasil.
#
- # @param [Integer] pos posição actual nos grupos 3 digitos do valor monetário
- # @return [String] o qualificador grupo de 3 digitos
- def self.e1e24(pos)
- A1e24[@@lc][@@ai[pos] > 0 ? @@ai[pos] > 1 ? 8 + pos : 0 + pos : 0]
- end
-
- # Produz o extenso da parte fracionária dum valor monetário em portugûes de portugal ou brasil.
- #
- # @return [String] o extenso da parte fracionária dum valor monetário
+ # @return [String] o extenso da parte fracionaria dum valor monetario
def self.ef99
- e90(@@nf) + e9(@@nf) + (@@nf == 1 ? ' ' + @@cs : @@nf > 1 ? ' ' + @@cp : '')
+ if @nf.positive?
+ e90(@nf) + e9(@nf) + (@nf > 1 ? ' ' + @cp : ' ' + @cs)
+ else
+ ''
+ end
end
- # Produz final da moeda em portugûes de portugal ou brasil.
+ # Produz final da moeda em portugues de portugal ou brasil.
#
# @return [String] o final da moeda
def self.efim
- # soma todos os grupos do valor monetário
- sto = @@s6 + @@m6
-
- (@@s6 == 0 && @@m6 > 0 ? ' DE' : '') + # proposição DE se zero nos primeiros 6 digitos e maiores que 1e6
- (sto == 1 ? ' ' + @@ms : sto > 1 ? ' ' + @@mp : '') + # singular/plural da moeda
- (sto > 0 && @@nf > 0 ? ' E ' : '') + # proposição E entre parte inteira e parte fracionária
- ef99 # extenso da parte fracionária dum valor monetário
+ # proposicao DE entre parte inteira e moeda
+ emo = @de ? ' DE' : ''
+ # moeda singular/plural
+ emo += @tt > 1 ? ' ' + @mp : ' ' + @ms if @tt.positive?
+ # proposicao E entre moeda e parte fracionaria
+ # extenso da parte fracionaria
+ emo + (@tt.positive? && @nf.positive? ? ' E ' : '') + ef99
end
- # Produz o extenso grupo 3 digitos em portugûes de portugal ou brasil.
+ # Produz separador entre grupos 3 digitos
#
- # @param [Integer] pos posição actual nos grupos 3 digitos do valor monetário
- # @return [String] o extenso grupo 3 digitos
- def self.edg3(pos)
- # extenso do grupo actual 3 digitos
- pos == 1 && @@ai[pos] == 1 ? e1e24(pos) : e900(@@ai[pos]) + e90(@@ai[pos]) + e9(@@ai[pos] % 100) + e1e24(pos)
- end
-
- # Produz separação entre grupos 3 digitos
- #
- # @param [Integer] pos posição actual nos grupos 3 digitos do valor monetário
- # @return [String] separação entre grupos 3 digitos
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
+ # @return [String] separador entre grupos 3 digitos
def self.esep(pos)
- pos > 0 ? @@ai[pos - 1] > 100 ? ' ' : @@ai[pos - 1] > 0 ? ' E ' : '' : ''
+ if pos.positive? && @ai[pos - 1].positive?
+ @ai[pos - 1] > 100 ? ' ' : ' E '
+ else
+ ''
+ end
end
- # Parametrizar grupos 3 digitos para controle de singular/plural
+ # Produz qualificador grupo de 3 digitos em portugues de portugal ou brasil.
#
- def self.pdg3
- @@s6 = @@ai[0].to_i + @@ai[1].to_i * 2 # soma grupos 1,2 (primeiros 6 digitos)
- @@m6 = @@ai[2..-1].to_a.inject(:+).to_i * 2 # soma grupos 3.. (digitos acima de 6)
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
+ # @return [String] qualificador grupo de 3 digitos
+ def self.e1e24(pos)
+ if @ai[pos].positive?
+ A1E24[@lc][@ai[pos] > 1 ? 8 + pos : pos]
+ else
+ ''
+ end
end
- # Parametrizar parte inteira/fracionária do valor monetário
+ # Produz extenso grupo 3 digitos em portugues de portugal ou brasil.
#
- # @param [String] dig string de digitos do valor monetário
- def self.pintfra(dig)
- # parte inteira do valor monetário => array grupos 3 digitos ex: 123022.12 => [22, 123]
- @@ai = dig[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map { |i| i.reverse.to_i }
-
- # parte fracionária do valor monetário ex: 123022.12 => 12
- # arredondada a 2 casas decimais (cêntimos/centavos)
- @@nf = (dig[/\.\d*/].to_f * 100).round
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
+ # @return [String] extenso grupo 3 digitos
+ def self.edg3(pos)
+ dg3 = if pos == 1 && @ai[pos] == 1
+ # caso especial MIL EUROS
+ ''
+ else
+ e900(@ai[pos]) + e90(@ai[pos]) + e9(@ai[pos] % 100)
+ end
+ # qualificador grupo de 3 digitos
+ dg3 + e1e24(pos)
end
- private_class_method :pintfra, :pdg3, :esep, :edg3, :e1e24, :e900, :e90, :e9, :ef99, :efim
-
- # Parametrizar moeda inferindo singular a partir do plural
+ # Parametrizar controle singular/plural & proposicoes
#
- # @param [Hash] moeda as opcoes para parametrizar a moeda/fração
- # @option moeda [Symbol] :lc locale do extenso - portugûes de portugal (:pt) ou brasil (:br)
- # @option moeda [String] :msingular moeda no singular - pode ser inferido do plural menos "S"
- # @option moeda [String] :fsingular fração no singular - pode ser inferido do plural menos "S"
- # @option moeda [String] :mplural moeda no plural
- # @option moeda [String] :fplural fração no plural
- def self.isingular(moeda)
- @@ms = moeda[:msingular] || (moeda[:mplural].to_s[-1] == 'S' ? moeda[:mplural][0..-2] : 'EURO')
- @@cs = moeda[:fsingular] || (moeda[:fplural].to_s[-1] == 'S' ? moeda[:fplural][0..-2] : 'CÊNTIMO')
+ def self.pcontrolo
+ # soma grupos 1,2 (primeiros 6 digitos)
+ @s6 = @ai[0].to_i + @ai[1].to_i * 2
+ # soma grupos 3.. (digitos acima de 6)
+ @m6 = @ai[2..-1].to_a.inject(:+).to_i * 2
+ @tt = @s6 + @m6 # proposicao E & singular/plural
+ @de = @s6.zero? && @m6.positive? # proposicao DE
end
- # Parametrizar moeda inferindo plural a partir do singular
+ # Produz o extenso dum valor monetario em portugues de portugal ou brasil.
#
- # @param [Hash] moeda as opcoes para parametrizar a moeda/fração
- # @option moeda [Symbol] :lc locale do extenso - portugûes de portugal (:pt) ou brasil (:br)
- # @option moeda [String] :msingular moeda no singular
- # @option moeda [String] :fsingular fração no singular
- # @option moeda [String] :mplural moeda no plural - pode ser inferido do singular mais "S"
- # @option moeda [String] :fplural fração no plural - pode ser inferido do singular mais "S"
- def self.iplural(moeda)
- @@mp = moeda[:mplural] || @@ms + 'S'
- @@cp = moeda[:fplural] || @@cs + 'S'
- end
-
- # Produz o extenso dum valor monetário em portugûes de portugal ou brasil.
- #
- # @param [Integer] pos posição actual nos grupos 3 digitos do valor monetário
- # @param [String] ext extenso actual em construção
- # @return [String] o extenso dum valor monetário
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
+ # @param [String] ext extenso em construcao
+ # @return [String] o extenso dum valor monetario
def self.enumerico(pos = 0, ext = '')
- # testa fim do valor monetário
- if pos >= @@ai.count
- # parametrizar grupos 3 digitos (@@s6, @@m6) para controle de singular/plural
- pdg3
+ # testa fim do valor monetario
+ if pos >= @ai.count
+ # parametrizar controle singular/plural & proposicoes
+ pcontrolo
# caso especial zero
- @@s6 == 0 && @@m6 == 0 && @@nf == 0 ? 'ZERO ' + @@mp : ext + efim
+ (@tt + @nf).zero? ? 'ZERO ' + @mp : ext + efim
else
# tratamento do proximo grupo 3 digitos
enumerico(pos + 1, edg3(pos) + esep(pos) + ext)
end
end
- # Converte um objeto criando extenso(s) em portugûes de portugal ou brasil.
+ # Parametrizar parte inteira/fracionaria do valor monetario
#
- # @param [Object] objeto o objeto a converter pode ser (String, Float, Integer, Array, Range, Hash) ou uma mistura
- # @return [String, Array<String>, Hash<String>] extenso se o objecto for (String, Float, Integer), Array dos extensos se o objecto for (Array, Range) ou Hash dos extensos se o objecto for (Hash)
+ # @param [String] dig string de digitos rdo valor monetario
+ def self.pintfra(dig)
+ # parte inteira do valor monetario => array grupos 3 digitos
+ # ex: 123022.12 => [22, 123]
+ @ai = dig[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map { |i| i.reverse.to_i }
+
+ # parte fracionaria do valor monetario
+ # ex: 123022.12 => 12
+ # arredondada a 2 casas decimais (centimos/centavos)
+ @nf = (dig[/\.\d*/].to_f * 100).round
+ end
+
+ private_class_method :pintfra, :pcontrolo, :esep, :edg3, :e1e24,
+ :e900, :e90, :e9, :ef99, :efim
+
+ # Converte um objeto criando extenso(s) em portugues de portugal ou brasil.
+ #
+ # @param [Object] objeto objeto a converter
+ # (String, Float, Integer, Array, Range, Hash)
+ # @return [String] extenso se objecto for (String, Float, Integer),
+ # Array<extensos> se objecto for (Array, Range),
+ # Hash<extensos> se objecto for (Hash)
def self.pobjeto(obj)
if obj.is_a?(Hash)
- # converte os valores do Hash nos seus extensos mantendo as chaves - devolve um Hash
+ # converte os valores do Hash nos seus extensos - devolve um Hash
obj.map { |k, v| [k, pobjeto(v)] }.to_h
- elsif obj.respond_to? :to_a
- # converte o objecto num Array e converte os valores do Array nos seus extensos - devolve um Array
+ elsif obj.respond_to?(:to_a)
+ # converte o objecto num Array com os extensos dos valores
obj.to_a.map { |v| pobjeto(v) }
else
# converte objeto numa string de digitos
- # usa bigdecimal/util para evitar aritmética binária (tem problemas com valores >1e12)
- # qualquer valor não convertivel (ex: texto) resulta em "0.0"
+ # usa bigdecimal/util para evitar aritmetica binaria
+ # (tem problemas com valores >1e12)
+ # qualquer valor nao convertivel (ex: texto) resulta em "0.0"
sdigitos = obj.to_d.to_s('F')
- # parametrizar parte inteira/fracionária (@@ai, @@nf) do valor monetário
+ # parametrizar parte inteira/fracionaria (@ai, @nf) do valor monetario
pintfra(sdigitos)
- # processar extenso - valores superiores a 1e24 não são tratados
+ # processar extenso - valores superiores a 1e24 nao sao tratados
sdigitos[/^\d+/].length <= 24 ? enumerico : ''
end
end
- # Produz extenso(s) de objeto(s) em portugûes de portugal ou brasil.
+ # Parametrizar moeda inferindo singular a partir do plural
#
- # @param [Hash] moeda as opcoes para parametrizar a moeda/fração
- # @option moeda [Symbol] :lc locale do extenso - portugûes de portugal (:pt) ou brasil (:br)
- # @option moeda [String] :msingular moeda no singular
- # @option moeda [String] :fsingular fração no singular
+ # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
+ # @option moeda [Symbol] :lc locale do extenso -
+ # portugues de portugal (:pt) ou brasil (:br)
+ # @option moeda [String] :msingular moeda no singular -
+ # inferido do plural menos "S"
+ # @option moeda [String] :fsingular fracao no singular -
+ # inferido do plural menos "S"
# @option moeda [String] :mplural moeda no plural
- # @option moeda [String] :fplural fração no plural
- # @return [String, Array<String>, Hash<String>] extenso se o objecto for (String, Float, Integer), Array dos extensos se o objecto for (Array, Range) ou Hash dos extensos se o objecto for (Hash)
- def extenso(moeda = { lc: :pt, msingular: 'EURO', fsingular: 'CÊNTIMO' })
- # parametrização por defeito para :br
- moeda = { lc: :br, msingular: 'REAL', mplural: 'REAIS', fsingular: 'CENTAVO' } if moeda[:lc] == :br && !moeda[:msingular] && !moeda[:mplural]
+ # @option moeda [String] :fplural fracao no plural
+ def self.isingular(moeda)
+ @ms = moeda[:msingular] ||
+ (moeda[:mplural].to_s[-1] == 'S' ? moeda[:mplural][0..-2] : 'EURO')
+ @cs = moeda[:fsingular] ||
+ (moeda[:fplural].to_s[-1] == 'S' ? moeda[:fplural][0..-2] : 'CÊNTIMO')
+ end
+ # Parametrizar moeda inferindo plural a partir do singular
+ #
+ # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
+ # @option moeda [Symbol] :lc locale do extenso -
+ # portugues de portugal (:pt) ou brasil (:br)
+ # @option moeda [String] :msingular moeda no singular
+ # @option moeda [String] :fsingular fracao no singular
+ # @option moeda [String] :mplural moeda no plural -
+ # inferido do singular mais "S"
+ # @option moeda [String] :fplural fracao no plural -
+ # inferido do singular mais "S"
+ def self.iplural(moeda)
# somente [:pt, :br]
- @@lc = LC.include?(moeda[:lc]) ? moeda[:lc] : :pt
+ @lc = LC.include?(moeda[:lc]) ? moeda[:lc] : :pt
+ @mp = moeda[:mplural] || @ms + 'S'
+ @cp = moeda[:fplural] || @cs + 'S'
+ end
+
+ # Produz extenso(s) de objeto(s) em portugues de portugal ou brasil.
+ #
+ # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
+ # @option moeda [Symbol] :lc locale do extenso -
+ # portugues de portugal (:pt) ou brasil (:br)
+ # @option moeda [String] :msingular moeda no singular
+ # @option moeda [String] :fsingular fracao no singular
+ # @option moeda [String] :mplural moeda no plural
+ # @option moeda [String] :fplural fracao no plural
+ # @return [String] extenso se objecto for (String, Float, Integer),
+ # Array<extensos> se objecto for (Array, Range),
+ # Hash<extensos> se objecto for (Hash)
+ def extenso(moeda = { lc: :pt, msingular: 'EURO', fsingular: 'CÊNTIMO' })
+ # parametrizacao por defeito para :br
+ if moeda[:lc] == :br && !moeda[:msingular] && !moeda[:mplural]
+ moeda.merge!(msingular: 'REAL', mplural: 'REAIS', fsingular: 'CENTAVO')
+ end
+
# parametrizar moeda
ExtensoPt.isingular(moeda)
ExtensoPt.iplural(moeda)
# processar objeto
ExtensoPt.pobjeto(self)
end
end
-class Hash; include ExtensoPt; end
-class Array; include ExtensoPt; end
-class Range; include ExtensoPt; end
-class Float; include ExtensoPt; end
-class Integer; include ExtensoPt; end
-class String; include ExtensoPt; end
+
+# permite obter um Hash com valores numericos convertidos nos seus extensos
+class Hash
+ include ExtensoPt
+end
+
+# permite obter um Array com valores numericos convertidos nos seus extensos
+class Array
+ include ExtensoPt
+end
+
+# permite obter um Array com valores numericos convertidos nos seus extensos
+class Range
+ include ExtensoPt
+end
+
+# permite obter o extenso dum Float
+class Float
+ include ExtensoPt
+end
+
+# permite obter o extenso dum Integer
+class Integer
+ include ExtensoPt
+end
+
+# permite obter o extenso duma String de digitos
+class String
+ include ExtensoPt
+end