Using setlocale() doesn't affect PHPs number conversions - php

I have the following script:
<?php
$test = "2.5";
echo (float)$test;
echo "\n";
$r = setlocale(LC_ALL, "da_DK.UTF8");
setlocale(LC_ALL, NULL);
print_r(localeconv());
echo "\n";
echo (float)$test;
echo "\n";
echo (float)"2,5";
echo "\n";
?>
Which generates the following output:
2.5
Array
(
[decimal_point] => ,
[thousands_sep] => .
[int_curr_symbol] => DKK
[currency_symbol] => kr
[mon_decimal_point] => ,
[mon_thousands_sep] => .
[positive_sign] =>
[negative_sign] => -
[int_frac_digits] => 2
[frac_digits] => 2
[p_cs_precedes] => 1
[p_sep_by_space] => 2
[n_cs_precedes] => 1
[n_sep_by_space] => 2
[p_sign_posn] => 4
[n_sign_posn] => 4
[grouping] => Array
(
[0] => 3
[1] => 3
)
[mon_grouping] => Array
(
[0] => 3
[1] => 3
)
)
2,5
2
The very last line which reads 2 - I would have expected that to read 2,5 - and as far as I can see on the PHP documentation, it should.
If the second call to setlocale is omitted then the output of localeconv() is inconsistent with the danish locale - for reasons that are unclear to me.

(float)"2,5" equals 2 (note the comma) whereas (float)"2.5" equals 2.5. The reason can be read in the manual:
If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.
Type casting is not affected by setlocale().

Related

Get two words (numbers) around a certain text in a string

There's a certain contents (from a webpage) where I need to get two numbers of a certain list.
Basically the list goes like:
..... 10 from 12....
..... 1 from 20....
..... 20 from 100...
and so on. For me, I need to get these numbers surrounding the word "from", so I can perform certain calculations with them later.
I looked into this and tried different ways to perform it with strpos or strstr but nothing worked. Does anyone have any idea how to accomplish something like that?
$text = "..... 10 from 12 etc....
..... 1 from 20....
..... 20 from 100...";
$r = preg_match_all('~(\d+) *from *(\d+)~u',$text,$match, PREG_SET_ORDER);
var_export($match);
Output:
array (
0 =>
array (
0 => '10 from 12',
1 => '10',
2 => '12',
),
1 =>
array (
0 => '1 from 20',
1 => '1',
2 => '20',
),
2 =>
array (
0 => '20 from 100',
1 => '20',
2 => '100',
),
)
Explanations:
\d+ one digit or more
(\d+) the sequence in brackets -> the digits in the result array
* no, one or more spaces
from the word from
Here is an example of what you can do with explode:
<?php
/* the text with many different gaps and mess! */
$text = "wlfsdjf;sd sdfljsdfk kfgjdlg d 10 from 200 kflgjdkgdklgsd slfksjd
dfgdf fgdlkjdf d 20 from 30 ldk;lfsd
dflksdjf 40 from 50 dkf;sd sdjfs ";
/* main array */
$array = explode("\n",$text);
echo '<pre>';
print_r($array);
/* looping and clearing out our values per line */
foreach($array as $k => $line){
$f = explode(" ",explode(" from ",$line)[0]);
$f = array_pop($f);
$numbers[$k]['first'] = $f;
$s = explode(" ",explode(" from ",$line)[1]);
$s = $s[0];
$numbers[$k]['second'] = $s;
}
/* our new array set per line */
print_r($numbers);
Will return:
Array
(
[0] => wlfsdjf;sd sdfljsdfk kfgjdlg d 10 from 200 kflgjdkgdklgsd slfksjd
[1] => dfgdf fgdlkjdf d 20 from 30 ldk;lfsd
[2] => dflksdjf 40 from 50 dkf;sd sdjfs
)
Array
(
[0] => Array
(
[first] => 10
[second] => 200
)
[1] => Array
(
[first] => 20
[second] => 30
)
[2] => Array
(
[first] => 40
[second] => 50
)
)

PHP locale with money_format not working with fr_CA

I have this simple code:
<?php
setlocale('LC_MONETARY', 'fr_CA.UTF-8');
echo money_format('%+#10n', '-4562.75834');
print_r(localeconv());
?>
Who normally should give -4 562,76 $. But the result is always this:
(4 562,76 $)
The output of localeconv():
Array
(
[decimal_point] => .
[thousands_sep] =>
[int_curr_symbol] => CAD
[currency_symbol] => $
[mon_decimal_point] => ,
[mon_thousands_sep] =>
[positive_sign] =>
[negative_sign] => -
[int_frac_digits] => 2
[frac_digits] => 2
[p_cs_precedes] => 0
[p_sep_by_space] => 1
[n_cs_precedes] => 0
[n_sep_by_space] => 1
[p_sign_posn] => 1
[n_sign_posn] => 0
[grouping] => Array
(
)
[mon_grouping] => Array
(
[0] => 3
[1] => 3
)
)
We can see that negative sign should be - but not ()
The locale on the server (which is Debian 7), is installed:
# locale-gen
Generating locales (this might take a while)...
en_CA.UTF-8... done
fr_CA.ISO-8859-1... done
fr_CA.UTF-8... done
Generation complete.
I have tried with PHP 5.4.45 and 5.6.17
You have put the LC_MONETARY between single quotes.
It needs to live as a const variable which is set as not in quotes.
setlocale(LC_MONETARY, 'fr_CA.UTF-8');

Order Array by 2nd value

I have an array as follows
Array
(
[1845267] => 2
[1845256] => 2
[1845260] => 2
[33636] => 1
[67376] => 2
[73250] => 1
[125313] => 2
[142062] => 1
[342520] => 2
[357301] => 2
[357303] => 1
[404419] => 1
[408957] => 1
[415891] => 2
[455894] => 1
[460119] => 1
[582332] => 1
[582333] => 1
[602886] => 1
)
My aim is to order them by the single digit value so the output would put the 2's(or highest number) to the top
Array
(
[1845267] => 2
[1845256] => 2
[1845260] => 2
[415891] => 2
[125313] => 2
[67376] => 2
[342520] => 2
[357301] => 2
[33636] => 1
[73250] => 1
[142062] => 1
[357303] => 1
[404419] => 1
[408957] => 1
[455894] => 1
[460119] => 1
[582332] => 1
[582333] => 1
[602886] => 1
)
Try with the arsort function:
arsort — Sort an array in reverse order and maintain index association
Example:
arsort($array);
// done, $array is now sorted
Built into PHP: http://php.net/manual/en/function.arsort.php
bascially you need toh known array function for php from here
and function as
arsort($arr);
Simple
arsort($array)
http://www.php.net/manual/en/function.arsort.php

PHP: Determine number of characters that come before a dash in a string

If I have a bunch of strings like XXX-WYC-5b, where XXX is any value between 1 and 999, how do I determine the length of XXX?
So I might have:
1: 6-WYC-5b
2: 32-WYC-5b
3: 932-W-5b
4: 22-XYQ-5b
5: 914-WYC-5b
And I want it to tell me the length of XXX, so:
1: 1 character
2: 2 characters
3: 3 characters
4: 2 characters
5: 3 characters
I would also like to know the value itself, so:
1: 6
2: 32
3: 932
4: 22
5: 914
I keep thinking there's a way to do this using substr_count() and explode(), but I can't seem to figure it out. Thanks very much for your help.
Use PHP's built-in string position function. Because it starts counting at 0, you don't even have to adjust the output:
$pos = strpos($string, "-");
For the second part, use PHP's substring function:
return substr($string, 0, $pos);
a different approach you may want to try:
<?php
$str[] = '6-WYC-5b';
$str[] = '32-WYC-5b';
$str[] = '932-W-5b';
$str[] = '22-XYQ-5b';
$str[] = '914-WYC-5b';
foreach($str as $v){
$result[] = getval($v);
}
function getval($value){
$seg = explode('-',$value);
return array('int'=>$seg[0],'intlen'=>strlen($seg[0]),'char'=>$seg[1],'charlen'=>strlen($seg[1]),'last'=>$seg[2],'lastlen'=>strlen($seg[2]));
}
print_r($result);
?>
outputs:
Array
(
[0] => Array
(
[int] => 6
[intlen] => 1
[char] => WYC
[charlen] => 3
[last] => 5b
[lastlen] => 2
)
[1] => Array
(
[int] => 32
[intlen] => 2
[char] => WYC
[charlen] => 3
[last] => 5b
[lastlen] => 2
)
[2] => Array
(
[int] => 932
[intlen] => 3
[char] => W
[charlen] => 1
[last] => 5b
[lastlen] => 2
)
[3] => Array
(
[int] => 22
[intlen] => 2
[char] => XYQ
[charlen] => 3
[last] => 5b
[lastlen] => 2
)
[4] => Array
(
[int] => 914
[intlen] => 3
[char] => WYC
[charlen] => 3
[last] => 5b
[lastlen] => 2
)
)

Get currency ISO 4217 code based on locale

Say, if I parse HTTP Accept-Language header with Locale::acceptFromHttp is there an easy and reliable way to get user's preferred currency based on this locale identifier? Like "USD" for "en-US".
I wish there was a way to do this with PHP intl extension but so far was unable to find my answer in the manual. I saw Zend Framework can do this with Zend_Currency but it's just too bloated for my particular software.
Any other libs or ways of achieving this? Since there must be a lot of locale identifiers a simple switch is a bit of overkill.
You can do this in both PHP 4 and PHP 5 using setlocale() and localeconv():
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
setlocale(LC_MONETARY, $locale);
print_r(localeconv());
Sample output:
Array
(
[decimal_point] => .
[thousands_sep] =>
[int_curr_symbol] => EUR
[currency_symbol] => €
[mon_decimal_point] => ,
[mon_thousands_sep] =>
[positive_sign] =>
[negative_sign] => -
[int_frac_digits] => 2
[frac_digits] => 2
[p_cs_precedes] => 1
[p_sep_by_space] => 1
[n_cs_precedes] => 1
[n_sep_by_space] => 1
[p_sign_posn] => 1
[n_sign_posn] => 2
[grouping] => Array
(
)
[mon_grouping] => Array
(
[0] => 3
[1] => 3
)
)
The ISO 4217 code is contained within the resulting array's int_curr_symbol key.
A bit late but you can get it with \NumberFormatter:
<?php
$currencyPerLocale = array_reduce(
\ResourceBundle::getLocales(''),
function (array $currencies, string $locale) {
$currencies[$locale] = \NumberFormatter::create(
$locale,
\NumberFormatter::CURRENCY
)->getTextAttribute(\NumberFormatter::CURRENCY_CODE);
return $currencies;
},
[]
);

Categories