diff --git a/faker/providers/date_time/__init__.py b/faker/providers/date_time/__init__.py
index f4d2626b..3bb3c28b 100644
--- a/faker/providers/date_time/__init__.py
+++ b/faker/providers/date_time/__init__.py
@@ -26,6 +26,20 @@ def datetime_to_timestamp(dt):
     return timegm(dt.timetuple())
 
 
+def timestamp_to_datetime(timestamp, tzinfo):
+    if tzinfo is None:
+        pick = datetime.fromtimestamp(timestamp, tzlocal())
+        pick = pick.astimezone(tzutc()).replace(tzinfo=None)
+    else:
+        pick = datetime.fromtimestamp(timestamp, tzinfo)
+
+    return pick
+
+
+class ParseError(ValueError):
+    pass
+
+
 timedelta_pattern = r''
 for name, sym in [('years', 'y'), ('weeks', 'w'), ('days', 'd'), ('hours', 'h'), ('minutes', 'm'), ('seconds', 's')]:
     timedelta_pattern += r'((?P<{0}>(?:\+|-)\d+?){1})?'.format(name, sym)
@@ -316,6 +330,37 @@ class Provider(BaseProvider):
         """
         return cls.date_time().time()
 
+    @classmethod
+    def _parse_date_string(cls, value):
+        parts = cls.regex.match(value)
+        if not parts:
+            raise ParseError("Can't parse date string `{}`.".format(value))
+        parts = parts.groupdict()
+        time_params = {}
+        for (name, param) in parts.items():
+            if param:
+                time_params[name] = int(param)
+
+        if 'years' in time_params:
+            if 'days' not in time_params:
+                time_params['days'] = 0
+            time_params['days'] += 365.24 * time_params.pop('years')
+
+        if not time_params:
+            raise ParseError("Can't parse date string `{}`.".format(value))
+        return time_params
+
+    @classmethod
+    def _parse_timedelta(cls, value):
+        if isinstance(value, timedelta):
+            return value.total_seconds()
+        if is_string(value):
+            time_params = cls._parse_date_string(value)
+            return timedelta(**time_params).total_seconds()
+        if isinstance(value, (int, float)):
+            return value
+        raise ParseError("Invalid format for timedelta '{0}'".format(value))
+
     @classmethod
     def _parse_date_time(cls, text, tzinfo=None):
         if isinstance(text, (datetime, date, real_datetime, real_date)):
@@ -326,24 +371,11 @@ class Provider(BaseProvider):
         if is_string(text):
             if text == 'now':
                 return datetime_to_timestamp(datetime.now(tzinfo))
-            parts = cls.regex.match(text)
-            if not parts:
-                return
-            parts = parts.groupdict()
-            time_params = {}
-            for (name, param) in parts.items():
-                if param:
-                    time_params[name] = int(param)
-
-            if 'years' in time_params:
-                if 'days' not in time_params:
-                    time_params['days'] = 0
-                time_params['days'] += 365.24 * time_params.pop('years')
-
+            time_params = cls._parse_date_string(text)
             return datetime_to_timestamp(now + timedelta(**time_params))
         if isinstance(text, int):
             return datetime_to_timestamp(now + timedelta(text))
-        raise ValueError("Invalid format for date '{0}'".format(text))
+        raise ParseError("Invalid format for date '{0}'".format(text))
 
     @classmethod
     def date_time_between(cls, start_date='-30y', end_date='now', tzinfo=None):
@@ -552,6 +584,35 @@ class Provider(BaseProvider):
         else:
             return now
 
+    @classmethod
+    def time_series(cls, start_date='-30d', end_date='now', precision=None, distrib=None, tzinfo=None):
+        """
+        Returns a generator yielding tuples of ``(<datetime>, <value>)``.
+
+        The data points will start at ``start_date``, and be at every time interval specified by
+        ``precision``.
+        """
+        start_date = cls._parse_date_time(start_date, tzinfo=tzinfo)
+        end_date = cls._parse_date_time(end_date, tzinfo=tzinfo)
+
+        if end_date < start_date:
+            raise ValueError("`end_date` must be greater than `start_date`.")
+
+        if precision is None:
+            precision = (end_date - start_date) / 30
+        precision = cls._parse_timedelta(precision)
+
+        if distrib is None:
+            distrib = lambda: random.uniform(0, precision)  # noqa
+
+        if not callable(distrib):
+            raise ValueError("`distrib` must be a callable. Got {} instead.".format(distrib))
+
+        datapoint = start_date
+        while datapoint < end_date:
+            datapoint += precision
+            yield (timestamp_to_datetime(datapoint, tzinfo), distrib())
+
     @classmethod
     def am_pm(cls):
         return cls.date('%p')

is faking time series data in the scope of this project ?
I wanted some fake time series data for a project and couldn't find anything suitable for my needs.
Is something like [this](http://www.xaprb.com/blog/2014/01/24/methods-generate-realistic-time-series-data/) in the scope of this project ?

diff --git a/tests/factory.py b/tests/factory.py
index 62ae0377..50ce8764 100644
--- a/tests/factory.py
+++ b/tests/factory.py
@@ -64,10 +64,6 @@ class FactoryTestCase(unittest.TestCase):
             faker.get_formatter('barFormatter')
             self.assertEqual(exc.args[0], 'Unknown formatter "barFormatter" with locale "it_IT"')
 
-    def test_invalid_locale(self):
-        with self.assertRaises(AttributeError):
-            Factory.create('foo_Bar')
-
     def test_format_calls_formatter_on_provider(self):
         self.assertEqual('foobar', self.generator.format('foo_formatter'))
 
diff --git a/tests/providers/date_time.py b/tests/providers/date_time.py
index c132384e..a4d405bc 100644
--- a/tests/providers/date_time.py
+++ b/tests/providers/date_time.py
@@ -231,6 +231,51 @@ class TestDateTime(unittest.TestCase):
             datetime.now(utc).replace(second=0, microsecond=0)
         )
 
+    def test_parse_timedelta(self):
+        from faker.providers.date_time import Provider
+
+        td = timedelta(days=7)
+        seconds = Provider._parse_timedelta(td)
+        self.assertEqual(seconds, 604800.0)
+
+        seconds = Provider._parse_timedelta('+1w')
+        self.assertEqual(seconds, 604800.0)
+
+        seconds = Provider._parse_timedelta('+1y')
+        self.assertEqual(seconds, 31556736.0)
+
+        with self.assertRaises(ValueError):
+            Provider._parse_timedelta('foobar')
+
+    def test_time_series(self):
+        from faker.providers.date_time import Provider
+
+        series = [i for i in Provider.time_series()]
+        self.assertTrue(len(series), 30)
+        self.assertTrue(series[1][0] - series[0][0], timedelta(days=1))
+
+        uniform = lambda: random.uniform(0, 5)  # noqa
+        series = [i for i in Provider.time_series('now', '+1w', '+1d', uniform)]
+        self.assertTrue(len(series), 7)
+        self.assertTrue(series[1][0] - series[0][0], timedelta(days=1))
+
+        end = datetime.now() + timedelta(days=7)
+        series = [i for i in Provider.time_series('now', end, '+1d', uniform)]
+        self.assertTrue(len(series), 7)
+        self.assertTrue(series[1][0] - series[0][0], timedelta(days=1))
+
+        self.assertTrue(series[-1][0] <= end)
+
+        with self.assertRaises(ValueError):
+            [i for i in Provider.time_series('+1w', 'now', '+1d', uniform)]
+
+        with self.assertRaises(ValueError):
+            [i for i in Provider.time_series('now', '+1w', '+1d', 'uniform')]
+
+        series = [i for i in Provider.time_series('now', end, '+1d', uniform, tzinfo=utc)]
+        self.assertTrue(len(series), 7)
+        self.assertTrue(series[1][0] - series[0][0], timedelta(days=1))
+
 
 class TestPlPL(unittest.TestCase):
 

pip install -e .
parse_log_pytest
requirements.txt
pytest
3.6
tests/requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
dnspython==2.2.1
email-validator==1.3.1
-e git+https://github.com/joke2k/faker.git@c12a23f112265bf051d720a3758f9919631734ab#egg=Faker
idna==3.10
importlib-metadata==4.8.3
iniconfig==1.1.1
mock==1.0.1
packaging==21.3
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
six==1.17.0
tomli==1.2.3
typing_extensions==4.1.1
UkPostcodeParser==1.1.2
zipp==3.6.0

name: faker
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - dnspython==2.2.1
      - email-validator==1.3.1
      - idna==3.10
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - mock==1.0.1
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - six==1.17.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - ukpostcodeparser==1.1.2
      - zipp==3.6.0
prefix: /opt/conda/envs/faker

tests/providers/date_time.py::TestDateTime::test_parse_timedelta tests/providers/date_time.py::TestDateTime::test_time_series
tests/factory.py::FactoryTestCase::test_add_provider_gives_priority_to_newly_added_provider tests/factory.py::FactoryTestCase::test_binary tests/factory.py::FactoryTestCase::test_command tests/factory.py::FactoryTestCase::test_command_custom_provider tests/factory.py::FactoryTestCase::test_documentor tests/factory.py::FactoryTestCase::test_email tests/factory.py::FactoryTestCase::test_ext_word_list tests/factory.py::FactoryTestCase::test_format_calls_formatter_on_provider tests/factory.py::FactoryTestCase::test_format_transfers_arguments_to_formatter tests/factory.py::FactoryTestCase::test_get_formatter_returns_callable tests/factory.py::FactoryTestCase::test_get_formatter_returns_correct_formatter tests/factory.py::FactoryTestCase::test_get_formatter_throws_exception_on_incorrect_formatter tests/factory.py::FactoryTestCase::test_ipv4 tests/factory.py::FactoryTestCase::test_ipv6 tests/factory.py::FactoryTestCase::test_language_code tests/factory.py::FactoryTestCase::test_locale tests/factory.py::FactoryTestCase::test_magic_call_calls_format tests/factory.py::FactoryTestCase::test_magic_call_calls_format_with_arguments tests/factory.py::FactoryTestCase::test_nl_BE_ssn_valid tests/factory.py::FactoryTestCase::test_no_words_paragraph tests/factory.py::FactoryTestCase::test_no_words_sentence tests/factory.py::FactoryTestCase::test_parse_returns_same_string_when_it_contains_no_curly_braces tests/factory.py::FactoryTestCase::test_parse_returns_string_with_tokens_replaced_by_formatters tests/factory.py::FactoryTestCase::test_password tests/factory.py::FactoryTestCase::test_prefix_suffix_always_string tests/factory.py::FactoryTestCase::test_random_element tests/factory.py::FactoryTestCase::test_random_number tests/factory.py::FactoryTestCase::test_random_pyfloat tests/factory.py::FactoryTestCase::test_random_pystr_characters tests/factory.py::FactoryTestCase::test_random_sample_unique tests/factory.py::FactoryTestCase::test_slugify tests/factory.py::FactoryTestCase::test_us_ssn_valid tests/factory.py::FactoryTestCase::test_words_valueerror tests/providers/date_time.py::TestDateTime::test_date_object tests/providers/date_time.py::TestDateTime::test_date_time_between_dates tests/providers/date_time.py::TestDateTime::test_date_time_between_dates_with_tzinfo tests/providers/date_time.py::TestDateTime::test_date_time_this_period tests/providers/date_time.py::TestDateTime::test_date_time_this_period_with_tzinfo tests/providers/date_time.py::TestDateTime::test_datetime_safe tests/providers/date_time.py::TestDateTime::test_datetime_safe_new_date tests/providers/date_time.py::TestDateTime::test_datetimes_with_and_without_tzinfo tests/providers/date_time.py::TestDateTime::test_day tests/providers/date_time.py::TestDateTime::test_future_date tests/providers/date_time.py::TestDateTime::test_future_datetime tests/providers/date_time.py::TestDateTime::test_month tests/providers/date_time.py::TestDateTime::test_parse_date_time tests/providers/date_time.py::TestDateTime::test_past_date tests/providers/date_time.py::TestDateTime::test_past_datetime tests/providers/date_time.py::TestDateTime::test_time_object tests/providers/date_time.py::TestDateTime::test_timezone_conversion tests/providers/date_time.py::TestPlPL::test_day tests/providers/date_time.py::TestPlPL::test_month
faker/providers/date_time/__init__.py
faker/providers/date_time/__init__.py