Repository: conan-io/conan

Issue:
[bug] ERROR: Incorrect definition of general.config_install_interval: 1s
executing the following command:
```
$ conan config set general.config_install_interval=1s
```
makes conan completely unusable, any conan command will fail:
```
$ conan config set general.config_install_interval=1h
ERROR: Incorrect definition of general.config_install_interval: 1s
$ conan create . stc/1.0.0-rc1@
ERROR: Incorrect definition of general.config_install_interval: 1s
```
and it seems like completely impossible to restore, at least from the command line.

looking at the code: https://github.com/conan-io/conan/blob/8e964922074538899de71bff068bb959fcfae6ac/conans/util/dates.py#L33
it doesn't allow seconds there, but seconds are allowed on `conan config set`, which is inconsistent...

I also don't like usage of in-house bicycle for parsing dates. I suggest to use [isodate](https://pypi.org/project/isodate/) module and its function `parse_duration`. it will be more flexible, as it will allow to use an arbitrary time intervals - e.g. not just an integral values of hours/minutes/seconds, but e.g. `1H30M` (1 hour and 30 minutes).

the new implementation may look like:
```
def timedelta_from_text(interval):
    import isodate
    interval = interval.upper()
    if not interval.startswith("PT"):
        interval = "PT" + interval
    return isodate.parse_duration(interval)
```

I also think `conan config set` command should validate value the same way (via trying `timedelta_from_text`), right now it allows arbitrary strings, e.g. the following is always successful command:
```
$ conan config set general.config_install_interval=xxx
```
(alternatively, read of config could default to 0 or infinity on parse error)
as every command reads the config, it's pretty annoying

/cc @uilianries 

<!--
  Please don't forget to update the issue title.
  Include all applicable information to help us reproduce your problem.

  To help us debug your issue please explain:
-->

### Environment Details (include every applicable attribute)
  * Operating System+version:
  * Compiler+version:
  * Conan version:
  * Python version:

### Steps to reproduce (Include if Applicable)


### Logs (Executed commands with output) (Include/Attach if Applicable)

<!--
  Your log content should be related to the bug description, it can be:
  - Conan command output
  - Server output (Artifactory, conan_server)
-->



Discussion:
Lets fix this, some inputs:
- Please do not introduce a new external dependency like isodate for just this.
- The validation of ``conan config set`` would be challenging, because different configs can have different validation, and the setting is completely agnostic of contents. Not worth the effort.
- Probably the mitigation is to invalidate the offending config, and remove it from the config file when wrong, so it is not being continuously failing.


Resolving patch:
diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py
--- a/conans/client/conf/__init__.py
+++ b/conans/client/conf/__init__.py
@@ -716,16 +716,19 @@ def get_log_level_by_name(level_name):
 
     @property
     def config_install_interval(self):
+        item = "general.config_install_interval"
         try:
-            interval = self.get_item("general.config_install_interval")
+            interval = self.get_item(item)
         except ConanException:
             return None
 
         try:
             return timedelta_from_text(interval)
         except Exception:
-            raise ConanException("Incorrect definition of general.config_install_interval: %s"
-                                 % interval)
+            self.rm_item(item)
+            raise ConanException("Incorrect definition of general.config_install_interval: {}. "
+                                 "Removing it from conan.conf to avoid possible loop error."
+                                 .format(interval))
 
     @property
     def required_conan_version(self):
diff --git a/conans/util/dates.py b/conans/util/dates.py
--- a/conans/util/dates.py
+++ b/conans/util/dates.py
@@ -31,14 +31,14 @@ def timestamp_to_str(timestamp):
 
 
 def timedelta_from_text(interval):
-    match = re.search(r"(\d+)([mhd])", interval)
+    match = re.search(r"(\d+)([smhdw])", interval)
     try:
         value, unit = match.group(1), match.group(2)
-        if unit == 'm':
-            return datetime.timedelta(minutes=float(value))
-        elif unit == 'h':
-            return datetime.timedelta(hours=float(value))
-        else:
-            return datetime.timedelta(days=float(value))
+        name = {'s': 'seconds',
+                'm': 'minutes',
+                'h': 'hours',
+                'd': 'days',
+                'w': 'weeks'}[unit]
+        return datetime.timedelta(**{name: float(value)})
     except Exception:
         raise ConanException("Incorrect time interval definition: %s" % interval)


Test patch:
diff --git a/conans/test/functional/command/config_install_test.py b/conans/test/functional/command/config_install_test.py
--- a/conans/test/functional/command/config_install_test.py
+++ b/conans/test/functional/command/config_install_test.py
@@ -8,6 +8,7 @@
 import pytest
 import six
 from mock import patch
+from parameterized import parameterized
 
 from conans.client.cache.remote_registry import Remote
 from conans.client.conf import ConanClientConfigParser
@@ -637,6 +638,7 @@ def setUp(self):
         self.folder = temp_folder(path_with_spaces=False)
         save_files(self.folder, {"conan.conf": conanconf_interval})
         self.client = TestClient()
+        self.client.save({"conanfile.txt": ""})
 
     def test_config_install_sched_file(self):
         """ Config install can be executed without restriction
@@ -685,14 +687,17 @@ def test_invalid_scheduler(self):
         self.client.run('config get general.config_install_interval', assert_error=True)
         self.assertIn("config_install_interval defined, but no config_install file", self.client.out)
 
-    def test_invalid_time_interval(self):
-        """ config_install_interval only accepts minutes, hours or days
+    @parameterized.expand([("1y",), ("2015t",), ("42",)])
+    def test_invalid_time_interval(self, internal):
+        """ config_install_interval only accepts seconds, minutes, hours, days and weeks.
         """
-        self.client.run('config set general.config_install_interval=1s')
+        self.client.run('config set general.config_install_interval={}'.format(internal))
         # Any conan invocation will fire the configuration error
         self.client.run('install .', assert_error=True)
-        self.assertIn("ERROR: Incorrect definition of general.config_install_interval: 1s",
+        self.assertIn("ERROR: Incorrect definition of general.config_install_interval: {}. "
+                      "Removing it from conan.conf to avoid possible loop error.".format(internal),
                       self.client.out)
+        self.client.run('install .')
 
     @pytest.mark.tool_git
     def test_config_install_remove_git_repo(self):