Repository: joke2k/faker

Issue:
Allow the user to specify a start_datetime in addition to end_datetime in unix_time()
In addition to the `end_datetime` parameter added via PR #606 (nice work @kungfu71186) I see value in being able to generate random datetimes within a specific window -- for example, when testing behavior in response to ten-digit Unix epoch datetimes they would want to specify a start_date of `Sunday, September 9, 2001 1:46:40 AM GMT` corresponding to `1000000000`


Discussion:
I'll submit a PR for this but would appreciate feedback -- I'm a relative python noob

Resolving patch:
diff --git a/faker/providers/date_time/__init__.py b/faker/providers/date_time/__init__.py
--- a/faker/providers/date_time/__init__.py
+++ b/faker/providers/date_time/__init__.py
@@ -1172,13 +1172,15 @@ class Provider(BaseProvider):
 
     regex = re.compile(timedelta_pattern)
 
-    def unix_time(self, end_datetime=None):
+    def unix_time(self, end_datetime=None, start_datetime=None):
         """
-        Get a timestamp between January 1, 1970 and now
+        Get a timestamp between January 1, 1970 and now, unless passed
+        explicit start_datetime or end_datetime values.
         :example 1061306726
         """
+        start_datetime = self._parse_start_datetime(start_datetime)
         end_datetime = self._parse_end_datetime(end_datetime)
-        return self.generator.random.randint(0, end_datetime)
+        return self.generator.random.randint(start_datetime, end_datetime)
 
     def time_delta(self, end_datetime=None):
         """
@@ -1257,6 +1259,13 @@ def time_object(self, end_datetime=None):
         """
         return self.date_time(end_datetime=end_datetime).time()
 
+    @classmethod
+    def _parse_start_datetime(cls, value):
+        if value is None:
+            return 0
+
+        return cls._parse_date_time(value)
+
     @classmethod
     def _parse_end_datetime(cls, value):
         if value is None:


Test patch:
diff --git a/tests/providers/test_date_time.py b/tests/providers/test_date_time.py
--- a/tests/providers/test_date_time.py
+++ b/tests/providers/test_date_time.py
@@ -55,6 +55,7 @@ class TestDateTime(unittest.TestCase):
 
     def setUp(self):
         self.factory = Faker()
+        self.factory.seed(0)
 
     def assertBetween(self, date, start_date, end_date):
         self.assertTrue(date <= end_date)
@@ -365,6 +366,43 @@ def test_time_series(self):
         series = [i for i in self.factory.time_series(start_date=start, end_date=end, tzinfo=start.tzinfo)]
         self.assertEqual(series[0][0], start)
 
+    def test_unix_time(self):
+        from faker.providers.date_time import datetime_to_timestamp
+
+        for _ in range(100):
+            now = datetime.now(utc).replace(microsecond=0)
+            epoch_start = datetime(1970,1,1,tzinfo=utc)
+
+            # Ensure doubly-constrained unix_times are generated correctly
+            start_datetime = datetime(2001, 1, 1, tzinfo=utc)
+            end_datetime = datetime(2001, 1, 2, tzinfo=utc)
+
+            constrained_unix_time = self.factory.unix_time(end_datetime=end_datetime, start_datetime=start_datetime)
+
+            self.assertIsInstance(constrained_unix_time, int)
+            self.assertBetween(constrained_unix_time, datetime_to_timestamp(start_datetime), datetime_to_timestamp(end_datetime))
+
+            # Ensure relative unix_times partially-constrained by a start time are generated correctly
+            one_day_ago = datetime.today()-timedelta(days=1)
+            
+            recent_unix_time = self.factory.unix_time(start_datetime=one_day_ago)
+
+            self.assertIsInstance(recent_unix_time, int)
+            self.assertBetween(recent_unix_time, datetime_to_timestamp(one_day_ago), datetime_to_timestamp(now))
+
+            # Ensure relative unix_times partially-constrained by an end time are generated correctly
+            one_day_after_epoch_start = datetime(1970, 1, 2, tzinfo=utc)
+
+            distant_unix_time = self.factory.unix_time(end_datetime=one_day_after_epoch_start)
+            
+            self.assertIsInstance(distant_unix_time, int)
+            self.assertBetween(distant_unix_time, datetime_to_timestamp(epoch_start), datetime_to_timestamp(one_day_after_epoch_start))
+
+            # Ensure wide-open unix_times are generated correctly
+            random_unix_time = self.factory.unix_time()
+
+            self.assertIsInstance(constrained_unix_time, int)
+            self.assertBetween(constrained_unix_time, 0, datetime_to_timestamp(now))
 
 class TestPlPL(unittest.TestCase):