Thread: to_char with locale decimal separator

to_char with locale decimal separator

From
Ingmar Brouns
Date:
Hi,

I need to convert some numerical values to text using the decimal
separator that corresponds to the current locale. However, I do
not want to lose information by padding with zero decimals or
truncating zero decimals. So I basically want a text cast that
also replaces the dot by a comma. I've looked at the to_char
function and the formatting patterns, but when using those I
either add or truncate zero decimals.


# show lc_numeric;
 lc_numeric
------------
 nl_NL.utf8
(1 row)

# select 1.500::text;
 text
-------
 1.500
(1 row)

# select to_char(1.500, '999999D99999999');
     to_char
------------------
       1,50000000
(1 row)

# select to_char(1.500, 'FM999999D99999999');
 to_char
---------
 1,5
(1 row)


I would like to have '1,500' as the output, what is the best way
to achieve this?

Thanks in advance,

Ingmar


Re: to_char with locale decimal separator

From
Ingmar Brouns
Date:
On Mon, Jul 29, 2013 at 1:24 PM, Ingmar Brouns <swingi@gmail.com> wrote:
> Hi,
>
> I need to convert some numerical values to text using the decimal
> separator that corresponds to the current locale. However, I do
> not want to lose information by padding with zero decimals or
> truncating zero decimals. So I basically want a text cast that
> also replaces the dot by a comma. I've looked at the to_char
> function and the formatting patterns, but when using those I
> either add or truncate zero decimals.
>
>
> # show lc_numeric;
>  lc_numeric
> ------------
>  nl_NL.utf8
> (1 row)
>
> # select 1.500::text;
>  text
> -------
>  1.500
> (1 row)
>
> # select to_char(1.500, '999999D99999999');
>      to_char
> ------------------
>        1,50000000
> (1 row)
>
> # select to_char(1.500, 'FM999999D99999999');
>  to_char
> ---------
>  1,5
> (1 row)
>

Maybe its important to add that the nr of decimals in the values
is variable. I could of course adjust the pattern to work for
1.500, but I'm looking for a solution that will work with an
arbitrary numerical value and that's a little more elegant than
casting to text, and then replacing the dot by a comma.


>
> I would like to have '1,500' as the output, what is the best way
> to achieve this?
>
> Thanks in advance,
>
> Ingmar


Re: to_char with locale decimal separator

From
Adrian Klaver
Date:
On 07/29/2013 04:24 AM, Ingmar Brouns wrote:
> Hi,
>
> I need to convert some numerical values to text using the decimal
> separator that corresponds to the current locale. However, I do
> not want to lose information by padding with zero decimals or
> truncating zero decimals. So I basically want a text cast that
> also replaces the dot by a comma. I've looked at the to_char
> function and the formatting patterns, but when using those I
> either add or truncate zero decimals.
>
>
> # show lc_numeric;
>   lc_numeric
> ------------
>   nl_NL.utf8
> (1 row)
>
> # select 1.500::text;
>   text
> -------
>   1.500
> (1 row)
>
> # select to_char(1.500, '999999D99999999');
>       to_char
> ------------------
>         1,50000000
> (1 row)
>
> # select to_char(1.500, 'FM999999D99999999');
>   to_char
> ---------
>   1,5
> (1 row)
>
>
> I would like to have '1,500' as the output, what is the best way
> to achieve this?

This work?:

test=> select replace(1.500::text, '.', ',');
  replace
---------
  1,500
(1 row)


>
> Thanks in advance,
>
> Ingmar
>
>


--
Adrian Klaver
adrian.klaver@gmail.com


Re: to_char with locale decimal separator

From
Ingmar Brouns
Date:
On Mon, Jul 29, 2013 at 3:45 PM, Adrian Klaver <adrian.klaver@gmail.com> wrote:
> On 07/29/2013 04:24 AM, Ingmar Brouns wrote:
>>
>> Hi,
>>
>> I need to convert some numerical values to text using the decimal
>> separator that corresponds to the current locale. However, I do
>> not want to lose information by padding with zero decimals or
>> truncating zero decimals. So I basically want a text cast that
>> also replaces the dot by a comma. I've looked at the to_char
>> function and the formatting patterns, but when using those I
>> either add or truncate zero decimals.
>>
>>
>> # show lc_numeric;
>>   lc_numeric
>> ------------
>>   nl_NL.utf8
>> (1 row)
>>
>> # select 1.500::text;
>>   text
>> -------
>>   1.500
>> (1 row)
>>
>> # select to_char(1.500, '999999D99999999');
>>       to_char
>> ------------------
>>         1,50000000
>> (1 row)
>>
>> # select to_char(1.500, 'FM999999D99999999');
>>   to_char
>> ---------
>>   1,5
>> (1 row)
>>
>>
>> I would like to have '1,500' as the output, what is the best way
>> to achieve this?
>
>
> This work?:
>
> test=> select replace(1.500::text, '.', ',');
>  replace
> ---------
>  1,500
> (1 row)
>


that would work, but that requires keeping track of which decimal
separator to use yourself.  If you change the locale, the code
has to change as well. As to_char already converts the decimal
separator in a locale aware manner, I wonder whether there is a
way to do this using the existing locale facilities.

Ingmar


Re: to_char with locale decimal separator

From
Adrian Klaver
Date:
On 07/29/2013 07:27 AM, Ingmar Brouns wrote:
> On Mon, Jul 29, 2013 at 3:45 PM, Adrian Klaver <adrian.klaver@gmail.com> wrote:
>> On 07/29/2013 04:24 AM, Ingmar Brouns wrote:
>>>
>>> Hi,

>>
>> This work?:
>>
>> test=> select replace(1.500::text, '.', ',');
>>   replace
>> ---------
>>   1,500
>> (1 row)
>>
>
>
> that would work, but that requires keeping track of which decimal
> separator to use yourself.  If you change the locale, the code
> has to change as well. As to_char already converts the decimal
> separator in a locale aware manner, I wonder whether there is a
> way to do this using the existing locale facilities.

Sorry, I just got to your second post where you explained that. I can't
think of a way at the moment.

>
> Ingmar
>
>


--
Adrian Klaver
adrian.klaver@gmail.com


Re: to_char with locale decimal separator

From
Ingmar Brouns
Date:
On Mon, Jul 29, 2013 at 3:12 PM, Ingmar Brouns <swingi@gmail.com> wrote:
> On Mon, Jul 29, 2013 at 1:24 PM, Ingmar Brouns <swingi@gmail.com> wrote:
>> Hi,
>>
>> I need to convert some numerical values to text using the decimal
>> separator that corresponds to the current locale. However, I do
>> not want to lose information by padding with zero decimals or
>> truncating zero decimals. So I basically want a text cast that
>> also replaces the dot by a comma. I've looked at the to_char
>> function and the formatting patterns, but when using those I
>> either add or truncate zero decimals.
>>
>>
>> # show lc_numeric;
>>  lc_numeric
>> ------------
>>  nl_NL.utf8
>> (1 row)
>>
>> # select 1.500::text;
>>  text
>> -------
>>  1.500
>> (1 row)
>>
>> # select to_char(1.500, '999999D99999999');
>>      to_char
>> ------------------
>>        1,50000000
>> (1 row)
>>
>> # select to_char(1.500, 'FM999999D99999999');
>>  to_char
>> ---------
>>  1,5
>> (1 row)
>>
>
> Maybe its important to add that the nr of decimals in the values
> is variable. I could of course adjust the pattern to work for
> 1.500, but I'm looking for a solution that will work with an
> arbitrary numerical value and that's a little more elegant than
> casting to text, and then replacing the dot by a comma.
>

anyone? Giving a locale corresponding textual representation
of a numerical value keeping the exact nr of decimal digits
must be a fairly common use case. Would it be an idea to
implement a to_char function that does not take a formatting
pattern and has this behaviour?

>
>>
>> I would like to have '1,500' as the output, what is the best way
>> to achieve this?
>>
>> Thanks in advance,
>>
>> Ingmar


Re: to_char with locale decimal separator

From
Adrian Klaver
Date:
On 07/30/2013 03:03 AM, Ingmar Brouns wrote:
> On Mon, Jul 29, 2013 at 3:12 PM, Ingmar Brouns <swingi@gmail.com> wrote:

>>
>
> anyone? Giving a locale corresponding textual representation
> of a numerical value keeping the exact nr of decimal digits
> must be a fairly common use case. Would it be an idea to
> implement a to_char function that does not take a formatting
> pattern and has this behaviour?
>

Best I can do is a proof of concept in plpythonu for determining locale
decimal point:

test=# SHOW lc_numeric ;
  lc_numeric
-------------
  en_US.UTF-8
(1 row)

test=# DO $$
     import locale
     rs = plpy.execute("SHOW lc_numeric")
     lc_n = rs[0]["lc_numeric"]
     locale.setlocale(locale.LC_NUMERIC, lc_n)
     d = locale.nl_langinfo(locale.RADIXCHAR)
     plpy.notice("Decimal point is " + d)
$$ LANGUAGE plpythonu;
NOTICE:  Decimal point is .
CONTEXT:  PL/Python anonymous code block
DO


test=# set lc_numeric = 'nl_NL.utf8';
SET
test=# DO $$
     import locale
     rs = plpy.execute("SHOW lc_numeric")
     lc_n = rs[0]["lc_numeric"]
     locale.setlocale(locale.LC_NUMERIC, lc_n)
     d = locale.nl_langinfo(locale.RADIXCHAR)
     plpy.notice("Decimal point is " + d)
$$ LANGUAGE plpythonu;
NOTICE:  Decimal point is ,
CONTEXT:  PL/Python anonymous code block
DO


>>
>>>
>>> I would like to have '1,500' as the output, what is the best way
>>> to achieve this?
>>>
>>> Thanks in advance,
>>>
>>> Ingmar
>
>


--
Adrian Klaver
adrian.klaver@gmail.com


Re: to_char with locale decimal separator

From
Ingmar Brouns
Date:
On Tue, Jul 30, 2013 at 4:42 PM, Adrian Klaver <adrian.klaver@gmail.com> wrote:
> On 07/30/2013 03:03 AM, Ingmar Brouns wrote:
>>
>> On Mon, Jul 29, 2013 at 3:12 PM, Ingmar Brouns <swingi@gmail.com> wrote:
>
>
>>>
>>
>> anyone? Giving a locale corresponding textual representation
>> of a numerical value keeping the exact nr of decimal digits
>> must be a fairly common use case. Would it be an idea to
>> implement a to_char function that does not take a formatting
>> pattern and has this behaviour?
>>
>
> Best I can do is a proof of concept in plpythonu for determining locale
> decimal point:
>
> test=# SHOW lc_numeric ;
>  lc_numeric
> -------------
>  en_US.UTF-8
> (1 row)
>
> test=# DO $$
>     import locale
>     rs = plpy.execute("SHOW lc_numeric")
>     lc_n = rs[0]["lc_numeric"]
>     locale.setlocale(locale.LC_NUMERIC, lc_n)
>     d = locale.nl_langinfo(locale.RADIXCHAR)
>     plpy.notice("Decimal point is " + d)
> $$ LANGUAGE plpythonu;
> NOTICE:  Decimal point is .
> CONTEXT:  PL/Python anonymous code block
> DO
>
>
> test=# set lc_numeric = 'nl_NL.utf8';
> SET
> test=# DO $$
>     import locale
>     rs = plpy.execute("SHOW lc_numeric")
>     lc_n = rs[0]["lc_numeric"]
>     locale.setlocale(locale.LC_NUMERIC, lc_n)
>     d = locale.nl_langinfo(locale.RADIXCHAR)
>     plpy.notice("Decimal point is " + d)
> $$ LANGUAGE plpythonu;
> NOTICE:  Decimal point is ,
> CONTEXT:  PL/Python anonymous code block
> DO
>

Thanks for your time, appreciate it! As a dirty alternative, you could also do
something like:

select translate(5.000::text,'.',substr(to_char(.0),2,1));

Not so nice, but would work. Though I still feel there should be a more
elegant of doing this...

>
>
>>>
>>>>
>>>> I would like to have '1,500' as the output, what is the best way
>>>> to achieve this?
>>>>
>>>> Thanks in advance,
>>>>
>>>> Ingmar
>>
>>
>>
>
>
> --
> Adrian Klaver
> adrian.klaver@gmail.com


Re: to_char with locale decimal separator

From
Adrian Klaver
Date:
On 07/30/2013 08:34 AM, Ingmar Brouns wrote:

>
> Thanks for your time, appreciate it! As a dirty alternative, you could also do
> something like:
>
> select translate(5.000::text,'.',substr(to_char(.0),2,1));
>
> Not so nice, but would work. Though I still feel there should be a more
> elegant of doing this...
>

Two issues.

1) Leading and trailing zeros tend to be a personal preference and what
and how many, even more so. Pre-canned implementations for formatting
seem to best guess. I could see where trying to cover every conceivable
possibility would get complex.

2) You where looking at converting variable precision values, not
uncommon, but adds a layer of complexity. For instance using the Python
locale module it is possible to have it format a number according to
locale and have trailing zeros, but it will pad to the specified
precision(6 by default). So you still need to track something, in this
case precision.

You could take your quick and dirty solution and put it in a
function(to_char_trailing(numeric) and hide the dirty part:)

>> --
>> Adrian Klaver
>> adrian.klaver@gmail.com


--
Adrian Klaver
adrian.klaver@gmail.com