I want date range from 12 to 15. How to get this? Please help
let dates = ["10/07/2021", "11/07/2021", "12/07/2021", "13/07/2021", "14/07/2021", "15/07/2021", "16/07/2021", "17/07/2021"];
Remove item before 12 and after 15
newDates = ["12/07/2021", "13/07/2021", "14/07/2021", "15/07/2021"];
Alternatively (this is essentially #Bravo's suggestion in the comments / #Nithleh's answer below but using regex to make the code a little cleaner):
dates = dates.filter( date => {
let d = new Date(date.replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$2-$1'))
return d.getDate() >= 12 && d.getDate() <= 15
} )
// shoud return ["12/07/2021", "13/07/2021", "14/07/2021", "15/07/2021"]
Regex explanation:
\d matches single digits 0-9 (and other numerical digits). {2} specifies the length of the matching set. (..) captures groups and \/ matches the /.
Your date format is 12/07/2021. In other words, a group of 2 digits followed by a forward slash / followed by a group of 2 digits followed by a / followed by a group of 4 digits. This translates into:
(\d{2})\/(\d{2})\/(\d{4}). This captures 3 parts; first part 2 digits ($1), second part 2 digits ($2) and the third part 4 digits ($3).
Replace function takes care of formatting the date into yyyy-mm-dd format since Date requires the date string to be in that format.
Now we know that the third part $3 holds year, $2 month and $1 day. So date.replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$2-$1') replaces (shifts the parts) the original date 12/07/2021 with the newly formatted date 2021/07/12
Now let d = new Date(date.replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$2-$1')) will have a date object and d.getDate() will give the day portion.
Note that this solution d.getDate() >= 12 && d.getDate() <= 15 would only work if the dates fall within the same month of the same year OR if you want to get these particular days regardless of the month or year.
Related
This question already has answers here:
How to convert timestamp to readable date/time?
(3 answers)
Closed 5 months ago.
I have a string like 20221004093142Z which I need to convert into a datetime format in JavaScript. Can someone help me on this?
If the timestring format never changes, you could build your datetime variable like the following:
let timestring = "20221004093142Z"
timestring =
timestring.substring(0, 4) + "-" +
timestring.substring(4, 6) + "-" +
timestring.substring(6, 8) + " " +
timestring.substring(8, 10) + ":" +
timestring.substring(10, 12) + ":" +
timestring.substring(12, timestring.length - 1)
let datetime = new Date(timestring)
console.log(datetime)
You could also build it the same way creating the single year, month etc. values with substring and then set it together.
Pretty sure there is a way to simplify the substring thing with splicing the ":" and "-" chars into the timestring.
Maybe you can use a RegExp to convert your input string to an ISO date formatted string (which is the closest to your input string) and then create a date from that formatted string. Something like:
const inputStr = '20221004093142Z'
const re = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\.\d{0,3})?/g;
const formattedStr = inputStr.replace(re, '$1-$2-$3T$4:$5:$6$7');
const outputDate = new Date(formattedStr);
console.log(`inputStr: ${inputStr}`);
console.log(`formattedStr: ${formattedStr}`);
console.log(`outputDate: ${outputDate}`);
console.log(`outputDate.toLocaleString(): ${outputDate.toLocaleString()}`);
The Regular Expression (RegExp) explained:
parentheses (()) delimit what is called a "capturing group", which can then be referred to by its position (e.g. $1 is the content of the first capturing group, $2 of the second, etc.)
\d matches any digit (0-9)
the curly brackets ({}) mark a quantifier: how many occurrences of the preceding character or group should I look for? You can provide an exact quantity ({4} -> exact 4) or a range ({0,3} -> from 0 up to 3)
the question mark (?) indicates that the preceding character or group is optional (there can be zero or exactly one occurrence, but no more than one)
So what the RegExp proposed does is to look for
a group of four digits ((\d{4})), which will be referenced as $1, followed by
a group of two digits ((\d{2})), which will be referenced as $2, followed by
a group of two digits ((\d{2})), which will be referenced as $3, followed by
a group of two digits ((\d{2})), which will be referenced as $4, followed by
a group of two digits ((\d{2})), which will be referenced as $5, followed by
a group of two digits ((\d{2})), which will be referenced as $6, followed by
an optional group formed by a dot (\.) and 0-to-3 digits (\d{0,3}), which will be referenced as $7
Now we have:
the year (4 digits) in $1
the month (2 digits) in $2
the day (2 digits) in $3
the hours (2 digits) in $4
the minutes (2 digits) in $5
the seconds (2 digits) in $6
the milliseconds (a dot followed by up to 3 digits) - if present - in $7
and we can use those substrings in the second argument of the String.prototype.replace() function, in order to transform the original string as we need.
For more on RegExp you can refer to: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
I also find this website useful as a quick reference and to test my RegExp: https://regexr.com/
I'm trying to come up with a regex which will reject non-consecutive characters in a supplied date format. I want to be as flexible as possible, and so I have decided that my date format string can contain YY or YYYY, MM or MMM, DD or DDD, hh mm and ss.
Some of the regex I have worked out already - for example, matching the following will show that the month is a 3 character format:
([M])\1{2}
I'm totally in the dark with regard to checking that the date format doesn't contain non consecutive characters. For example, the following date formats should be valid:
YYYY-MM-DD hh:mm:ss
hh:mm:ss YYYY-MM-DD
DD/MMM/YYYYhh-mm
But these formats should be rejected
YYYY-MM-DD hh:mm:ss YYYY // year appears twice
hh:mm:ss YYYY-MM-DD hh // hour appears twice
DD/MMM/YYYYhh-mm m // m not consecutive with other m
In the interests of future expansion, I want to allow non consecutive special characters (/ - . : ) etc and reject all non-consecutive alpha-numeric characters. Case sensitive though - mm and MM are not not the same (as above)
Just to be clear - I'm not trying to validate an actual date - I am trying to validate a date format string only.
I suggest checking if there is at least one occurrence of the same character that has already been present before, and then negating the outcome:
function(text) {
return !/(\w)\1*(?!\1).*\1/.test(text);
}
See the regex demo. You may change \w to [YMDhms] to only check these six letters.
Pattern details
(\w) - Group 1 (further referenced to with the \1 backreference): a word char
\1* - zero or more occurrences of the same char as in Group 1
(?!\1) - set a boundary, make sure there next char is not the same as the char in Group 1
.* - any zero or more chars other than line break chars, as many as possible
\1 - the same char as in Group 1.
I'm trying to put restrictions on a date input field so users don't put in exaggerating dates like the year 3000. I found this neat solution which works. But I want the date in yyyy/mm/dd format with year also having restriction, so mm is between 1-12, dd is between 1-31, and yy is between 1900-2100.
Here's the jsfiddle, I can't get it to work with format yyyy/mm/dd. If I change the dtArrays to
dtMonth = dtArray[5];
dtDay= dtArray[7];
dtYear = dtArray[1];
Year works but mm ends up being in place of dd. What could I be doing wrong? Also are there any better ways of accomplish this? Last question.. this problem seems to be pretty simple, what books on jquery/javascript would you recommend so I may be able to get this on my own?
I think you've misunderstood what you get in dtArray (which isn't a great name). It's the output of the capture groups from this regex:
/^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/
which matches mm/dd/yyyy (where those are digits) so
[1] = m or mm
[2] = a / or - separator
[3] = d or dd
[4] = a / or - separator
[5] = yyyy
They aren't offsets into the string. (dtArray[0] will be the whole date matched.) With your modified regex is
/^(\d{4})(\/|-)(\d{1,2})(\/|-)(\d{1,2})$/
i.e. four digits in the first position, then you'll get
[1] = yyyy
[2] = a / or - separator
[3] = m or mm
[4] = a / or - separator
[5] = d or dd
and so
dtYear = dtArray[1];
dtMonth = dtArray[3];
dtDay = dtArray[5];
(Note at this point that the three variables will actually be strings, not integers, albeit containing string representations of integer values. However JavaScript being what it is, they'll be coerced into integers when you try and use them as integers.)
A user can enter a few valid date combinations into an input :
Examples : ( all combinations are allowed 3!=6)
feb 7 2012
feb 07 2012
7 feb 2012
2012 7 feb
...
All are valid dates.
I have also managed to create a regex which check it :
/^(?=.*\b(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\b)(?=.*(\b[12]\d{3}\b))(?=.*\b(0[1-9]|[12]\d|3[01])\b).*$/i
Which means :
(?=.*\b(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\b) : I'm expecting one of those values at the future.
(?=.*(\b[12]\d{3}\b)) : I'm expecting year : 1xxx or 2xxx
(?=.*\b(0[1-9]|[12]\d|3[01])\b) I'm expecting day : 0x or 1x or 2x or 3x
All are OK.
So where is the problem ?
My regex also matches an invalid solutions which includes a valid solution :
IE : feb 13 2012 4 will also pass.
Console :
/^(?=.*\b(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\b)(?=.*(\b[12]\d{3}\b))(?=.*\b(0[1-9]|[12]\d|3[01])\b).*$/i.test('feb 13 2012 4') //true
Question :
How can I enhance my regex in order to find a strict match ?
p.s.
Checking new Date(xxx) is also a solution , but I'm looking for regex solution.(to improve my regex skills).
Write a regexp for each format:
RE1 - recognizes MON DD YYYY = (?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\s+(?:0?[1-9]|[12]\d|3[01])\s+[12]\d{3}
RE2 - recognizes DD MON YYYY = (?:0?[1-9]|[12]\d|3[01])\s+(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\s+[12]\d{3}
RE3 - recognizes YYYY DD MON = [12]\d{3}\s+(?:0?[1-9]|[12]\d|3[01])\s+(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)
Then combine them:
/^(?:RE1|RE2|RE3)$/i
Create one look-forward (?=...) group at the beginning, then optional groups for digits before or after the month block. The regex below works for all of your examples (see the unit tests at the linked page). Edit: it now matches all 3!=6 allowed combinations, but no impermissible combinations like 2 feb 1978 4.
/^(?=[a-z]{3}\s(\d{1,2}\s\d{4}|\d{4}\s\d{1,2})$|\d{1,2}\s[a-z]{3}\s\d{4}$|\d{4}\s[a-z]{3}\s\d{1,2}$|(\d{1,2}\s\d{4}|\d{4}\s\d{1,2})\s[a-z]{3}$)([12]\d{3}\s|\d{1,2}\s){0,2}(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(\s\d{1,2}|\s[12]\d{3}){0,2}$/i
Debuggex Demo
Explanation:
The entire expression must look like one of the following:
Three of [a-z] followed by a day, then a year
Three of [a-z] followed by a year, then a day
A day, three of [a-z], and a year
A year, three of [a-z], and a day
A day, a year, then three of [a-z]
A year, a day, then three of [a-z]
Optionally match one or both of the number groups
Match the three-letter month code
Optionally match one or both of the number groups
I'm trying to make the regular expression find the numbers in a date string (eg, 04/05/1989). This is what I have:
\A0[1-9]{2}\/0[1-9]{2}\/[1900-2012]\z
The square brackets create a character range, not a number range:
[A-Z] matches all ASCII characters from A to Z.
[1900-2012] matches the 1, the 9, the 0, the range of ASCII characters between 0 and 2, the 0, the 1 and the 2. Effectively the same can be expressed as [0-29].
Within a character range expression, the order of characters is not important. [0815] is the same as [8510]. Hence [1900] is the same as [019].
You want (19[0-9]{2}|200[0-9]|201[0-2]) to match the correct year range. Or, if you just want to match four digits and don't want range validation you can use ([0-9]{4})
Same for month and day. You can do it with range validation or you can do it by matching one or two digits. I'd recommend the latter.
^([0-9]{1,2})/([0-9]{2})/([0-9]{4})$
Try to convert the result to a date value. If that fails, the input was invalid. If it succeeds, check if the resulting date falls into your required range. Regex is the wrong tool to provide date validity checks.
I had answered a similar question over here: How to parse a date in format "YYYYmmdd" in JavaScript?. It just needs some modifications in the extraction part.
EDIT:
You could modify that function this way:
function parse(str) { // str format: 'dd/mm/yyyy'
var d = str.substr(0,2),
m = parseInt(str.substr(3,2)) - 1,
y = str.substr(6,4);
var D = new Date(y,m,d);
return (D.getFullYear() == y && D.getMonth() == m && D.getDate() == d) ? D : 'invalid date';
}
(?<!\d)((0?\d)|([12]\d)|(3[01]))/((0?\d)|(1[0-2]))/((19)|(20))\d\d
Seems to work in the tests I did.
(?<!\d)((((0?\d)|([12]\d)|(3[01]))/(((0?((1[02]?)|([3578]))))|(1[0-2])))|(((0?\d)|([12]\d))/(0?2))|(((0?\d)|([12]\d)|(30))/((0?[2469])|(11))))/((19)|(20))\d\d
The previous regex matches invalid dates like 31/02/2012 but this ones seems a little more normative.
IMHO this won't match valid 10/10/1989 but will match invalid 099/0991989. First of all 0[1-9]{2} matches 0 plus two digits between 1 and 9. Also [1900-2012] is not what you want.
try this
\A[0-9]{2}\/[0-9]{2}\/[1900-2012]\z
it should match dates in format dd/mm/yyyy(1900 to 2012)