How do I turn a thousand-comma separated string representation of an integer into an integer value in PHP? (is there a general way to do it for other separators too?)
e.g. 1,000 -> 1000
Edit (Thanks #ghost) Ideally, decimals should be handled, but I could accept a solution that truncates at a decimal point.
If thats simple as it gets you could use filter_var():
$number = '1,000';
$number = (int) filter_var($number, FILTER_SANITIZE_NUMBER_INT);
var_dump($number);
Or
$number = '1,000.5669';
$number = (float) str_replace(',', '', $number);
var_dump($number);
You can strip a specific character using str_replace, and cast as an integer using intval. A regular expression filter can also be used to determine if the input string is formatted correctly. Here is what that code might look like:
<?php
function remove_delimiters_simple($string, $delimiter = ',') {
// Removes all instances of the specified delimiter and cast as an integer
// Comma (,) is the default delimiter
return (int) str_replace($delimiter, '', $string);
}
function remove_delimiters_advanced($string, $delimiter = ',') {
// Use preg_quote in case our delimiter is '/' for some reason
// The regular expression should match validly formatted numbers using a delimiter
// every 3 characters
$valid_format_expression = sprintf(
'/^\d{1,3}(%s\d{3})*$/',
preg_quote($delimiter, '/')
);
// If not a validly formatted number, return null
if (! preg_match($valid_format_expression, $string)) {
return null;
}
// Otherwise, return the simple value
return remove_delimiters_simple($string, $delimiter);
}
If using PHP >= 5.3, you could use numfmt_create(), like:
$fmt = numfmt_create( 'nl_NL', NumberFormatter::TYPE_INT32 );
$num = "1,000";
echo numfmt_parse($fmt, $num); //gives 1000
Note::nl_NL is the locale you used in formatting number, and it should be the same when using for numfmt_create
Related
One of my script has the following function to return a float value from a text value consist with currency code.
function preformatFloat($value, $decimal_point = '.')
{
if ($decimal_point != '.' && strpos($value, $decimal_point)) {
$value = str_replace('.', '~', $value);
$value = str_replace($decimal_point, '.', $value);
}
return (float)preg_replace('/[^0-9\-\.]/', '', $value);
}
And if I run this function
echo preformatFloat("Rs.990.00",".");
I got the answer as 0.99 but I wanted to get the value as 990.00
I tried lot by modifying regex value but no luck.
Can you please help with this. Thank you
try this
function preformatFloat($string)
{
$precedingFullStop = strpos($string, ".");
$newString = substr($string, $precedingFullStop + 1);
return (float)preg_replace('/[^0-9\-\.]/', '', $newString);
}
echo preformatFloat("PKR.200.09");
Here is a different approach using a RegExp match. It tries to find the first valid (float) number and ignores anything else.
function parseFloatInput(
$value,
$decimal_separator = '.',
$thousand_separator = ','
) {
$pattern = '(
# define named templates for the separators,
# escape variable values for pattern
(?(DEFINE)(?<dp>'.preg_quote($decimal_separator).'))
(?(DEFINE)(?<tp>'.preg_quote($thousand_separator).'))
(
# at least one digit
(?:\d+)
# any repeat: a thousand separator followed by 3 digits
(?:(?&tp)?\d{3})*
# one or no: decimal separator followed by at least one digit
(?:(?&dp)?\d+)?
)
)x';
if (preg_match($pattern, $value, $match)) {
return (float)str_replace(
[$thousand_separator, $decimal_separator],
['', '.'],
$match[0]
);
}
return NAN;
}
var_dump(parseFloatInput("Rs.990.99","."));
var_dump(parseFloatInput("Rs.1,990.99","."));
var_dump(parseFloatInput("Rs.990.99",","));
var_dump(parseFloatInput("Rs.",","));
Output:
float(990.99)
float(1990.99)
float(990)
float(NAN)
Notes
/ is not the only possible delimiter. Any non alpha numeric character works. But only parentheses/brackets do not conflict with usage inside the pattern. So I prefer using () - reading it as group 0.
Modifier x for extended syntax. It allows to format and comment the pattern.
The separators are defined as templates, to improve the readability of the actual matching part.
My function trim_text would not give the trimmed words when using another function like dash_text. BUT giving a string directly to the trim_text would work!
function trim_text($data, $limit){
$words = str_word_count($data, 1);
$trim = (count($words) >= $limit)? array_slice($words, 0, $limit) : $words;
return implode(" ", $trim);
}
function dash_text($data){
$data = str_replace(' ','-',$data);
return $data;
}
$title = 'this is a test.';
$slug = trim_text(dash_text($title), 2);
var_dump($slug); //this will not return the trimmed words but instead return `this-is-a-test.`
//should return `this-is`
$slug = trim_text('this is a test', 2);
var_dump($slug); //but this would!
Also, if my methods are not the best practice(I'm not talking about security), tell me some suggestions to convert $title to lowered, trimmed and dashed string.
Its because this line of code:
$data = str_replace(' ','-',$data);
You are replacing space with dash.
Words separated concatenated by space are different.
e.g. In the string
this is a test., this, is, a, ... are words
But, concatenated with hypen (dash) are not different.
e.g. this-is-a-test
this-is-a-test is the only word.
So,
Change
trim_text(dash_text($title), 2);
To:
$slug = dash_text(trim_text($title, 2));
You should be calling $slug = dash_text(trim_text($title, 2));
instead of trim_text(dash_text($title), 2);
Explanation
In your case, the method dash_text($title) will be executed first, and it will return this-is-a-test.. The method trim_text is performed on this string. Hence it will return this-is-a-test. since there are no word separators in the input.
On the other hand, dash_text(trim_text($title, 2)); will perform trim_text first and will return this is. Then dash_text will be performed on this is and will return this-is.
The problem lies in the fact that str_word_count function does not count words separated by "-" as multiple words. See PHP documentation:
http://lv.php.net/str_word_count
For the purpose of this function, 'word' is defined as a locale dependent string containing alphabetic characters, which also may contain, but not start with "'" and "-" characters.
Due to the fact that you convert all of the spaces to "-" and then pass the text 'this-is-a-test' to trim_text function, you always get a return value of 1 from str_word_count.
Be careful with the order of functions you call.
I have strings like:
-4:00
3:15
+8:30
I need to format them as UTC offset values like:
-0400
+0315
+0815
How can I convert the sample strings to the final strings? I know it probably uses some combo of str_replace and sprintf, but I cannot work it out.
Thanks!
This looks like a pretty simple re-formatting to me (Demo):
$offset = vsprintf('%+03d%02d', sscanf($offset, '%d:%d'));
0 is treated as positive number (+ as in +0000).
First, check if the input string matches. If it does, remove the whole matching string from the result, and if there are only two parts, the leading sign is missing. In this case, add a plus in the beginning and pad the hour to a length of 2. Finally convert that array into a string.
foreach (array('-1:50','1:50','+1:50','-12:00','12:00','+12:00') as $input) {
echo $input . ': ';
if (preg_match('/^([-+])?([1-9][0-9]?):([0-9]{2})$/DX', $input, $asMatch) === 1) {
unset($asMatch[0]);
if ($asMatch[1] === '') {
array_unshift($asMatch, '+');
}
$asMatch[2] = str_pad($asMatch[2], 2, '0', STR_PAD_LEFT);
echo implode('', $asMatch);
}
echo "\n";
}
In three steps here it is:
$offset = preg_replace('/:/','',$offset);
$offset = preg_replace('/\b(?=\d{3}$)/', '0', $offset);
$offset = preg_replace('/^(?=\d)/m', '+', $offset);
You can remove the m flag on the second regex if you are only passing one offset at a time.
A set of regex substitutions for the input formats you want to support would probably be the most readable and maintainable.
So I have done a fair bit of research on how to store "money" in a database and I think the system I want to use is
Converting Money into CENTS and then storing the CENTS in a MySQL DB with a field type of DECIMAL (19,4).
My question is, IF I have an input field from the user... how do I deal with multiple input types.
IE:
$input = "1,346.54"
$input = "10,985.23"
$input = "110,400.50"
$input = "1033.44"
etc etc...
What would be the best method for converting this to CENTS? As we have to deal with 'strings' and convert them to INT, and divide by 100... Everything that I try throws issues because of the "comma" separation with the numbers.
Any thoughts or direction would be greatly appreciated.
function getMoneyAsCents($value)
{
// strip out commas
$value = preg_replace("/\,/i","",$value);
// strip out all but numbers, dash, and dot
$value = preg_replace("/([^0-9\.\-])/i","",$value);
// make sure we are dealing with a proper number now, no +.4393 or 3...304 or 76.5895,94
if (!is_numeric($value))
{
return 0.00;
}
// convert to a float explicitly
$value = (float)$value;
return round($value,2)*100;
}
Looks like there is a NumberFormatter class which provides a parseCurrency method. Have a look at http://www.php.net/manual/en/numberformatter.parsecurrency.php
The example provided is
$fmt = new NumberFormatter( 'de_DE', NumberFormatter::CURRENCY );
$num = "1.234.567,89 $";
echo "We have ".$fmt->parseCurrency($num, $curr)." in $curr\n";
You can remove the commas like this:
$input = str_replace( ',', '', $input);
At this point, you can convert to cents by converting to a float and multiplying by 100. However, this is probably unnecessary. You would potential encounter precision issues when performing math operations, but simply storing the values in the database can be done in the original form without alteration of the value (assuming your DB tables are properly structured):
$input = (float)str_replace( ',', '', $input);
function convert_to_cents($v)
{
$v = str_replace(',','',$v);
$p = explode('.',$v);
if(strlen($p[1])<2){ $p[1] = $p[1]*10;}
return ($p[0]*100)+$p[1];
}
This converts most of the decimal currencies to their subunits.
$1,234,567.89 = 123456789
£ 1,234,567.89 = 123456789
€1.234.567,89 = 123456789
12,34 EUR = 1234
12,34 € = 1234
12,30 € = 1230
1,2 = 102
function convertDecimalCurrencyToSubUnit($str)
{
if( preg_match('/^(.+)[^\d](\d|\d\d)[^\d]*$/', $str, $m) )
return intval(preg_replace('/[^\d]/', '', $m[1]) . ( (strlen($m[2])>1) ? $m[2] : ('0' . $m[2]) ));
return 0;
}
Probably just remove the ',' and the '.' from the string, the result is the amount in cents.
You will probably need to parse the string from the back using strrpos ... If you find a comma 2 spots from the end, then its prob safe to assume its foreign currency and those are the CENTS... Once you determine that, use a regex to strip the remaining commas (after you convert the "CENTS" comma to a decimal of course) ... Now you have a normal DEC number to play with.
Use this to find the last comma in your string ... strrpos
Use this to replace the commas preg_replace
Here is a helpful regex website .. regexlib
//Finding the last comma
$yourCommaPos = strrpos($myString, ',');
if ($yourCommaPos == strlen($myString) - 2) {
//Comma is foreign currency decimal
// Replace with '.'
} else {
//Not foreign Currency so...
//Strip Commas
preg_replace(',', '', $myString);
}
I'm using the getExcerpt() function below to dynamically set the length of a snippet of text. However, my substr method is currently based on character count. I'd like to convert it to word count. Do I need to separate function or is there a PHP method that I can use in place of substr?
function getExcerpt()
{
//currently this is character count. Need to convert to word count
$my_excerptLength = 100;
$my_postExcerpt = strip_tags(
substr(
'This is the post excerpt hard coded for demo purposes',
0,
$my_excerptLength
)
);
return ": <em>".$my_postExcerpt." [...]</em>";}
}
Use str_word_count
Depending on the parameters, it can either return the number of words in a string (default) or an array of the words found (in case you only want to use a subset of them).
So, to return the first 100 words of a snippet of text:
function getExcerpt($text)
{
$words_in_text = str_word_count($text,1);
$words_to_return = 100;
$result = array_slice($words_in_text,0,$words_to_return);
return '<em>'.implode(" ",$result).'</em>';
}
If you want that your script should not ignore the period and comma and other punctuation symbols then you should adopt this approach.
function getExcerpt($text)
{
$my_excerptLength = 100;
$my_array = explode(" ",$text);
$value = implode(" ",array_slice($my_array,0,$my_excerptLength));
return
}
Note : This is just an example.Hope it will help you.Don't forget to vote if it help you.