Date Range Validation in BizTalk EDI Schema

后端 未结 2 1642
北海茫月
北海茫月 2020-12-04 03:40

I need to validate the date range in an element in a BizTalk schema. I have received dates with start dates before end dates (20130521-20130501). I know I could easily pars

相关标签:
2条回答
  • 2020-12-04 03:44

    Rather than writing your own custom component to do the validation you could use the BizTalk Business Rules Engine Pipeline Framework in conjunction with a BRE Policy to validate the date range.

    Full Disclosure: This framework is written by a colleague of mine.

    0 讨论(0)
  • 2020-12-04 04:05

    Disclaimer: I'm using PHP, which means I'm using the PCRE regex flavor.

    The problem

    It seems that you are unaware of the limits of regular expressions, but that's ok.
    What the question really comes to is the following solution: check if x =< y and match it.

    The limit

    Why ? Well you want to check if start date =< end date. The idea of regular expressions is to match certain characters following a certain regular pattern. Regex alone can't check if x < y since regex doesn't have logical operators > <.

    Bypassing certain limit

    What regex could do is to check if x = y. Say for example I've the following string and I want to get all the lines where x = y:

    10 = 10
    15 = 51
    33 = 31
    100 = 101
    780 = 780
    

    We could use the following regex: ^(\d+)\s*=\s*\1$ with the m modifier. What does this mean ?

    • ^ : start of line
    • (\d+) : group and match any digit one or more times
    • \s*=\s* : match white space 0 or more times, and then = and then any white space 0 or more times
    • \1 : referring to group 1, so match only if it's the same as what was matched in group 1.
    • $ : end of line
    • m modifier : multi-line. Make ^ and $ match start and end of line respectively
      Online demo.

    Proof of concept

    Let's hack further. For this POC, we are going to match the following: x-y where 0 =< x =< 9 and 0 =< y =< 9 and x =< y.
    What we can do is trying to match all possibilites where x =< y. So if x=0 then y=[0-9], if x=1 then y=[1-9], if x=2 then y=[2-9] and so forth. Since regex has the or statement, we could write the following regex:
    0-[0-9]|1-[1-9]|2-[2-9]|3-[3-9]|4-[4-9]|5-[5-9]|6-[6-9]|7-[7-9]|8-[8-9]|9-9
    Online demo
    You see ? It's actually so long for a simple comparison ! That's why any sane person would parse and validate it with built in language tools.

    Breaking the laws of regex

    We're going to use PHP to generate a regex expression:

    $start = strtotime('2013-01-01'); // Start date
    $end = strtotime('2013-03-01'); // End date
    $range = array_map(function($v){return date('Ymd', $v);}, range($start, $end, 86400)); // Creating the range of dates
    $result = ''; // Declaring an empty variable to store our regex in it
    
    for($i=$start;$i<=$end;$i+=86400){ // loop each day
        $result .= '(?:' . date('Ymd', $i) . '-(?:'. implode('|', $range) . '))|'; // building our regex
        array_shift($range); // removing first element of range
    }
    $result = substr($result, 0, -1); // removing last | since we don't need it
    echo $result; // Output
    

    The above code will generate a regex that can validate a date between 2013-01-01 and 2013-03-01 where x =< y in the form of x-y. This regex is not optimised and is about 17KB. So imagine the size of this regex if I configured it to validate a range of 10 years ? Note that the size grows exponentially. I tried with an interval of 4 months but I got an error/warning saying that the expression is too long.
    Since the regex is too long, I can't make an online demo of it, but here's the code in PHP:

    $string = '20130101-20130101
    20130201-20130101
    20130105-20130120
    20130201-20130301
    20130210-20130215
    20130301-20130301
    20130301-20130201
    '; // A sample
    
    $regex = file_get_contents('regex.txt'); // Get the regex from a file (which we generated previously)
    preg_match_all('#'.$regex.'#', $string, $matches); // Let's regex !
    print_r($matches[0]); // Printing the matches ...
    

    Output:

    Array
    (
        [0] => 20130101-20130101
        [1] => 20130105-20130120
        [2] => 20130201-20130301
        [3] => 20130210-20130215
        [4] => 20130301-20130301
    )
    

    Online dump of the regex   |   Online PHP demo

    Conclusion

    Please don't ever think about using regex for this task, otherwise you would have 10 problems :)

    0 讨论(0)
提交回复
热议问题