used regular expression in `format_is_iso()`
State: closed

- [x] closes #50465 (Replace xxxx with the GitHub issue number)
- [ ] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [ ] Added [type annotations](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#type-hints) to new arguments/methods/functions.
- [x] Added an entry in the latest `doc/source/whatsnew/v2.0.0.rst` file if fixing a bug or adding a new feature.

Added regular expressions in the `format_is_iso()` function 

``` python 
def format_is_iso(f: str) -> bint:
    """
    Does format match the iso8601 set that can be handled by the C parser?
    Generally of form YYYY-MM-DDTHH:MM:SS - date separator can be different
    but must be consistent.  Leading 0s in dates and times are optional.
    """
    iso_regex = \
        r"^\d{4}(-\d{2}(-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?(([+-]\d{2}:\d{2})|Z)?)?)?)?$"
    excluded_formats = ["%Y%m%d", "%Y%m", "%Y"]
    if re.match(iso_regex, f) and f not in excluded_formats:
        return True
    return False


```

Labels:
name: Datetime
description: Datetime data dtype
name: Performance
description: Memory or execution speed performance

Comments:
Oh sorry didn't read the lin,  let me fix it 
``` python 
import re

def format_is_iso(f: str) -> bool:
    """
    Does format match the iso8601 set that can be handled by the C parser?
    Generally of form YYYY-MM-DDTHH:MM:SS - date separator can be different
    but must be consistent.  Leading 0s in dates and times are optional.
    """
    iso_regex = re.compile(
        r"""
        ^                         # start of string
        \d{4}                     # match a 4-digit year
        (-\d{2})?                 # optionally match a 2-digit month
        (-\d{2})?                 # optionally match a 2-digit day
        (T\d{2}:\d{2}:\d{2}       # match time in the format "THH:MM:SS"
        (\.\d+)?                  # optionally match a decimal and fractional seconds
        ([+-]\d{2}:\d{2}|Z)?)?    # optionally match a timezone in the format "+HH:MM" or "Z"
        $                         # end of string
        """,
        re.VERBOSE,
    )
    excluded_formats = ["%Y%m%d", "%Y%m", "%Y"]
    if re.match(iso_regex, f) and f not in excluded_formats:
        return True
    return False


res = format_is_iso('2022-12-38T17:26:49Z')
print(res)

```
``` python 
        ([ -/\\.]\d{2}|\d{2})?  # optionally match a 2-digit month
        ([ -/\\.]\d{2}|\d{2})?  # optionally match a 2-digit day
        ([ T]\d{2}:\d{2}:\d{2}  # match time in the format "THH:MM:SS"

```

Added some separators regex to separate the **dates** & **time**
getting there, but it's not quite right,it's failing lots of tests




> tests are still failing
> 
> at a minimum, you need to get
> 
> ```
> pytest pandas/tests/tslibs/test_parsing.py
> ```
> 
> to pass - please make sure that this passes locally for you

Sorry about the inconvenience I didn't knew we can test this on local system 
@MarcoGorelli ran the test on the **non-regular-expression** version they are also failing. What should I do? any suggestions? 
![image](https://user-images.githubusercontent.com/72117025/209953106-1c33d2da-d2b3-4b18-abef-48d7fa24b30f.png)

did you compile the C extensions? https://pandas.pydata.org/docs/dev/development/contributing_environment.html#step-3-build-and-install-pandas
> @MarcoGorelli ran the test on the **non-regular-expression** version they are also failing. What should I do? any suggestions? ![image](https://user-images.githubusercontent.com/72117025/209953106-1c33d2da-d2b3-4b18-abef-48d7fa24b30f.png)

Hey, @MarcoGorelli didn't understand why it's `assert False == True` in all. It should compare the expected value with the result value. 
As in the file `pandas/tests/tslibs/test_parsing.py`
```python 
@pytest.mark.parametrize(
    "fmt,expected",
    [
        ("%Y %m %d %H:%M:%S", True),
        ("%Y/%m/%d %H:%M:%S", True),
        (r"%Y\%m\%d %H:%M:%S", True),
        ("%Y-%m-%d %H:%M:%S", True),
        ("%Y.%m.%d %H:%M:%S", True),
        ("%Y%m%d %H:%M:%S", True),
        ("%Y-%m-%dT%H:%M:%S", True),
        ("%Y-%m-%dT%H:%M:%S%z", True),
        ("%Y-%m-%dT%H:%M:%S%Z", False),
        ("%Y-%m-%dT%H:%M:%S.%f", True),
        ("%Y-%m-%dT%H:%M:%S.%f%z", True),
        ("%Y-%m-%dT%H:%M:%S.%f%Z", False),
        ("%Y%m%d", False),
        ("%Y%m", False),
        ("%Y", False),
        ("%Y-%m-%d", True),
        ("%Y-%m", True),
    ],
)
def test_is_iso_format(fmt, expected):
    # see gh-41047
    result = parsing.format_is_iso(fmt)
    assert result == expected
```
Wrote the code with the dates in the format of the above and checked the result with the excepted output, the result output is matching with the expected out 

```python
import re


def format_is_iso(f: str) -> bool:
    """
    Does format match the iso8601 set that can be handled by the C parser?
    Generally of form YYYY-MM-DDTHH:MM:SS - date separator can be different
    but must be consistent.  Leading 0s in dates and times are optional.
    """
    iso_regex = re.compile(
        r"""
        ^                       # start of string
        \d{4}                   # match a 4-digit year
        ([ -/\\.]\d{2}|\d{2})?  # optionally match a 2-digit month
        ([ -/\\.]\d{2}|\d{2})?  # optionally match a 2-digit day
        ([ T]\d{2}:\d{2}:\d{2}  # match time in the format "THH:MM:SS"
        (\.\d+)?                # match a decimal and fractional seconds
        ([+-]\d{2}:\d{2}|Z)?)?  # match timezone in the format "+HH:MM" or "Z"
        $                       # end of string
        """,
        re.VERBOSE,
    )

    excluded_formats = [
        r"^\d{4}\d{2}\d{2}$",  # %Y%m%d
        r"^\d{4}\d{2}$",       # %Y%m
        r"^\d{4}$",            # %Y
    ]

    if any(re.match(pattern, f) for pattern in excluded_formats):
        return False

    return bool(re.match(iso_regex, f))


dates = [
    "2022 12 29 12:34:56",
    "2022/12/29 12:34:56",
    "2022\\12\\29 12:34:56",
    "2022-12-29 12:34:56",
    "2022.12.29 12:34:56",
    "20221229 12:34:56",
    "2022-12-29T12:34:56",
    "2022-12-29T12:34:56+01:00",
    "2022-12-29T12:34:56CET",
    "2022-12-29T12:34:56.123456",
    "2022-12-29T12:34:56.123456+01:00",
    "2022-12-29T12:34:56.123456CET",
    "20221229",
    "202212",
    "2022",
    "2022-12-29",
    "2022-12"
]

for date in dates:
    res = format_is_iso(date)
    print(date, res)

```
![image](https://user-images.githubusercontent.com/72117025/209973439-4b4a94a2-f1ea-4a63-ad14-66d948a543d7.png)

But at the time of `pytest` it fails again 
does the test pass on the `main` branch? if not, then I guess that your pandas build isn't quite correct - check the installation instructions I sent earlier
> does the test pass on the `main` branch? if not, then I guess that your pandas build isn't quite correct - check the installation instructions I sent earlier

The test got passed on the main branch with the `non-regular-expression`.

then you need to fix up your regular expression 😄 
this might help https://stackoverflow.com/a/74953592/4451315
Hey the upstream got the function remove, don't know what exactly happened 
it moved to a different file, if you do a search (e.g. with `git grep`) you'll find it
> it moved to a different file, if you do a search (e.g. with `git grep`) you'll find it

`pandas/_libs/tslibs/strptime.pyx` this one?
yes
`pytest pandas/tests/tslibs/test_parsing.py`
do I still have to run this to test it locally? or has the test changed?
yes, the tests need to pass
> yes, the tests need to pass

same test or did the **test** file got changed? 
it would take you less time to check than to ask 😄 should be the same file anyway
Hey, tried this to `using the main branch format_is_iso` code, to test what the output should come, as tried on some dates formats some and valid, and some are invalid, but it's showing false in every condition, wonder how it's passing the tests if it's showing false for true input, correct me if I am wrong 

``` python 
def format_is_iso(f: str) -> bool:
     excluded_formats = ["%Y%m"]
     for date_sep in [" ", "/", "\\", "-", ".", ""]:
         for time_sep in [" ", "T"]:
             for micro_or_tz in ["", "%z", ".%f", ".%f%z"]:
                iso_fmt = f"%Y{date_sep}%m{date_sep}%d{time_sep}%H:%M:%S{micro_or_tz}"
                if iso_fmt.startswith(f) and f not in excluded_formats:
                     return True
     return False


dates = [
    "2022 12 29 12:34:56",
    "2022/12/29 12:34:56",
    "2022\\12\\29 12:34:56",
    "2022-12-29 12:34:56",
    "2022.12.29 12:34:56",
    "20221229 12:34:56",
    "2022-12-29T12:34:56",
    "2022-12-29T12:34:56+01:00",
    "2022-12-29T12:34:56CET",
    "2022-12-29T12:34:56.123456",
    "2022-12-29T12:34:56.123456+01:00",
    "2022-12-29T12:34:56.123456CET",
    "20221229",
    "202212",
    "2022",
    "2022-12-29",
    "2022-12"
]

for date in dates:
    res = format_is_iso(date)
    print(date, res)
```
the inputs to the test should be formats

https://github.com/pandas-dev/pandas/blob/502919e4b18e5d5aca584d4ebb84d663fcefffc9/pandas/tests/tslibs/test_parsing.py#L296-L315
The test got passed on the local system 
> This erroneously matches "%Y-%m %H:%M:%S", though it shouldn't (the original non-regex code, in fact, doesn't)

what about updating the exclude list like 
```python 
excluded_formats = [
        r"^%Y%m$",
        r"^%Y[/.\\ -]%m[ |T]%H:%M.*$",
        r"^%Y%m[ |T]%H:%M.*$",
]
```
I was thinking more something like
```
%Y
(?:[./\\-]?
  (?:%m
    (?:\1
      ?(:%d



      )
    )
  )
)
```
with HMS in the middle
> I was thinking more something like
> 
> ```
> %Y
> (?:[./\\-]?
>   (?:%m
>     (?:\1
>       ?(:%d
> 
> 
> 
>       )
>     )
>   )
> )
> ```
> 
> with HMS in the middle

didn't think like that, can try to work on like this.
> I was thinking more something like
> 
> ```
> %Y
> (?:[./\\-]?
>   (?:%m
>     (?:\1
>       ?(:%d
> 
> 
> 
>       )
>     )
>   )
> )
> ```
> 
> with HMS in the middle

Like this ?

```python 
    iso_regex = re.compile(
        r"""
        ^                      # start of string
        %Y
        (?:([-/ \\.]?)
          (?:%m
            (?: \1
              (?: %d
                (?: [ |T]
                  (?: %H
                    (?: \:
                      (?: %M
                        (?: \:
                          (?: %S
                            (?: %z|.%f(?:%z|Z)?
                            )?
                          )?
                        )?
                      )?
                    )?
                  )?
                )?
              )?
            )?
          )?
        )?
        $                      # end of string
        """,
        re.VERBOSE,
    )

```
Nice! you can probably simplify
```                    (?: \:
                      (?: %M
```
to something like
```
                    (?:\:%M
```
, given that the separator between %H and %M can only be `:`
> Nice! you can probably simplify
> 
> ```
>                       (?: %M
> ```
> 
> to something like
> 
> ```
>                     (?:\:%M
> ```
> 
> , given that the separator between %H and %M can only be `:`

What about this? 

```python 
    iso_regex = re.compile(
        r"""
        ^                     # start of string
        %Y                    # Year
        (?:([-/ \\.]?)%m      # month with or without separators
        (?:\1%d               # day with or without separators
        (?:[ |T]%H            # hour with separator
        (?:\:%M               # minute with separator
        (?:\:%S               # second with separator
        (?:%z|.%f(?:%z|Z)?    # timezone or fractional second
        )?)?)?)?)?)?          # optional
        $                     # end of string
        """,
        re.VERBOSE,
    )

```
Nice! If that works, it looks good to me!