skip to Main Content

I am trying to write a regular expression to ensure that the text of years is valid. The following are ALL valid years

  • 2023
  • 300
  • -1
  • 40AD
  • 40 AD
  • 3000 BC
  • 200BC

Here is the Regex that I camp up with

^(-?)([0-9]+)s*(BC|AD){0,1}$

However it has one shortfall. The above Regex also finds a match for the following:

  • -200AD
  • -700BC
  • 0BC
  • 0AD
  • -0
  • -0BC
  • -0AD

So bascially, I do NOT want the Regex to find a match if any of the following happens:

  1. A negative number is enetered, with the letters BC or AD
  2. 0BC or 0AD should not be allowed
  3. -0 should not be allowed. This also then includes -0BC and -0AD, which in turn should not be allowed either

How do I do that?

Thanks.

2

Answers


  1. Consider:

    let re = String.raw`
        ^ # begin
        (
            (
                # negative
                -
                [1-9] [0-9]{0,3}  # dont allow leading zeroes
            )
            |
            (
                # positive
                [1-9] [0-9]{0,3}  # dont allow leading zeroes
                (
                    # AD/BC
                    s*
                    (AD | BC)
                )?
            )
            |
            (
                # special case
                0
            )
        )
        $ # end
    `
    
    //
    
    re = new RegExp(re.replace(/s+|#.+/g, ''))
    
    console.log(re)
    ;
    `
    2023
    300
    -1
    40AD
    40 AD
    3000 BC
    200BC
    -200AD
    -700BC
    0BC
    0AD
    -0
    -0BC
    -0AD
    `.trim().split('n').map(s => s.trim()).forEach(s => console.log(s, re.test(s)))

    Regular expressions are programs, why do people insist on writing them without spaces and indentation? 😉

    Login or Signup to reply.
  2. In the pattern that you tried ^(-?)([0-9]+)s*(BC|AD){0,1}$ all parts are optional except matching 1 or more digits, so the pattern is a very broad match and is not taking any rules for zeroes or hyphens into account.

    If you want a pattern for validation, you can omit the capture groups:

    ^(?:-?[1-9]d*|[1-9]d*s*(?:AD|BC)|0)$
    

    The pattern matches:

    • ^ Start of string
    • (?: Non capture group
      • -? Match optional hyphen
      • [1-9]d* Match 1-9 and optional digits
      • | Or
      • [1-9]d*s*(?:AD|BC) Match 1-9, optional digits, optional whitespace chars and either AD or BC
      • | Or
      • 0 Match a single zero
    • ) Close the non capture group
    • $ End of string

    See a regex demo.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search