Saturday, July 10, 2010

Кое-что об использовании локалей в перле

Столкнулся недавно с такой проблемой:  при подключении (use) некоторого модуля X, print и printf начинали использовать символ "," в качестве разделителя при печатании чисел с дробной частью. Модуль X использовал функцию POSIX::setlocale, после чего локаль менялась глобально.

Документация по данному вопросу откровенно врёт. Например perldoc -f printf говорит следующее:
If use locale is in effect, and POSIX::setlocale() has been called, the character used for the decimal separator in formatted floating-point numbers is affected by the LC_NUMERIC locale.

На самом деле, use locale для этого нафиг не нужна:
# perl -MPOSIX -e 'setlocale(LC_ALL,"ru_RU.CP1251"); printf "%.2f", 1.5'
1,5

В общем, получается, что установив  таким образом LC_NUMERIC в любом месте программы, мы меняем форматирование всех дробных чисел.

Во ибежание таких побочных эффектов, следует сохранять прежнюю локаль и восстанавливать ее в нужном месте программы.

Update: Еще один косяк - POSIX::strftime. Согласно документации

By default, Perl ignores the current locale. The use locale pragma tells Perl to use the current locale for some operations: ... The POSIX date formatting function (strftime()) uses LC_TIME .


Однако и для strftime "use locale" не нужна:

LANG=de_DE.UTF-8 perl -MPOSIX -E 'say strftime "%A %B %e %H:%M:%S %Y", localtime'
Dienstag März 15 17:19:54 2011


Все потому, что функция С strftime использует текущую локаль, и Perl особо не заморачивается с прагмой use locale.

No comments:

Post a Comment