regex a string, convert to number and match condition - javascript

I have this string:
002 2.0 (100aa) 95-97
I then want regex the 95-97 portion of it and paste it with relevant two numbers so I get a year.
In example, 96-97 should become 1995-1997, but 00-05 should become 2000-2005 (all numbers between 0 and 16 should be pasted with 20, but all other numbers with 19).
Then, when I have i.e. 1995-1997 I want to check if a year (i.e. 1996) is present inside 1995-1997 interval or not, and return a bolean.
How would one wright such code?
Best Regards

You could use the callback variant of replace:
function parseString(str) {
function padYear(year) {
return year < 30 ? 2000+year :
year < 100 ? 1900+year : year;
}
var result = {};
result.hasCurrentYear = false;
result.str = str.replace(/(\d\d)-(\d\d)$/g, function (match, yr1, yr2) {
yr1 = padYear(+yr1);
yr2 = padYear(+yr2);
var yrNow = (new Date).getFullYear();
result.hasCurrentYear = yrNow >= yr1 && yrNow <= yr2;
return yr1 + '-' + yr2;
});
return result;
}
var str = '002 2.0 (100aa) 95-16';
console.log(parseString(str));
Note that I made the split at year 30, as the solution will become outdated soon if you use 16 as split year.

I suppose there's a much simpler way to check if a certain year is in "range".The solution using String.split, Array.map functions and Number constructor:
var str = "002 2.0 (100aa) 95-97";
function checkYearInRange(str, year) {
year = Number(year);
var range = str.split(" ").pop().split('-').map((v) => Number((Number(v) > 16)? "19"+v : "20"+v));
return (range[0] <= year && year <= range[1]);
}
console.log(checkYearInRange(str, "1996")); // true
console.log(checkYearInRange(str, "2015")); // false

Related

NaN (not a number) when attempting output 2 decimal place for money value [duplicate]

I have a text box that will have a currency string in it that I then need to convert that string to a double to perform some operations on it.
"$1,100.00" → 1100.00
This needs to occur all client side. I have no choice but to leave the currency string as a currency string as input but need to cast/convert it to a double to allow some mathematical operations.
Remove all non dot / digits:
var currency = "-$4,400.50";
var number = Number(currency.replace(/[^0-9.-]+/g,""));
accounting.js is the way to go. I used it at a project and had very good experience using it.
accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99
accounting.unformat("€ 1.000.000,00", ","); // 1000000
You can find it at GitHub
Use a regex to remove the formating (dollar and comma), and use parseFloat to convert the string to a floating point number.`
var currency = "$1,100.00";
currency.replace(/[$,]+/g,"");
var result = parseFloat(currency) + .05;
I know this is an old question but wanted to give an additional option.
The jQuery Globalize gives the ability to parse a culture specific format to a float.
https://github.com/jquery/globalize
Given a string "$13,042.00", and Globalize set to en-US:
Globalize.culture("en-US");
You can parse the float value out like so:
var result = Globalize.parseFloat(Globalize.format("$13,042.00", "c"));
This will give you:
13042.00
And allows you to work with other cultures.
I know this is an old question, but CMS's answer seems to have one tiny little flaw: it only works if currency format uses "." as decimal separator.
For example, if you need to work with russian rubles, the string will look like this:
"1 000,00 rub."
My solution is far less elegant than CMS's, but it should do the trick.
var currency = "1 000,00 rub."; //it works for US-style currency strings as well
var cur_re = /\D*(\d+|\d.*?\d)(?:\D+(\d{2}))?\D*$/;
var parts = cur_re.exec(currency);
var number = parseFloat(parts[1].replace(/\D/,'')+'.'+(parts[2]?parts[2]:'00'));
console.log(number.toFixed(2));
Assumptions:
currency value uses decimal notation
there are no digits in the string that are not a part of the currency value
currency value contains either 0 or 2 digits in its fractional part *
The regexp can even handle something like "1,999 dollars and 99 cents", though it isn't an intended feature and it should not be relied upon.
Hope this will help someone.
This example run ok
var currency = "$1,123,456.00";
var number = Number(currency.replace(/[^0-9\.]+/g,""));
console.log(number);
For anyone looking for a solution in 2021 you can use Currency.js.
After much research this was the most reliable method I found for production, I didn't have any issues so far. In addition it's very active on Github.
currency(123); // 123.00
currency(1.23); // 1.23
currency("1.23") // 1.23
currency("$12.30") // 12.30
var value = currency("123.45");
currency(value); // 123.45
typescript
import currency from "currency.js";
currency("$12.30").value; // 12.30
This is my function. Works with all currencies..
function toFloat(num) {
dotPos = num.indexOf('.');
commaPos = num.indexOf(',');
if (dotPos < 0)
dotPos = 0;
if (commaPos < 0)
commaPos = 0;
if ((dotPos > commaPos) && dotPos)
sep = dotPos;
else {
if ((commaPos > dotPos) && commaPos)
sep = commaPos;
else
sep = false;
}
if (sep == false)
return parseFloat(num.replace(/[^\d]/g, ""));
return parseFloat(
num.substr(0, sep).replace(/[^\d]/g, "") + '.' +
num.substr(sep+1, num.length).replace(/[^0-9]/, "")
);
}
Usage : toFloat("$1,100.00") or toFloat("1,100.00$")
// "10.000.500,61 TL" price_to_number => 10000500.61
// "10000500.62" number_to_price => 10.000.500,62
JS FIDDLE: https://jsfiddle.net/Limitlessisa/oxhgd32c/
var price="10.000.500,61 TL";
document.getElementById("demo1").innerHTML = price_to_number(price);
var numberPrice="10000500.62";
document.getElementById("demo2").innerHTML = number_to_price(numberPrice);
function price_to_number(v){
if(!v){return 0;}
v=v.split('.').join('');
v=v.split(',').join('.');
return Number(v.replace(/[^0-9.]/g, ""));
}
function number_to_price(v){
if(v==0){return '0,00';}
v=parseFloat(v);
v=v.toFixed(2).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
v=v.split('.').join('*').split(',').join('.').split('*').join(',');
return v;
}
You can try this
var str = "$1,112.12";
str = str.replace(",", "");
str = str.replace("$", "");
console.log(parseFloat(str));
let thousands_seps = '.';
let decimal_sep = ',';
let sanitizeValue = "R$ 2.530,55".replace(thousands_seps,'')
.replace(decimal_sep,'.')
.replace(/[^0-9.-]+/, '');
// Converting to float
// Result 2530.55
let stringToFloat = parseFloat(sanitizeValue);
// Formatting for currency: "R$ 2.530,55"
// BRL in this case
let floatTocurrency = Number(stringToFloat).toLocaleString('pt-BR', {style: 'currency', currency: 'BRL'});
// Output
console.log(stringToFloat, floatTocurrency);
I know you've found a solution to your question, I just wanted to recommend that maybe you look at the following more extensive jQuery plugin for International Number Formats:
International Number Formatter
How about simply
Number(currency.replace(/[^0-9-]+/g,""))/100;
Works with all currencies and locales. replaces all non-numeric chars (you can have €50.000,00 or $50,000.00) input must have 2 decimal places
jQuery.preferCulture("en-IN");
var price = jQuery.format(39.00, "c");
output is: Rs. 39.00
use jquery.glob.js,
jQuery.glob.all.js
Here's a simple function -
function getNumberFromCurrency(currency) {
return Number(currency.replace(/[$,]/g,''))
}
console.log(getNumberFromCurrency('$1,000,000.99')) // 1000000.99
For currencies that use the ',' separator mentioned by Quethzel Diaz
Currency is in Brazilian.
var currency_br = "R$ 1.343,45";
currency_br = currency_br.replace('.', "").replace(',', '.');
var number_formated = Number(currency_br.replace(/[^0-9.-]+/g,""));
var parseCurrency = function (e) {
if (typeof (e) === 'number') return e;
if (typeof (e) === 'string') {
var str = e.trim();
var value = Number(e.replace(/[^0-9.-]+/g, ""));
return str.startsWith('(') && str.endsWith(')') ? -value: value;
}
return e;
}
This worked for me and covers most edge cases :)
function toFloat(num) {
const cleanStr = String(num).replace(/[^0-9.,]/g, '');
let dotPos = cleanStr.indexOf('.');
let commaPos = cleanStr.indexOf(',');
if (dotPos < 0) dotPos = 0;
if (commaPos < 0) commaPos = 0;
const dotSplit = cleanStr.split('.');
const commaSplit = cleanStr.split(',');
const isDecimalDot = dotPos
&& (
(commaPos && dotPos > commaPos)
|| (!commaPos && dotSplit[dotSplit.length - 1].length === 2)
);
const isDecimalComma = commaPos
&& (
(dotPos && dotPos < commaPos)
|| (!dotPos && commaSplit[commaSplit.length - 1].length === 2)
);
let integerPart = cleanStr;
let decimalPart = '0';
if (isDecimalComma) {
integerPart = commaSplit[0];
decimalPart = commaSplit[1];
}
if (isDecimalDot) {
integerPart = dotSplit[0];
decimalPart = dotSplit[1];
}
return parseFloat(
`${integerPart.replace(/[^0-9]/g, '')}.${decimalPart.replace(/[^0-9]/g, '')}`,
);
}
toFloat('USD 1,500.00'); // 1500
toFloat('USD 1,500'); // 1500
toFloat('USD 500.00'); // 500
toFloat('USD 500'); // 500
toFloat('EUR 1.500,00'); // 1500
toFloat('EUR 1.500'); // 1500
toFloat('EUR 500,00'); // 500
toFloat('EUR 500'); // 500
Such a headache and so less consideration to other cultures for nothing...
here it is folks:
let floatPrice = parseFloat(price.replace(/(,|\.)([0-9]{3})/g,'$2').replace(/(,|\.)/,'.'));
as simple as that.
$ 150.00
Fr. 150.00
€ 689.00
I have tested for above three currency symbols .You can do it for others also.
var price = Fr. 150.00;
var priceFloat = price.replace(/[^\d\.]/g, '');
Above regular expression will remove everything that is not a digit or a period.So You can get the string without currency symbol but in case of " Fr. 150.00 " if you console for output then you will get price as
console.log('priceFloat : '+priceFloat);
output will be like priceFloat : .150.00
which is wrong so you check the index of "." then split that and get the proper result.
if (priceFloat.indexOf('.') == 0) {
priceFloat = parseFloat(priceFloat.split('.')[1]);
}else{
priceFloat = parseFloat(priceFloat);
}
function NumberConvertToDecimal (number) {
if (number == 0) {
return '0.00';
}
number = parseFloat(number);
number = number.toFixed(2).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1");
number = number.split('.').join('*').split('*').join('.');
return number;
}
This function should work whichever the locale and currency settings :
function getNumPrice(price, decimalpoint) {
var p = price.split(decimalpoint);
for (var i=0;i<p.length;i++) p[i] = p[i].replace(/\D/g,'');
return p.join('.');
}
This assumes you know the decimal point character (in my case the locale is set from PHP, so I get it with <?php echo cms_function_to_get_decimal_point(); ?>).
You should be able to handle this using vanilla JS. The Internationalization API is part of JS core: ECMAScript Internationalization API
https://www.w3.org/International/wiki/JavaScriptInternationalization
This answer worked for me: How to format numbers as currency strings

Check If a given time(Only hours:minutes) lies betwenn two other different time?

I have 2 different times:
var shiftStartTime = "05:48";
var shiftEndTime = "14:29";
And i have another time which is selectedDate ="06:20"(this will change according datetimepicker selection), and i want to check if selectedDate should be between (shiftStartTime and shiftEndTime ).
Can anyone help in this?
Updated Code:
i have 6 different timespan like below
var shift1StartTime = "05:48";
var shift1EndTime = "14:18";
var shift2StartTime = "14:30";
var shift2EndTime = "22:29";
va
r shift3StartTime = "22:30";
var shift3EndTime = "05:47";
using all 6 timespan i want to check the if the given time is between (shift1StartTime and shift1EndTime) return shift1
Or
if the given time is between (shift2StartTime and shift2EndTime) return shift2
Or
if the given time is between (shift3StartTime and shift3EndTime) return shift3
Simply compare the strings like
var shiftStartTime = "05:48"; var shiftEndTime = "14:29";
shiftStartTime > shiftEndTime // false
Here is some JS that does this, although better formatted time would make it a lot easier
function findTotalTime(time) {
hours = parseInt(time.substring(0,2))
mins = parseInt(time.substring(3,5))
return (hours*60) + mins
}
startTime = findTotalTime(shiftStartTime)
endTime = findTotalTime(shiftEndTime)
selectedTime = findTotalTime(selectedDate)
if (selectedTime > startTime && selectedTime < endTime) {
// time is inbetween shifts
}
const date = new Date();
const shiftStartTime = '05:48';
const shiftEndTime = '14:29';
const selectedDate = '14:20';
const start = date.setHours(+shiftStartTime.split(':')[0], +shiftStartTime.split(':')[1], 0, 0);
const end = date.setHours(+shiftEndTime.split(':')[0], +shiftEndTime.split(':')[1], 0, 0);
const selected = date.setHours(+selectedDate.split(':')[0], +selectedDate.split(':')[1], 0, 0);
if (start < selected && selected < end) {
console.log(true);
} else {
console.log(false);
}
Alright, so you got three relative times as strings in the format HH:mm. I'm assuming that your times are given as 24h strings / military time, because otherwise, you'd need an A.M. / P.M. specifier.
It is always useful to have the data you are working with in a well-suited machine-readable format, so you could parse them into a simple object holding the hour and minute as numbers.
A function doing this could look like this.
function parseTimeStr(time) {
// The pattern of your input,
// allows spaces around the `:`
// and single-digit inputs like `8:00`
let re = /([0-9][0-9]?)\s*:\s*([0-9][0-9]?)/;
let result = re.exec(time.trim());
if (result === null) {
throw "No match"
}
let hour = parseInt(result[1], 10);
let minute = parseInt(result[2], 10);
/* handle out of range values here */
return { hour, minute };
}
Alright, so you have these objects now. How do you compare them? There's a pattern for that: Have a function returning whether the first argument is greater (1), equal (0), or less (-1) than the second.
Writing this is simple now that the time is an object:
function cmpDate(date1, date2) {
if (date1.hour > date2.hour) {
return 1;
} else if (date1.hour < date2.hour) {
return -1;
} else if (date1.minute > date2.minute) {
return 1;
} else if (date1.minute < date2.minute) {
return -1;
} else {
return 0;
}
}
Alright, now we can have a helper function checking if the first argument is in the closed interval defined by the last two arguments:
function isInShift(time, shiftStart, shiftEnd) {
// time is greater or equal shiftStart
// and less or equal shiftEnd
return cmpDate(time, shiftStart) !== -1 && cmpDate(time, shiftEnd) !== 1;
}
You can then finally make your comparison by calling isInShift(parseTimeStr(selectedTime), parseTimeStr(shiftStartTime), parseTimeStr(shiftEndTime)). This will return a boolean. You can easily extend this infrastructure for multiple shifts.
Be aware that both reality and your users can be more ... screwy than you'd expect.
The above code does not do error handling for invalid time inputs, neither does it account for overnight shifts, but these are details that you can easily work out, you just have to put some effort into thinking of them.

Re-write malformed dates yyyy-M-d to yyyy-MM-dd in javascript using RegEx

So I'm rewriting dates in javacript and as familiar js spits dates like 2013-1-1 that isn't very useful always. Instead I'm looking for a routine that will form this date to the correct iso-version 2013-01-01
Today I make this by using string
var b = new Date('2013-1-1');
var result = b.getFullYear() + "-" +
(b.getMonth().toString().length == 1 ? "0" + parseInt(b.getMonth() + 1) : parseInt(b.getMonth() + 1)) + "-" +
(b.getDate().toString().length == 1 ? "0" + b.getDate() : b.getDate());
This works but it is ugly. Is there a better way to perform this using RegEx?
Please spare me of any anti-regex comments
A non-regex solution would be a generic padding function. First get your date in the non-padded version then you can split on the separator and pad it as necessary. Something like this:
var date = '2013-1-1';
var pad = function(n) {
return function(str) {
while (str.length < n) {
str = '0'+ str;
}
return str;
}
};
date = date.split(/-/g).map(pad(2)).join('-'); //=> 2013-01-01
may be this could help:
var str="2013-1-1";
var m = str.match(/^(\d{4})-(\d{1})-(\d{1})$/);
console.log([m[1], "0".concat([2]-1), "0".concat(m[3])].join('-'));
based on elclanrs suggestion I wrote an extension method
// Add 0 to single numbers
Number.prototype.padDate = function () {
// Add +1 if input is 0 (js months starts at 0)
var number = this == 0 ? 1 : this;
return number.toString().length == 1 ? "0" + number : number;
};
This allows me to build dates like this
var b = new Date('2013-1-1');
var result = b.getFullYear() + "-" + b.getMonth().padDate() + "-" + b.getDate().padDate();
Much cleaner, thanks

Is there a more efficient way to do this without all the "if" and "else" statements?

How would you program this more efficiently?
if( randomYear%4==0 ) {
if( randomYear%100==0 ) {
if( randomYear%400==0 ) {
randomDay = 1 + Math.floor(Math.random()*29);
}
else {
randomDay = 1 + Math.floor(Math.random()*28);
}
else{
randomDay = 1 + Math.floor(Math.random()*29);
}
else{
randomDay = 1 + Math.floor(Math.random()*28);
}
First off, i''m using math.floor because it includes 0 and excludes 1, which is what i'm looking for. The purpose of this is to determine if the variable 'randomYear' is a leap year and have the appropriate days in February.
I'm mainly concerned about all the if and else statements. BTW, i'm using Javascript.
Thank YOU SO much!!
You don't even need the math:
var tmp = new Date(year,1,29); // attempt to get February 29th
isleapyear = (tmp.getMonth() == 1);
How about this?
var maxDays = 28;
if (randomYear%4 == 0 && (randomYear%100 != 0 || randomYear%400 == 0)) {
maxDays = 29;
}
randomDay = 1 + Math.floor(Math.random() * maxDays);
If you are ok with including a third party library, try this library:
http://momentjs.com/
And you can just do:
moment([2000]).isLeapYear()
to check if 2000 is a leap year and then you can do appropriate logic. Also you can check if 29th of Feb of a certain year exists or not using its validation api.
You can do it as given below.
function isLeapYear(year){
return !(year%400) || ((year%100 > 0) && !(year%4)) ;
}
function getRandomDay(year){
return 1 + Math.floor(Math.random()* (isLeapYear(year)?29:28))
}
var day = getRandomDay(2000);
Performance wise it might not make big changes. But this is the way to write organized re-usable code in less number of lines.

How to check if a string is a legal "dd/mm/yyyy" date?

Given a string str, how could I check if it is in the dd/mm/yyyy format and contains a legal date ?
Some examples:
bla bla // false
14/09/2011 // true
09/14/2011 // false
14/9/2011 // false
1/09/2011 // false
14/09/11 // false
14.09.2011 // false
14/00/2011 // false
29/02/2011 // false
14/09/9999 // true
Edit: exact solution below
You could do something like this, but with a more accurate algorithm for day validation:
function testDate(str) {
var t = str.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
if(t === null)
return false;
var d = +t[1], m = +t[2], y = +t[3];
// Below should be a more acurate algorithm
if(m >= 1 && m <= 12 && d >= 1 && d <= 31) {
return true;
}
return false;
}
http://jsfiddle.net/aMWtj/
Date validation alg.: http://www.eee.hiflyers.co.uk/ProgPrac/DateValidation-algorithm.pdf
Exact solution: function that returns a parsed date or null, depending exactly on your requirements.
function parseDate(str) {
var t = str.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
if(t !== null){
var d = +t[1], m = +t[2], y = +t[3];
var date = new Date(y, m - 1, d);
if(date.getFullYear() === y && date.getMonth() === m - 1) {
return date;
}
}
return null;
}
http://jsfiddle.net/aMWtj/2/
In case you need the function to return true/false and for a yyyy/mm/dd format
function IsValidDate(pText) {
var isValid = false ;
var t = pText.match(/^(\d{4})\/(\d{2})\/(\d{2})$/);
if (t !== null) {
var y = +t[1], m = +t[2], d = +t[3];
var date = new Date(y, m - 1, d);
isValid = (date.getFullYear() === y && date.getMonth() === m - 1) ;
}
return isValid ;
}
Try -
var strDate = '12/03/2011';
var dateParts = strDate.split("/");
var date = new Date(dateParts[2], (dateParts[1] - 1) ,dateParts[0]);
There's more info in this question - Parse DateTime string in JavaScript (the code in my answer is heavily influenced by linked question)
Demo - http://jsfiddle.net/xW2p8/
EDIT
Updated answer, try -
function isValidDate(strDate) {
if (strDate.length != 10) return false;
var dateParts = strDate.split("/");
var date = new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]);
if (date.getDate() == dateParts[0] && date.getMonth() == (dateParts[1] - 1) && date.getFullYear() == dateParts[2]) {
return true;
}
else return false;
}
This function passes all the test cases. As far as I'm aware, Adam Jurczyk had posted an accurate answer well before I corrected my original wrong answer. He deserves credit for this.
Demo - http://jsfiddle.net/2r6eX/1/
you can use regular exp to validate date .
try like this :
re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
if(form.mydate.value != '' && !form.mydate.value.match(re))
//do something here
note: this will only work for dd/mm/yyyy
for exact match of your requirement use
re = /^\d{2}\/\d{2}\/\d{4}$/;
I'm going to answer a different question, as Misha Moroshko's has already been well-answered: use HTML5. That is, on the assumption that the strings in question arise as user inputs through a Web browser, I propose that the entries be received as
<input type = "date" ...
I recognize that not all browsers likely to be in use will interpret "date" in a way that rigorously enforces validity. It's the right thing to do, though, will certainly improve as time goes on, and might well be good enough in a particular context even now simply to eliminate the need to validate the date-string after the fact.
Personally, I think the best solution would be to modify the UI to use dropdowns for the month and possibly day selections.
Trying to figure out if 1/2/2001 is January 2nd or February 1st based solely on that input string is impossible.
Recent discovery: You can use date.js lib, it adds function Date.parseExact so you can just do Date.parseExact(dateString,"dd/MM/yyyy"). It fails when month is 00, but its still usefull.
for dd/mm/yyyy format only
^(0?[1-9]|[12][0-9]|3[01])[\/](0?[1-9]|1[012])[\/]\d{4}$

Categories