• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 662
  • Last Modified:

date range ...

Hi experts. Regular expressions are, to be perfectly honest with you, a bit of a black art to me, so I don't even know where to start.


Basically this is what I want to do. I have two dates presented to me as strings in

"YYYY-MM-DD" format

What I want to be able to do is use a regular expression that recognises any other date that falls within the range specified by the two dates I got.

I trust this is somewhat helped by the fact that if you write any dates out as numbers like YYYYMMDD, the > and < operators would always work. so if date 3 falls between date 1 and date 2, then the YYYYMMDD representations of these three dates also follow a simple numeric comparison.


But how do you express that in "regular expressions"?


cheeeeers.
0
WernerVonBraun
Asked:
WernerVonBraun
  • 9
  • 7
  • 4
  • +2
2 Solutions
 
käµfm³d 👽Commented:
Parsing dates is a frightening task in regex. To actually "parse" a date for validity, the pattern is quite extensive and complicated. If you merely want to validate structure, then the regex is not nearly as bad.

Is there a reason why you can't parse the dates in your language using some built-in construct?
0
 
WernerVonBraunAuthor Commented:
I don't need to validate dates, I merely need to be able to confirm that one string that looks like yyyy-mm-dd alphabetically falls between two others.
0
 
HonorGodCommented:
> What I want to be able to do is use a regular expression that recognises any other date that falls within the range specified by the two dates I got.

  This is a really difficult task.

  I would suggest that you start by taking a look at this article I wrote:
2 Dates - What's the difference? http://www.experts-exchange.com/A_483.html

  My suggestion would be to:
- verify/validate that each date is valid using a RegExp
- convert each date into a Date object
- use a simple comparison to test if a third date is between the start and end date

  Does this make sense?
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
HonorGodCommented:
> I merely need to be able to confirm that one string that looks like yyyy-mm-dd alphabetically falls between two others.

  The problem with this is that the date may "look" valid (e.g., Feb 29th, 2011) but may not, in fact, be a real date.

  So it is much better to have the string verified using a RegExp, then converting it to a actual Date object (which can then be formatted and compared to the user specified value).  Then, this Date object should be used for the kind of comparison you describe.
0
 
käµfm³d 👽Commented:
>>  I merely need to be able to confirm that one string that looks like yyyy-mm-dd

Regex can satisfy this requirement.


>>  alphabetically falls between two others.

Regex can not satisfy this requirement.
0
 
WernerVonBraunAuthor Commented:
Ok, let's see if I can explain this better, because I think I made a balls of it first time around.

The validity or non-validity of the dates are actually completely irrelevant to me. Yes, the actual strings in question *are* produced by some tool converting actual dates into a "YYYY-MM-DD" format, but by the time I come to look at that it is no longer important where the strings came from. They are now stored in a kind of "database", as strings, and the only way I have to interrogate the database is to ask it, in a language that *it* understands, to give me all the rows for which field X conforms to any regular expression that I care to provide.

Say the database contains the rows:

1292-44-77
9290-33-36
2883-33-46
3565-52-33

Say I have two values:

2322-99-87
and
8208-11-37

When you look at all the strings on a purely *alphabetical* basis, you will see that the first row does not fall between the two provided values. Nor does the second row. But the 3rd and 4th do.


And that's what I'm looking for. A formula that, given two of such values that are formatted like 4 digits, a dash, 2 digits, a dash and 2 more digits can give me, for any third value that is also formatted like that, a "yay" or "nay" for the question "does the 3rd value fall between the first and the second one".

I'll make sure that the first one is always the smaller one and the second the larger one.
0
 
WernerVonBraunAuthor Commented:

>> >>  alphabetically falls between two others.

>> Regex can not satisfy this requirement.


Why not?
0
 
WernerVonBraunAuthor Commented:
>> Regex can not satisfy this requirement.

I would be surprised if it couldn't. Let me describe the mechanism in pseudocode. Say you have two two-character values and one for comparison:

23
67

I would do it something like this:

If Char1 < 2 then "nay"
ElseIf Char1 > 6 then "nay"
Else
  If Char2 < 3 then "nay"
  ElseIf Char2 > 7 then "nay"
  Else
     "yaaaaay"!!!!!!
  EndIf
EndIf


Obviously I'm talking about 10-character comparison strings of which the 5th and the 7th character are *always* a dash, so the real pseudocode would be much more complex but that is the basic principle. I would be surprised if something like that could not be done in regex
0
 
HonorGodCommented:
> > Regex can not satisfy this requirement.

> Why not?

  Because in order for the RegExp to do this kind of thing, it would have to have patterns to explicitly identify the end points, as well as the allowed intermediate values.

- For example:
  You can have a pattern identify that a character is a digit using this meta-character \d
 
  And, you can identify that a numeric value is within a specific range by adding modifiers, and making the RegExp much more complex.

  To identify a 3 digit value we might want to use something like: \d\d\d  or \d{3}
  this would match things like 000 001 002 003 all the way to 999

  Here's one way to validate that a number is in the range of 0..255:
(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])

  But, there is no way to have a RegExp say that you have 3 numeric values ... in increasing order.

  Does that make sense?


0
 
WernerVonBraunAuthor Commented:
I can construct the regex in my calling program so getting the "2" and the "6", and the "3" and the "7" in there as per the example I gave shouldn't be a problem.
0
 
HonorGodCommented:
> I would be surprised if something like that could not be done in regex

  Unfortunately, your pseudo-code "knows" where each two digit number exists, and is able to say

  compare the 1st digit of value #1 against the 1st digit of value #2

  A RegExp must provide a pattern to analyze the characters in order.
0
 
HonorGodCommented:
You could have a RegExp that validates the three different dates.
However, you would need extra code to compare the different pieces of each date value outside of the RegExp.
0
 
WernerVonBraunAuthor Commented:
> But, there is no way to have a RegExp say that you have 3 numeric values ... in increasing order.

But that's not what I'm looking for. I'm only checking *one* number against criteria that, yes, consist of two other numbers but I'm willing and able to process those to generate a brand-new regular expression "on the fly" so to speak.

Even simpler example

Say you have a word

"fish"

Surely you could construe a regular expression that will tell you whether "fish" falls between "boat" and "water" or not?
0
 
HonorGodCommented:
Consider a string containing 3 dates...

YYYY-MM-DD  YYYY-MM-DD  YYYY-MM-DD

How, looking at the characters in order, can you say that the 2nd and 3rd date are "numerically larger" than the first?

You could have a RegExp that is able to determine where each part of each date exists, e.g.,

- Year1
- Month1
- Date1

- Year2
- Month2
- Date2

- Year3
- Month3
- Date3

  But, being able to take each as a whole value, and saying that the next date, as a whole value, is larger is not possible with RegExp
0
 
HonorGodCommented:
> Surely you could construe a regular expression that will tell you whether "fish" falls between "boat" and "water" or not?

  That is not how RegExp are designed to work.

  They are used to define a pattern against which values can be compared.

  You could have a RegExp that was able to identify "fish", "boat" and "water", or 3 different words in an input string. But the RegExp can't be used to say that "word1" must be less than "word2" must be less than "word3" in the input value.
0
 
käµfm³d 👽Commented:
>>  Why not?

Because what you are saying is you want to compare the values of two widgets. Regular expressions are about matching patterns, not comparing values, per se. A typical use of regular expression would be:

    verify that the target string is, "formatted like 4 digits, a dash, 2 digits, a dash and 2 more digits."

What you are talking about doing is comparing the value of A to the value of B and to the value of C.

Regular expressions are a form of state machine--a very simple state machine. We say that a pattern accepts input if we can transition from state to state based on the source data. Given the pattern:

    \d*[a-z][a-z]*

and the input:

    123abc

The different states of this machine are shown below (states are the circles).

  State Machine for Regex Example
The triangle points to our initial state; the double-circle is our terminating state (acceptance state). You should be able to see from the diagram, we can loop an indefinite number of times whenever we find a digit, so long as we are in the first state (q0). This part of the machine would match the "123" in our source data. Once we find a letter, matched by the transition between q0 and q1, we transition to the next state (q1). "a" would be matched during this transition. While at q2, we can loop an indefinite number of times to find more letters. "bc" would be matched by this action. Once we no longer find a letter, the double-circle part of the state machine is enforced and we say the source data was accepted by the pattern if we reach this double-circle. If we never get to q1 (because we found, say, a question mark, which is not defined by this pattern), then the source data was not accepted by the pattern.

You'll notice there's no way, according to the diagram, to compare two things to each other. There's not even a way to compare if one thing is less than or greater than another. This is the same concept behind regex. Your pattern is what you are comparing against the source data. You pattern basically only checks for conditions of equality, and when it can't find such, it abandons the matching process and indicates failure.

I realize that's more than you probably wanted to know, but I'm hoping to shed some light on how regex works  = )
0
 
Terry WoodsIT GuruCommented:
Given 2 values, say:
2322-99-87
and
8208-11-37

It should be possible to programmatically *build* a regular expression that accepts values between those values. I think RegexBuddy can do this, maybe?
0
 
ozoCommented:
2322-99-87
and
8208-11-37

2322-99-8[7-9]|2322-99-9[0-9]|232[3-9]-[0-9][0-9]-[0-9][0-9]|23[3-9][0-9]-[0-9][0-9]-[0-9][0-9]|2[4-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[3-7][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|8[0-1][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|820[0-7]-[0-9][0-9]-[0-9][0-9]|8208-0[0-9]-[0-9][0-9]|8208-10-[0-9][0-9]|8208-11-[0-2][0-9]|8208-11-3[0-7]
0
 
Terry WoodsIT GuruCommented:
Exactly!
0
 
WernerVonBraunAuthor Commented:
And there we have it. That is actually quite simple. Now all I need to do is write a proggy that can produce a similar kind of RegEx given *any* "start" and "end" value and ozo's yer uncle .... or aunt .... whatever the case may be. Thanks a mill.
0
 
WernerVonBraunAuthor Commented:
350 for ozo for providing the actual solution, and a 150 point acknowledgement to TerryAtOpus for thinking along the right lines before ozo posted it.
0
 
käµfm³d 👽Commented:
I stand corrected  = )
0
 
WernerVonBraunAuthor Commented:
No problem. Probably also due to the clunky and confusing way in which I presented the true nature of the problem.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 9
  • 7
  • 4
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now